commit 8a1f664443e147b2261b702b5786dbe2ada5de6a Author: Andrea Bontempi Date: Thu Oct 21 15:00:01 2021 +0200 Init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e9b46f5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.kdev4 +*/.kdev4/* +*/build/* +*/nbproject/* diff --git a/BitPattern/CMakeLists.txt b/BitPattern/CMakeLists.txt new file mode 100644 index 0000000..14846ba --- /dev/null +++ b/BitPattern/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 2.6) +project(bitpattern) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") + +add_executable(bitpattern main.cpp bitpattern.h) + +install(TARGETS bitpattern RUNTIME DESTINATION bin) diff --git a/BitPattern/bitpattern.h b/BitPattern/bitpattern.h new file mode 100644 index 0000000..7af609d --- /dev/null +++ b/BitPattern/bitpattern.h @@ -0,0 +1,47 @@ +#ifndef BITPATTERN_HPP +#define BITPATTERN_HPP + +#include +#include + +class BitPattern { + private: + + std::uint64_t expected{}; + std::uint64_t mask{}; + + public: + + template + explicit constexpr BitPattern(const char (&input)[Size]) { + + std::uint64_t cur_bit = 1; + cur_bit <<= (Size - 2); + + for (const char val : input) { + + if (val == 0) { + return; + } + + if (val == '1') { + expected |= cur_bit; + mask |= cur_bit; + } else if (val == '0') { + mask |= cur_bit; + } + + cur_bit >>= 1; + + } + + } + + template + constexpr friend bool operator==(const ValueType value, const BitPattern &pattern) { + return (value & pattern.mask) == pattern.expected; + } + +}; + +#endif diff --git a/BitPattern/main.cpp b/BitPattern/main.cpp new file mode 100644 index 0000000..845e68b --- /dev/null +++ b/BitPattern/main.cpp @@ -0,0 +1,10 @@ +#include +#include "bitpattern.h" + +int main() { + + if(0b1101010u == BitPattern("11*1**0")) { + std::cout << "Match!" << std::endl; + } + +} diff --git a/CartesianProduct/CMakeLists.txt b/CartesianProduct/CMakeLists.txt new file mode 100644 index 0000000..3a85d23 --- /dev/null +++ b/CartesianProduct/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 2.6) +project(cartesianproduct) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") + +add_executable(cartesianproduct main.cpp cartesian_product.h) + +install(TARGETS cartesianproduct RUNTIME DESTINATION bin) diff --git a/CartesianProduct/cartesian_product.h b/CartesianProduct/cartesian_product.h new file mode 100644 index 0000000..1c594a3 --- /dev/null +++ b/CartesianProduct/cartesian_product.h @@ -0,0 +1,104 @@ +#ifndef LIBCART_H +#define LIBCART_H + +#include + +template +class cartesian_product { + +friend class iterator; + +private: + TYPE_A *a; + TYPE_B *b; + +public: + + class iterator { + + private: + int count, count_a, count_b; + typename TYPE_A::iterator iterator_a; + typename TYPE_B::iterator iterator_b; + cartesian_product *cp; + + public: + + /* ITERATOR TRAITS */ + using difference_type = int; + using value_type = int; + using pointer = std::pair; + using reference = std::pair; + using iterator_category = std::input_iterator_tag; + + /* ITERATOR METHODS */ + + iterator(int count, cartesian_product* cp) : count(count), cp(cp) { + this->iterator_a = std::begin(*(cp->a)); + this->iterator_b = std::begin(*(cp->b)); + this->count_a = count / (cp->size() / cp->a->size()); + this->count_b = count % cp->b->size(); + for(int i = 0; i < this->count_a; i++) this->iterator_a++; + for(int i = 0; i < this->count_b; i++) this->iterator_b++; + } + + iterator(const iterator& mit) : iterator(mit.count, mit.cp) {} + + iterator& operator++() { + + ++count; + int new_count_a = count / (cp->size() / cp->a->size()); + this->count_b = count % cp->b->size(); + + if(this->count_a != new_count_a) { + this->iterator_a++; + this->count_a = new_count_a; + } + + if(this->count_b == 0) { + this->iterator_b = std::begin(*(cp->b)); + } else { + this->iterator_b++; + } + + return *this; + + } + + iterator operator++(int) { + iterator tmp(*this); + operator++(); + return tmp; + } + + bool operator==(const iterator& rhs) { + return count == rhs.count; + } + + bool operator!=(const iterator& rhs) { + return count != rhs.count; + } + + std::pair operator*() { + return std::make_pair(*(iterator_a), *(iterator_b)); + } + + }; + + cartesian_product(TYPE_A &a, TYPE_B &b) : a(&a) , b(&b) {} + + int size() { + return a->size() * b->size(); + } + + iterator begin() { + return iterator(0, this); + } + + iterator end() { + return iterator(this->size(), this); + } + +}; + +#endif //LIBCART_H diff --git a/CartesianProduct/main.cpp b/CartesianProduct/main.cpp new file mode 100644 index 0000000..b5f2a75 --- /dev/null +++ b/CartesianProduct/main.cpp @@ -0,0 +1,16 @@ +#include +#include +#include +#include +#include "cartesian_product.h" + +int main() { + + std::vector a = {1,2,3,4}; + std::set b = {'a','b'}; + + for(auto i : cartesian_product(a,b)) { + std::cout << "(" << i.first << ", " << i.second << ")" << std::endl; + } + +} diff --git a/DynamicMethods/dynamicMethods.cpp b/DynamicMethods/dynamicMethods.cpp new file mode 100644 index 0000000..94b58a8 --- /dev/null +++ b/DynamicMethods/dynamicMethods.cpp @@ -0,0 +1,14 @@ +#include +#include "dynamicMethods.h" + +void dynamicMethods::addMethod(std::string name, std::function param)> functionPtr) { + this->publicMethods[name] = [this, functionPtr](std::vector param){return functionPtr(this,param);}; +} + +void* dynamicMethods::callMethod(std::string name, std::vector< std::string > param) { + if(this->publicMethods.find(name) == this->publicMethods.end()) { + throw std::logic_error("Method " + name + " not found"); + } + return this->publicMethods[name](param); +} + diff --git a/DynamicMethods/dynamicMethods.h b/DynamicMethods/dynamicMethods.h new file mode 100644 index 0000000..ade0091 --- /dev/null +++ b/DynamicMethods/dynamicMethods.h @@ -0,0 +1,29 @@ +#ifndef LIBDYNMET_H +#define LIBDYNMET_H + +#include +#include +#include +#include +#include + +class dynamicMethods { + +private: + std::map)>> publicMethods; + +public: + void addMethod(std::string name, std::function param)> functionPtr); + void* callMethod(std::string name, std::vector param); + + template + T callMethod(std::string name, std::vector< std::string > param) { + if(this->publicMethods.find(name) == this->publicMethods.end()) { + throw std::logic_error("Method " + name + " not found"); + } + return reinterpret_cast(this->publicMethods[name](param)); + } + +}; + +#endif //LIBIMPLICANT_H \ No newline at end of file diff --git a/DynamicMethods/dynamicMethods.h.gch b/DynamicMethods/dynamicMethods.h.gch new file mode 100644 index 0000000..e64684d Binary files /dev/null and b/DynamicMethods/dynamicMethods.h.gch differ diff --git a/DynamicMethods/main.cpp b/DynamicMethods/main.cpp new file mode 100644 index 0000000..165a6e5 --- /dev/null +++ b/DynamicMethods/main.cpp @@ -0,0 +1,18 @@ +#include +#include +#include "dynamicMethods.h" + +using namespace std; + +void* hello (dynamicMethods *thisPtr, std::vector param) { + std::cout << "hello " << thisPtr << endl; + std::cout << "hello " << param[0] << endl; + return (void*)100; +} + +int main() { + dynamicMethods test; + test.addMethod("hello", hello); + auto res = test.callMethod("hello", {"ciao"}); + cout << "Ritorno: " << res << endl; +} diff --git a/Eratostene/CMakeLists.txt b/Eratostene/CMakeLists.txt new file mode 100644 index 0000000..754f1ac --- /dev/null +++ b/Eratostene/CMakeLists.txt @@ -0,0 +1,13 @@ +cmake_minimum_required(VERSION 2.6) +project(rangeiterator) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + +add_executable(eratostene main.cpp eratostene.cpp eratostene.h) + +set(BOOST_LIBS program_options) +find_package(Boost COMPONENTS ${BOOST_LIBS} REQUIRED) + +target_link_libraries(eratostene ${Boost_LIBRARIES}) + + +install(TARGETS eratostene RUNTIME DESTINATION bin) diff --git a/Eratostene/eratostene.cpp b/Eratostene/eratostene.cpp new file mode 100644 index 0000000..65c71c2 --- /dev/null +++ b/Eratostene/eratostene.cpp @@ -0,0 +1,43 @@ +#include +#include "eratostene.h" + +unsigned long int load_from_file(std::vector& primes, std::ifstream& file) { + unsigned long read; + while (file >> read) { + primes.push_back(read); + } + return read; +} + +void Chunk::set_multiple(unsigned long n) { + + int range_min = std::ceil((double)this->chunk_offset / n); + int range_max = std::floor((double)(this->chunk_offset + this->chunk_size - 1) / n); + + for(int i = range_min; i <= range_max; i++) { + this->chunk_table->set((n * i) - this->chunk_offset); + } + +} + +std::vector Chunk::process(const std::vector& primes) { + + this->chunk_table->reset(); + + for(auto i : primes) { + this->set_multiple(i); + } + + std::vector new_primes; + + for(int i = 0; i < this->chunk_size; i++) { + if(!this->chunk_table->test(i)) { + unsigned long new_prime = i + this->chunk_offset; + new_primes.push_back(new_prime); + this->set_multiple(new_prime); + } + } + + return new_primes; + +} diff --git a/Eratostene/eratostene.h b/Eratostene/eratostene.h new file mode 100644 index 0000000..59fb7d0 --- /dev/null +++ b/Eratostene/eratostene.h @@ -0,0 +1,43 @@ +#ifndef ERAT_H +#define ERAT_H + +#include +#include +#include + +unsigned long int load_from_file(std::vector& primes, std::ifstream& file); + +class Chunk { + +private: + + Chunk(const Chunk&) = delete; + Chunk& operator=(Chunk const&) = delete; + + boost::dynamic_bitset<>* chunk_table; + unsigned long int chunk_offset; + int chunk_size; + + void set_multiple(unsigned long int n); + +public: + + Chunk(int size, unsigned long int offset) { + this->chunk_offset = offset; + this->chunk_size = size; + this->chunk_table = new boost::dynamic_bitset<>(size, 0ul); + } + + ~Chunk() { + delete this->chunk_table; + } + + void forward() { + this->chunk_offset += this->chunk_size; + } + + std::vector process(const std::vector& primes); + +}; + +#endif //ERAT_H diff --git a/Eratostene/main.cpp b/Eratostene/main.cpp new file mode 100644 index 0000000..23e5732 --- /dev/null +++ b/Eratostene/main.cpp @@ -0,0 +1,56 @@ +#include +#include +#include "eratostene.h" + +const int CHUNK_SIZE = 100000; +const int CHUNK_NUMBER = 1; + +int main(int argc, char *argv[]) { + + boost::program_options::options_description po ("Eratostene"); + + po.add_options() + ("help,h", "Help") + ("chunk-size,s", boost::program_options::value()->default_value(CHUNK_SIZE), "Chunk size") + ("chunk-number,n", boost::program_options::value()->default_value(CHUNK_NUMBER), "Number of chunk processed in one run") + ("load,l", boost::program_options::value(), "Load file") + ; + + boost::program_options::variables_map vm; + boost::program_options::store(boost::program_options::parse_command_line(argc, argv, po), vm); + boost::program_options::notify(vm); + + if (vm.count("help")) { + std::cout << po << std::endl; + return 0; + } + + std::vector primes; + unsigned long int chunk_offset = 2; + + if(vm.count("load")) { + std::ifstream myfile; + myfile.open(vm["load"].as()); + chunk_offset = load_from_file(primes, myfile); + myfile.close(); + } + + Chunk mychunk(vm["chunk-size"].as(), chunk_offset); + + for(int counter = 0; counter < vm["chunk-number"].as(); counter++) { + + auto new_primes = mychunk.process(primes); + + primes.insert(std::end(primes), std::begin(new_primes), std::end(new_primes)); + + mychunk.forward(); + + } + + for(auto i : primes) { + std::cout << i << "\n"; + } + + return EXIT_SUCCESS; + +} diff --git a/EventManager/CMakeLists.txt b/EventManager/CMakeLists.txt new file mode 100644 index 0000000..d26bcbf --- /dev/null +++ b/EventManager/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 2.6) +project(eventmanager) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + +add_executable(eventmanager main.cpp EventManager.cpp EventManager.h) + +install(TARGETS eventmanager RUNTIME DESTINATION bin) diff --git a/EventManager/EventManager.cpp b/EventManager/EventManager.cpp new file mode 100644 index 0000000..612b6ed --- /dev/null +++ b/EventManager/EventManager.cpp @@ -0,0 +1,13 @@ +#include "EventManager.h" + +void EventManager::eventRegister(std::string eventName, std::function< void(EventInfo) > callBack) { + this->callBackList[eventName].push_back(callBack); +} + +void EventManager::eventDispatch(std::string eventName){ + EventInfo info; + info.eventName = eventName; + for(auto call : this->callBackList[eventName]) { + call(info); + } +} diff --git a/EventManager/EventManager.h b/EventManager/EventManager.h new file mode 100644 index 0000000..008bdaa --- /dev/null +++ b/EventManager/EventManager.h @@ -0,0 +1,26 @@ +#ifndef EMAN_H +#define EMAN_H + +#include +#include +#include +#include + +struct EventInfo { + + std::string eventName; + +}; + +class EventManager { + +private: + std::map>> callBackList; + +public: + void eventRegister(std::string eventName, std::function callBack); + void eventDispatch(std::string eventName); + +}; + +#endif // EMAN_H diff --git a/EventManager/main.cpp b/EventManager/main.cpp new file mode 100644 index 0000000..3e12a31 --- /dev/null +++ b/EventManager/main.cpp @@ -0,0 +1,22 @@ +#include +#include +#include + +#include "EventManager.h" + +int main(int argc, char **argv) { + + EventManager manager; + + manager.eventRegister("mioEvento", [](EventInfo info){ + std::cout << "1 - " << info.eventName << std::endl; + }); + + manager.eventRegister("mioEvento", [](EventInfo info){ + std::cout << "2 - " << info.eventName << std::endl; + }); + + manager.eventDispatch("mioEvento"); + + return 0; +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..20d40b6 --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. \ No newline at end of file diff --git a/Mandelbrot/CMakeLists.txt b/Mandelbrot/CMakeLists.txt new file mode 100644 index 0000000..5ed25f8 --- /dev/null +++ b/Mandelbrot/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.6) +project(mandelbrot) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -O2 -ffast-math -fopenmp") +set(EXECUTABLE_NAME "mandelbrot") + +add_executable(${EXECUTABLE_NAME} main.cpp functions.hpp Fractal.hpp Fractal.cpp) + +link_directories(/usr/local/lib) + +set(BOOST_LIBS program_options) +find_package(Boost COMPONENTS ${BOOST_LIBS} REQUIRED) + +target_link_libraries (${EXECUTABLE_NAME} ${Boost_LIBRARIES}) +target_link_libraries (${EXECUTABLE_NAME} sfml-window) +target_link_libraries (${EXECUTABLE_NAME} sfml-system) +target_link_libraries (${EXECUTABLE_NAME} sfml-graphics) + +install(TARGETS ${EXECUTABLE_NAME} RUNTIME DESTINATION bin) diff --git a/Mandelbrot/Fractal.cpp b/Mandelbrot/Fractal.cpp new file mode 100644 index 0000000..5ec3d69 --- /dev/null +++ b/Mandelbrot/Fractal.cpp @@ -0,0 +1,98 @@ +#include "Fractal.hpp" +#include +#include +#include + +Fractal::Fractal(int image_width, int image_height, Domain domain, std::function (std::complex, std::complex)> fractal_function, std::function render_function) : domain(domain) { + this->fractal_function = fractal_function; + this->render_function = render_function; + this->image_height = image_height; + this->image_width = image_width; + this->frame.create(image_width, image_height, sf::Color(0, 0, 0)); + this->hasChanged = true; +} + +void Fractal::setFractalFunction(std::function (std::complex, std::complex)> fractal_function) { + this->fractal_function = fractal_function; + this->hasChanged = true; +} + +void Fractal::setRenderFunction(std::function render_function) { + this->render_function = render_function; + this->hasChanged = true; +} + +int Fractal::compute_point(std::complex point, int max_iterations) { + + std::complex z(0); + int iter = 0; + + while (abs(z) < 2.0 && iter < max_iterations) { + z = this->fractal_function(z, point); + iter++; + } + + return iter; + +} + +std::complex Fractal::scale_point(std::complex point) { + std::complex aux(point.real() / (double)this->image_width * this->domain.width() + this->domain.x_min, point.imag() / (double)this->image_height * this->domain.height() + domain.y_min); + return aux; +} + +sf::Image Fractal::getFrame(){ + + if (this->hasChanged) { + + std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now(); + + int max_iterations = compute_max_iterations(this->image_width, this->domain.width()); + + #pragma omp parallel for + for(int y = 0; y < this->image_height; y++) { + for(int x = 0; x < this->image_width; x++) { + std::complex point(x, y); + point = scale_point(point); + int iterations = compute_point(point, max_iterations); + sf::Color color = this->render_function(iterations, max_iterations); + this->frame.setPixel(x, y, color); + } + } + + std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now(); + + auto t = std::chrono::duration_cast(end - start).count(); + std::cerr << "Frame> Time: " << t << "ms, Max iterations: " << max_iterations << std::endl; + + this->hasChanged = false; + } + + return this->frame; + +} + +void Fractal::moveTo(int x, int y) { + std::complex point(x, y); + point = this->scale_point(point); + this->domain.centralize(point); + this->hasChanged = true; +} + +void Fractal::moveBy(double x, double y) { + this->domain.move(x, y); + this->hasChanged = true; +} + +void Fractal::zoom(double factor, bool invert) { + this->domain.zoom((invert)?1/factor:factor); + this->hasChanged = true; +} + +int Fractal::compute_max_iterations(int window_width, double domain_width) { + int max = 50 * std::pow(std::log10(window_width / domain_width), 1.25); + return (max > 0)? max : 0; +} + + + diff --git a/Mandelbrot/Fractal.hpp b/Mandelbrot/Fractal.hpp new file mode 100644 index 0000000..225031c --- /dev/null +++ b/Mandelbrot/Fractal.hpp @@ -0,0 +1,123 @@ +#ifndef LIBFRACTAL_H +#define LIBFRACTAL_H + +#include +#include +#include +#include "functions.hpp" + +struct Domain { + + double x_min, x_max, y_min, y_max; + + Domain(double x_min, double x_max, double y_min, double y_max) : x_min(x_min), x_max(x_max), y_min(y_min), y_max(y_max) {} + + double width() { + return x_max - x_min; + } + + double height() { + return y_max - y_min; + } + + double size() { + return width() * height(); + } + + double ratio() { + return width() / height(); + } + + void setRatio(double ratio) { + double factor = (width() / ratio) / 2; + double w = (y_max + y_min) / 2; + y_min = w - factor; + y_max = w + factor; + } + + void zoom(double factor) { + + double x_frac = width() / 2; + double y_frac = height() / 2; + + double x_factor = x_frac - (x_frac * factor); + double y_factor = y_frac - (y_frac * factor); + + x_min -= x_factor; + y_min -= y_factor; + + x_max += x_factor; + y_max += y_factor; + + } + + void move(double x, double y) { + + double deltax = x * (x_max - x_min); + x_min += deltax; + x_max += deltax; + + double deltay = y * (y_max - y_min); + y_min += deltay; + y_max += deltay; + + } + + void centralize(std::complex point) { + + double x_frac = width() / 2; + double y_frac = height() / 2; + + x_min = point.real() - x_frac; + y_min = point.imag() - y_frac; + + x_max = point.real() + x_frac; + y_max = point.imag() + y_frac; + + } + +}; + +class Fractal { + +private: + + int image_width, image_height; + std::function(std::complex, std::complex)> fractal_function; + std::function render_function; + sf::Image frame; + bool hasChanged; + Domain domain; + + std::complex scale_point(std::complex point); + int compute_point(std::complex point, int max_iterations); + int compute_max_iterations(int window_width, double domain_width); + +public: + + Fractal(int image_width, + int image_height, + Domain domain, + std::function(std::complex, std::complex)> fractal_function = fractal_mandelbrot, + std::function render_function = render_smooth + ); + + void setFractalFunction(std::function(std::complex, std::complex)> fractal_function); + + void setRenderFunction(std::function render_function); + + void moveTo(int x, int y); + + void moveBy(double x, double y); + + void zoom(double factor, bool invert = false); + + sf::Image getFrame(); + + Domain& getDomain() { + return this->domain; + } + +}; + +#endif //LIBFRACTAL_H diff --git a/Mandelbrot/functions.hpp b/Mandelbrot/functions.hpp new file mode 100644 index 0000000..ac24e62 --- /dev/null +++ b/Mandelbrot/functions.hpp @@ -0,0 +1,57 @@ +#ifndef LIBFUNCTIONS_H +#define LIBFUNCTIONS_H + +#include +#include + +inline std::complex fractal_mandelbrot(std::complex z, std::complex c) { + return (z * z) + c; +} + +inline std::complex fractal_triple_mandelbrot(std::complex z, std::complex c) { + return (z * z * z) + c; +} + +inline std::complex fractal_quadruple_mandelbrot(std::complex z, std::complex c) { + return (z * z * z * z) + c; +} + +inline std::complex fractal_quintuple_mandelbrot(std::complex z, std::complex c) { + return (z * z * z * z * z) + c; +} + +inline sf::Color render_linear(int iteration_number, int max_iterations) { + int N = 256; // colors per element + int N3 = N * N * N; + double t = (double)iteration_number/(double)max_iterations; + // expand n on the 0 .. 256^3 interval (integers) + iteration_number = (int)(t * (double) N3); + + int b = iteration_number/(N * N); + int nn = iteration_number - b * N * N; + int r = nn/N; + int g = nn - r * N; + return sf::Color(r, g, b); +} + +inline sf::Color render_smooth(int iteration_number, int max_iterations) { + double t = (double)iteration_number/(double)max_iterations; + // Use smooth polynomials for r, g, b + int r = (int)(9*(1-t)*t*t*t*255); + int g = (int)(15*(1-t)*(1-t)*t*t*255); + int b = (int)(8.5*(1-t)*(1-t)*(1-t)*t*255); + return sf::Color(r, g, b); +} + +inline sf::Color render_black_and_white(int iteration_number, int max_iterations) { + double t = (double)iteration_number/(double)max_iterations; + return (t != 1)? sf::Color(0, 0, 0) : sf::Color(255, 255, 255); +} + +inline sf::Color render_green_gradient(int iteration_number, int max_iterations) { + double t = (double)iteration_number/(double)max_iterations; + if(t == 1) return sf::Color(0, 0, 0); + return (t > 0.5)? sf::Color(t*255, 255, t*255) : sf::Color(0, t*255, 0); +} + +#endif //LIBFUNCTIONS_H diff --git a/Mandelbrot/main.cpp b/Mandelbrot/main.cpp new file mode 100644 index 0000000..0a61694 --- /dev/null +++ b/Mandelbrot/main.cpp @@ -0,0 +1,234 @@ +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "functions.hpp" +#include "Fractal.hpp" + +const double DOMAIN_X_MIN = -2.0; +const double DOMAIN_X_MAX = 2.0; +const double DOMAIN_Y_MIN = -1.7; +const double DOMAIN_Y_MAX = 1.7; +const int IMAGE_WIDTH = 1920; +const int IMAGE_HEIGHT = 1080; +const int FRAMERATE = 20; + +int main(int argc, char **argv) { + + boost::program_options::options_description po ("Mandelbrot"); + + po.add_options() + ("help", "Help") + ("noratio", "Don't force the window ratio on domain") + ("framerate", boost::program_options::value()->default_value(FRAMERATE), "Framerate") + ("width", boost::program_options::value()->default_value(IMAGE_WIDTH), "Window width") + ("height", boost::program_options::value()->default_value(IMAGE_HEIGHT), "Window height") + ("domXmin", boost::program_options::value()->default_value(DOMAIN_X_MIN), "Domain X (Min)") + ("domXmax", boost::program_options::value()->default_value(DOMAIN_X_MAX), "Domain X (Max)") + ("domYmin", boost::program_options::value()->default_value(DOMAIN_Y_MIN), "Domain Y (Min)") + ("domYmax", boost::program_options::value()->default_value(DOMAIN_Y_MAX), "Domain Y (Max)") + ("filename", boost::program_options::value(), "Filename") + ; + + boost::program_options::variables_map vm; + boost::program_options::store(boost::program_options::parse_command_line(argc, argv, po), vm); + boost::program_options::notify(vm); + + if (vm.count("help")) { + std::cout << po << std::endl; + return 0; + } + + int screen_width = vm["width"].as(); + int screen_height = vm["height"].as(); + + double windowRatio = (double)screen_width / (double)screen_height; + + Fractal mandelbrot( + screen_width, + screen_height, + Domain( + vm["domXmin"].as(), + vm["domXmax"].as(), + vm["domYmin"].as(), + vm["domYmax"].as() + ) + ); + + if(!vm.count("noratio")){ + std::cerr << "Force ratio " << windowRatio << std::endl; + mandelbrot.getDomain().setRatio(windowRatio); + } + + if(vm.count("filename")) { + mandelbrot.getFrame().saveToFile(vm["filename"].as()); + std::cerr << "Screenshot stored in file " << vm["filename"].as() << std::endl; + return 0; + } + + sf::RenderWindow window(sf::VideoMode(screen_width, screen_height), "Mandelbrot"); + window.setFramerateLimit(vm["framerate"].as()); + + sf::Texture texture; + sf::Sprite sprite; + + while (window.isOpen()) { + + sf::Event event; + while (window.pollEvent(event)) { + + switch (event.type) { + + case sf::Event::Closed: + window.close(); + break; + + case sf::Event::MouseButtonReleased: { + + sf::Vector2i mousePosition = sf::Mouse::getPosition(window); + + switch (event.mouseButton.button) { + + case sf::Mouse::Left: + mandelbrot.moveTo(mousePosition.x, mousePosition.y); + break; + + case sf::Mouse::Right: + mandelbrot.moveTo(mousePosition.x, mousePosition.y); + break; + + default: + break; + + } + + } + break; + + case sf::Event::MouseWheelMoved: + + if(event.mouseWheel.delta > 0) { + mandelbrot.zoom(1.05); + } else { + mandelbrot.zoom(1.05, true); + } + + break; + + + case sf::Event::KeyPressed: + switch (event.key.code) { + + case sf::Keyboard::Escape: + window.close(); + break; + + case sf::Keyboard::Key::Add: + mandelbrot.zoom(1.5); + break; + + case sf::Keyboard::Key::Subtract: + mandelbrot.zoom(1.5, true); + break; + + case sf::Keyboard::Key::Right: + mandelbrot.moveBy(0.01, 0); + break; + + case sf::Keyboard::Key::Left: + mandelbrot.moveBy(-0.01, 0); + break; + + case sf::Keyboard::Key::Up: + mandelbrot.moveBy(0, -0.01); + break; + + case sf::Keyboard::Key::Down: + mandelbrot.moveBy(0, 0.01); + break; + + case sf::Keyboard::Key::S: { + std::time_t t = std::time(nullptr); + std::tm tm = *std::localtime(&t); + std::stringstream filename; + filename << "Screenshot_" << std::put_time(&tm, "%Y%m%d%H%M%S") << ".jpeg"; + mandelbrot.getFrame().saveToFile(filename.str()); + std::cerr << "Screenshot stored in file " << filename.str() << std::endl; + } + break; + + case sf::Keyboard::Key::D: { + std::cerr << std::scientific << std::setprecision(10) << "domXmin=" << mandelbrot.getDomain().x_min << ", domXmax=" << mandelbrot.getDomain().x_max << ", domYmin=" << mandelbrot.getDomain().y_min << ", domYmax=" << mandelbrot.getDomain().y_max << std::endl; + } + break; + + // Renderer selection + case sf::Keyboard::Key::Q: + std::cerr << "Selected smooth renderer" << std::endl; + mandelbrot.setRenderFunction(render_smooth); + break; + + case sf::Keyboard::Key::W: + std::cerr << "Selected linear renderer" << std::endl; + mandelbrot.setRenderFunction(render_linear); + break; + + case sf::Keyboard::Key::E: + std::cerr << "Selected black&white renderer" << std::endl; + mandelbrot.setRenderFunction(render_black_and_white); + break; + + case sf::Keyboard::Key::R: + std::cerr << "Selected green gradient renderer" << std::endl; + mandelbrot.setRenderFunction(render_green_gradient); + break; + + // Fractal selection + case sf::Keyboard::Key::Num1: + std::cerr << "Selected mandelbrot algorithm" << std::endl; + mandelbrot.setFractalFunction(fractal_mandelbrot); + break; + + case sf::Keyboard::Key::Num2: + std::cerr << "Selected triple mandelbrot algorithm" << std::endl; + mandelbrot.setFractalFunction(fractal_triple_mandelbrot); + break; + + case sf::Keyboard::Key::Num3: + std::cerr << "Selected quadruple mandelbrot algorithm" << std::endl; + mandelbrot.setFractalFunction(fractal_quadruple_mandelbrot); + break; + + case sf::Keyboard::Key::Num4: + std::cerr << "Selected quintuple mandelbrot algorithm" << std::endl; + mandelbrot.setFractalFunction(fractal_quintuple_mandelbrot); + break; + + default: + break; + + } + + default: + break; + + } + } + + window.clear(sf::Color::Black); + texture.loadFromImage(mandelbrot.getFrame()); + sprite.setTexture(texture); + window.draw(sprite); + window.display(); + + } + + return 0; + +} diff --git a/MultiType/CMakeLists.txt b/MultiType/CMakeLists.txt new file mode 100644 index 0000000..dd0a25c --- /dev/null +++ b/MultiType/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 2.6) +project(multitype) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + +add_executable(multitype main.cpp MultiType.cpp MultiType.h) + +install(TARGETS multitype RUNTIME DESTINATION bin) diff --git a/MultiType/MultiType.cpp b/MultiType/MultiType.cpp new file mode 100644 index 0000000..619eb53 --- /dev/null +++ b/MultiType/MultiType.cpp @@ -0,0 +1,28 @@ +#include "MultiType.h" + +Node::Node() { + this->myType = Type::NIL; +} + +Node::~Node() +{ + +} + +Type Node::getTypeFromHash(const std::type_info& hash) { + + if(hash == typeid(char)) { + return Type::CHAR; + } else if(hash == typeid(int)) { + return Type::INT; + } else if(hash == typeid(double)) { + return Type::DOUBLE; + } else if(hash == typeid(bool)) { + return Type::BOOL; + } else if(hash == typeid(std::string)) { + return Type::STRING; + } else { + throw new std::logic_error("Type error"); + } + +} diff --git a/MultiType/MultiType.h b/MultiType/MultiType.h new file mode 100644 index 0000000..8d67a1a --- /dev/null +++ b/MultiType/MultiType.h @@ -0,0 +1,87 @@ +#ifndef MULTI_H +#define MULTI_H + +#include +#include +#include + +enum Type { NIL, CHAR, INT, DOUBLE, BOOL, STRING }; + +class Node { + +private: + // TYPE TAG + Type myType; + + // DATA + union { + char c; + int i; + double d; + bool b; + }; + + Type getTypeFromHash(const std::type_info &hash); + +public: + + Node(); + ~Node(); + + template + TYPE getData() { + + if(this->getTypeFromHash(typeid(TYPE)) != this->myType) { + throw new std::logic_error("Type error"); + } + + switch(this->myType) { + case Type::CHAR: + return c; + break; + case Type::INT: + return i; + break; + case Type::DOUBLE: + return d; + break; + case Type::BOOL: + return b; + break; + default: + throw new std::logic_error("Type error"); + } + + } + + template + void setData(TYPE data) { + + if(this->myType != Type::NIL && this->myType != this->getTypeFromHash(typeid(TYPE))) { + throw new std::logic_error("Type error"); + } + + this->myType = this->getTypeFromHash(typeid(TYPE)); + + switch(this->myType) { + case Type::CHAR: + c = data; + break; + case Type::INT: + i = data; + break; + case Type::DOUBLE: + d = data; + break; + case Type::BOOL: + b = data; + break; + default: + throw new std::logic_error("Type error"); + } + + } + +}; + +#endif // MULTI_H diff --git a/MultiType/main.cpp b/MultiType/main.cpp new file mode 100644 index 0000000..187bd27 --- /dev/null +++ b/MultiType/main.cpp @@ -0,0 +1,24 @@ +#include +#include +#include + +#include "MultiType.h" + +int main(int argc, char **argv) { + + Node test; + + test.setData(10.1); + + std::cout << test.getData() << std::endl; + + test.setData(20.2); + + std::cout << test.getData() << std::endl; + + test.setData(3); + + std::cout << test.getData() << std::endl; + + return 0; +} diff --git a/PoolAllocator/CMakeLists.txt b/PoolAllocator/CMakeLists.txt new file mode 100644 index 0000000..539afc0 --- /dev/null +++ b/PoolAllocator/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.1) +project(poolallocator) +set (CMAKE_CXX_STANDARD 17) + +add_executable(poolallocator main.cpp PoolAllocator.h) + +install(TARGETS poolallocator RUNTIME DESTINATION bin) diff --git a/PoolAllocator/PoolAllocator.h b/PoolAllocator/PoolAllocator.h new file mode 100644 index 0000000..c838b42 --- /dev/null +++ b/PoolAllocator/PoolAllocator.h @@ -0,0 +1,67 @@ +#ifndef POOL_H +#define POOL_H + +#include +#include + +template +class PoolAllocator { + +private: + + template + union alloc_t { + Q type; + alloc_t* next; + }; + + alloc_t* _pool = nullptr; + alloc_t* _head = nullptr; + +public: + + PoolAllocator() { + + // Allocate pool + + _pool = (alloc_t*) malloc((DIM * sizeof(alloc_t))+1); + _head = _pool; + + // Init free list + + for(int i = 0; i < DIM; i++) { + _pool[i].next = &_pool[i+1]; + } + + _pool[DIM].next = nullptr; + + } + + ~PoolAllocator() { + free(_pool); + } + + T* allocate() { + if(_head->next == nullptr) throw std::bad_alloc(); + alloc_t* pointer = _head; + _head = pointer->next; + std::cout << "Allocated " << pointer << std::endl; + return (T*) pointer; + } + + void deallocate(T* p) { + alloc_t* pointer = (alloc_t*) p; + pointer->next = _head; + _head = pointer; + std::cout << "Deallocated " << p << std::endl; + } + + void dump() { + for(int i = 0; i < DIM; i++) { + std::cout << "[" << (T*) &_pool[i] << "] " << (T) _pool[i].type << std::endl; + } + } + +}; + +#endif // POOL_H diff --git a/PoolAllocator/main.cpp b/PoolAllocator/main.cpp new file mode 100644 index 0000000..7fb4fa0 --- /dev/null +++ b/PoolAllocator/main.cpp @@ -0,0 +1,33 @@ +#include +#include + +#include "PoolAllocator.h" + +int main(int argc, char **argv) { + + PoolAllocator pool; + + std::cout << "Test allocate..." << std::endl; + + int* i = pool.allocate(); + int* j = pool.allocate(); + + *i = 1; + *j = 2; + + std::cout << "Test dump..." << std::endl; + pool.dump(); + + std::cout << "Test deallocate..." << std::endl; + pool.deallocate(i); + pool.deallocate(j); + + std::cout << "Test bad alloc..." << std::endl; + + for(int i = 0; i < 11; i++) { + pool.allocate(); + } + + return 0; + +} diff --git a/Quaternion/CMakeLists.txt b/Quaternion/CMakeLists.txt new file mode 100644 index 0000000..9f3d6ad --- /dev/null +++ b/Quaternion/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 2.6) +project(quaternion) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") + +find_package(Boost COMPONENTS unit_test_framework system REQUIRED) +include_directories (${Boost_INCLUDE_DIRS}) + +add_executable(quaternion_example example.cpp Quaternion.h) + +add_executable(quaternion_test test.cpp Quaternion.h) + +target_link_libraries(quaternion_test ${Boost_LIBRARIES}) + +add_test(NAME quaternion_test WORKING_DIRECTORY ${PROJECT_BINARY_DIR} COMMAND ${PROJECT_BINARY_DIR}/quaternion_test) + +enable_testing() diff --git a/Quaternion/Quaternion.h b/Quaternion/Quaternion.h new file mode 100644 index 0000000..9b8012f --- /dev/null +++ b/Quaternion/Quaternion.h @@ -0,0 +1,437 @@ +/* + * Copyright © 2019 Andrea Bontempi All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * - Neither the name of Andrea Bontempi nor the names of its contributors may be used to + * endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef QUATER_H +#define QUATER_H + +#include +#include +#include +#include + +constexpr double PI = 3.14159265358979323846; + +template +class Quaternion { + +private: + + T n, ni, nj, nk; + +public: + + using value_type = T; ///< value_type trait for STL compatibility + + /** + * Default constuctor + */ + Quaternion(const T& n = static_cast(0), const T& ni = static_cast(0), const T& nj = static_cast(0), const T& nk = static_cast(0)) + : n(n), ni(ni), nj(nj), nk(nk) {} + + /** + * Specialized constructor for std::complex + */ + Quaternion(const std::complex& complex_a, const std::complex& complex_b = std::complex(static_cast(0), static_cast(0))) + : n(complex_a.real()), ni(complex_a.imag()), nj(complex_b.real()), nk(complex_b.imag()) {} + + /** + * Copy constructor + */ + template + Quaternion(const Quaternion& rhs) + : n(rhs.a()), ni(rhs.b()), nj(rhs.c()), nk(rhs.d()) {} + + /** + * Default copy assignment operator + */ + template + Quaternion& operator=(const Quaternion& rhs) { + this->n = rhs.a(); + this->ni = rhs.b(); + this->nj = rhs.c(); + this->nk = rhs.d(); + } + + /** + * Specialized copy assignment operator for std::complex + */ + template + Quaternion& operator=(const std::complex rhs) { + this->n = rhs.real(); + this->ni = rhs.imag(); + this->nj = static_cast(0); + this->nk = static_cast(0); + } + + T a() const { + return this->n; + } + + T b() const { + return this->ni; + } + + T c() const { + return this->nj; + } + + T d() const { + return this->nk; + } + + T w() const { + return this->n; + } + + T x() const { + return this->ni; + } + + T y() const { + return this->nj; + } + + T z() const { + return this->nk; + } + + std::complex complex_a() const { + return {this->n, this->ni}; + } + + std::complex complex_b() const { + return {this->nj, this->nk}; + } + + T real() const { + return this->n; + } + + Quaternion unreal() const { + return {static_cast(0), this->ni, this->nj, this->nk}; + } + +}; + +namespace std { + + /** + * Norm of quaternion + */ + template + T norm(const Quaternion& quat) { + return (quat.a() * quat.a()) + (quat.b() * quat.b()) + (quat.c() * quat.c()) + (quat.d() * quat.d()); + } + + /** + * Implementation of abs with float sqrt + */ + float abs(const Quaternion& quat) { + return std::sqrt(std::norm(quat)); + } + + /** + * Implementation of abs with double sqrt + */ + double abs(const Quaternion& quat) { + return std::sqrt(std::norm(quat)); + } + + /** + * Implementation of abs with long double sqrt + */ + long double abs(const Quaternion& quat) { + return std::sqrt(std::norm(quat)); + } + + /** + * The conjugate of quaternion + */ + template + Quaternion conj(const Quaternion& quat) { + return {quat.a(), quat.b() * -1, quat.c() * -1, quat.d() * -1}; + } + + /** + * Is not a number? + */ + template + bool isnan(Quaternion quat) { + return std::isnan(quat.a()) || std::isnan(quat.b()) || std::isnan(quat.c()) || std::isnan(quat.d()); + } + + /** + * Is infinite? + */ + template + bool isinf(Quaternion quat) { + return std::isinf(quat.a()) || std::isinf(quat.b()) || std::isinf(quat.c()) || std::isinf(quat.d()); + } + + /** + * Is finite? + */ + template + bool isfinite(Quaternion quat) { + return std::isfinite(quat.a()) && std::isfinite(quat.b()) && std::isfinite(quat.c()) && std::isfinite(quat.d()); + } + +} + +/** + * Add operator between two quaternios. + */ +template +auto operator+(const Quaternion<_tA>& lhs, const Quaternion<_tB>& rhs) -> Quaternion { + return {lhs.a() + rhs.a(), lhs.b() + rhs.b(), lhs.c() + rhs.c(), lhs.d() + rhs.d()}; +} + +/** + * Add operator between quaternion and std::complex. + */ +template +auto operator+(const Quaternion<_tA>& lhs, const std::complex<_tB>& rhs) -> Quaternion { + return {lhs.a() + rhs.real(), lhs.b() + rhs.imag(), lhs.c(), lhs.d()}; +} + +/** + * Add operator between std::complex and quaternion. + */ +template +auto operator+(const std::complex<_tB>& lhs, const Quaternion<_tA>& rhs) -> Quaternion { + return operator+(rhs, lhs); +} + +/** + * Add operator between quaternion and scalar. + */ +template +auto operator+(const Quaternion<_tA>& lhs, const _tB& rhs) -> Quaternion { + return {lhs.a() + rhs, lhs.b(), lhs.c(), lhs.d()}; +} + +/** + * Add operator between scalar and quaternion. + */ +template +auto operator+(const _tA& lhs, const Quaternion<_tB>& rhs) -> Quaternion { + return operator+(rhs, lhs); +} + +/** + * Sub operator between two quaternions. + */ +template +auto operator-(const Quaternion<_tA>& lhs, const Quaternion<_tB>& rhs) -> Quaternion { + return {lhs.a() - rhs.a(), lhs.b() - rhs.b(), lhs.c() - rhs.c(), lhs.d() - rhs.d()}; +} + +/** + * Sub operator between quaternion and std:complex. + */ +template +auto operator-(const Quaternion<_tA>& lhs, const std::complex<_tB>& rhs) -> Quaternion { + return {lhs.a() - rhs.real(), lhs.b() - rhs.imag(), lhs.c(), lhs.d()}; +} + +/** + * Sub operator between std:complex and quaternion. + */ +template +auto operator-(const std::complex<_tB>& lhs, const Quaternion<_tA>& rhs) -> Quaternion { + return {lhs.real() - rhs.a(), lhs.imag() - rhs.b(), -rhs.c(), -rhs.d()}; +} + +/** + * Sub operator between quaternion and scalar. + */ +template +auto operator-(const Quaternion<_tA>& lhs, const _tB& rhs) -> Quaternion { + return {lhs.a() - rhs, lhs.b(), lhs.c(), lhs.d()}; +} + +/** + * Sub operator between scalar and quaternion. + */ +template +auto operator-(const _tA& lhs, const Quaternion<_tB>& rhs) -> Quaternion { + return {lhs - rhs.a(), -rhs.b(), -rhs.c(), -rhs.d()}; +} + +/** + * Mul operator between two quaternions. + */ +template +auto operator*(const Quaternion<_tA>& lhs, const Quaternion<_tB>& rhs) -> Quaternion { + decltype(lhs.a() * rhs.a()) tn = (lhs.a() * rhs.a()) - (lhs.b() * rhs.b()) - (lhs.c() * rhs.c()) - (lhs.d() * rhs.d()); + decltype(lhs.a() * rhs.a()) tni = (lhs.a() * rhs.b()) + (lhs.b() * rhs.a()) + (lhs.c() * rhs.d()) - (lhs.d() * rhs.c()); + decltype(lhs.a() * rhs.a()) tnj = (lhs.a() * rhs.c()) + (lhs.c() * rhs.a()) + (lhs.d() * rhs.b()) - (lhs.b() * rhs.d()); + decltype(lhs.a() * rhs.a()) tnk = (lhs.a() * rhs.d()) + (lhs.d() * rhs.a()) + (lhs.b() * rhs.c()) - (lhs.c() * rhs.b()); + return {tn, tni, tnj, tnk}; +} + +/** + * Mul operator between quaternion and std:complex. + */ +template +auto operator*(const Quaternion<_tA>& lhs, const std::complex<_tB>& rhs) -> Quaternion { + decltype(lhs.a() * rhs.real()) tn = (lhs.a() * rhs.real()) - (lhs.b() * rhs.imag()); + decltype(lhs.a() * rhs.real()) tni = (lhs.a() * rhs.imag()) + (lhs.b() * rhs.real()); + decltype(lhs.a() * rhs.real()) tnj = (lhs.c() * rhs.real()) + (lhs.d() * rhs.imag()); + decltype(lhs.a() * rhs.real()) tnk = (lhs.d() * rhs.real()) - (lhs.c() * rhs.imag()); + return {tn, tni, tnj, tnk}; +} + +/** + * Mul operator between std:complex and quaternion. + */ +template +auto operator*(const std::complex<_tB>& lhs, const Quaternion<_tA>& rhs) -> Quaternion { + decltype(lhs.real() * rhs.a()) tn = (lhs.real() * rhs.a()) - (lhs.imag() * rhs.b()); + decltype(lhs.real() * rhs.a()) tni = (lhs.real() * rhs.b()) + (lhs.imag() * rhs.a()); + decltype(lhs.real() * rhs.a()) tnj = (lhs.real() * rhs.c()) - (lhs.imag() * rhs.d()); + decltype(lhs.real() * rhs.a()) tnk = (lhs.real() * rhs.d()) + (lhs.imag() * rhs.c()); + return {tn, tni, tnj, tnk}; +} + +/** + * Mul operator between quaternion and scalar. + */ +template +auto operator*(const Quaternion<_tA>& lhs, const _tB& rhs) -> Quaternion { + return {lhs.a() * rhs, lhs.b() * rhs, lhs.c() * rhs, lhs.d() * rhs}; +} + +/** + * Mul operator between scalar and quaternion. + */ +template +auto operator*(const _tA& lhs, const Quaternion<_tB>& rhs) -> Quaternion { + return operator*(rhs, lhs); +} + +/** + * Div operator between two quaternions. + */ +template +auto operator/(const Quaternion<_tA>& lhs, const Quaternion<_tB>& rhs) -> Quaternion { + decltype(lhs.a() * rhs.a()) tn = (lhs.a() * rhs.a()) + (lhs.b() * rhs.b()) + (lhs.c() * rhs.c()) + (lhs.d() * rhs.d()); + decltype(lhs.a() * rhs.a()) tni = - (lhs.a() * rhs.b()) + (lhs.b() * rhs.a()) - (lhs.c() * rhs.d()) + (lhs.d() * rhs.c()); + decltype(lhs.a() * rhs.a()) tnj = - (lhs.a() * rhs.c()) + (lhs.c() * rhs.a()) - (lhs.d() * rhs.b()) + (lhs.b() * rhs.d()); + decltype(lhs.a() * rhs.a()) tnk = - (lhs.a() * rhs.d()) + (lhs.d() * rhs.a()) - (lhs.b() * rhs.c()) + (lhs.c() * rhs.b()); + decltype(rhs.a()) norm = std::norm(rhs); + return {tn / norm, tni / norm, tnj / norm, tnk / norm}; +} + +/** + * Div operator between quaternion and scalar. + */ +template +auto operator/(const Quaternion<_tA>& lhs, const _tB& rhs) -> Quaternion { + return {lhs.a() / rhs, lhs.b() / rhs, lhs.c() / rhs, lhs.d() / rhs}; +} + +/** + * Div operator between scalar and quaternion. + */ +template +auto operator/(const _tB& lhs, const Quaternion<_tA>& rhs) -> Quaternion { + decltype(rhs.a()) norm = std::norm(rhs); + return {(rhs.a() * lhs) / norm, -(rhs.b() * lhs) / norm, -(rhs.c() * lhs) / norm, -(rhs.d() * lhs) / norm}; +} + +/** + * Trivial comparison operator between quaternions. + */ +template +bool operator==(const _tA& lhs, const _tB& rhs) { + return lhs.a() == rhs.a() && lhs.b() == rhs.b() && lhs.c() == rhs.c() && lhs.d() == rhs.d(); +} + +/** + * Stream operator for quaternion. + */ +template +std::ostream& operator<< (std::ostream& os, const Quaternion& obj) { + os << "(" << obj.a() << "," << obj.b() << "," << obj.c() << "," << obj.d() << ")"; + return os; +} + +/** + * Normalization function + */ +template +auto normalized(const Quaternion& quat) -> Quaternion { + return quat / std::abs(quat); +} + +/** + * Inverse function + */ +template +auto inverse(const Quaternion& quat) { + return std::conj(quat) / std::norm(quat); +} + +/** + * Euler angles (radiants in ZYX order) to Quaternion conversion + */ +template +Quaternion euler_to_quaternion(T roll, T pitch, T yaw) { + T cy = std::cos(yaw / 2); + T sy = std::sin(yaw / 2); + T cp = std::cos(pitch / 2); + T sp = std::sin(pitch / 2); + T cr = std::cos(roll / 2); + T sr = std::sin(roll / 2); + T tn = cy * cp * cr + sy * sp * sr; + T tni = cy * cp * sr - sy * sp * cr; + T tnj = sy * cp * sr + cy * sp * cr; + T tnk = sy * cp * cr - cy * sp * sr; + return {tn, tni, tnj, tnk}; +} + +/** + * Quaternion to euler angles (radiants in ZYX order) conversion + */ +template +std::tuple quaternion_to_euler(Quaternion quat) { + T sinr_cosp = +2.0 * (quat.w() * quat.x() + quat.y() * quat.z()); + T cosr_cosp = +1.0 - 2.0 * (quat.x() * quat.x() + quat.y() * quat.y()); + T roll = std::atan2(sinr_cosp, cosr_cosp); + T sinp = +2.0 * (quat.w() * quat.y() - quat.z() * quat.x()); + T pitch = (std::fabs(sinp) >= 1)? std::copysign(PI / 2, sinp) : std::asin(sinp); + T siny_cosp = +2.0 * (quat.w() * quat.z() + quat.x() * quat.y()); + T cosy_cosp = +1.0 - 2.0 * (quat.y() * quat.y() + quat.z() * quat.z()); + T yaw = std::atan2(siny_cosp, cosy_cosp); + return {roll, pitch, yaw}; +} + +#endif // QUATER_H diff --git a/Quaternion/example.cpp b/Quaternion/example.cpp new file mode 100644 index 0000000..f192f84 --- /dev/null +++ b/Quaternion/example.cpp @@ -0,0 +1,69 @@ +#include +#include "Quaternion.h" + +int main(int argc, char **argv) { + + Quaternion a(1,0,1,0); + Quaternion b(1,0.5,0.5,0.75); + Quaternion c(3,0.5,1.5,0.75); + + std::complex ca(1,2); + std::complex cb(3,4); + + std::cout << "Real part of " << a << " is " << a.real() << std::endl; + + std::cout << "Unreal part of " << b << " is " << b.unreal() << std::endl; + + std::cout << "Component of " << a << " is " << a.a() << ", " << a.b() << ", " << a.c() << ", " << a.d() << std::endl; + + std::cout << "Norm of " << a << " is " << std::norm(a) << std::endl; + + std::cout << "Modulus of " << c << " is " << std::abs(c) << std::endl; + + std::cout << "Conjugate of " << b << " is " << std::conj(b) << std::endl; + + std::cout << "Normalization of " << b << " is " << normalized(b) << std::endl; + + std::cout << "Inverse of " << b << " is " << inverse(b) << std::endl; + + std::cout << a << " + " << b << " = " << a + b << std::endl; + + std::cout << a << " + " << 3 << " = " << a + 3 << std::endl; + + std::cout << b << " + complex " << ca << " = " << b + ca << std::endl; + + std::cout << a << " - " << b << " = " << a - b << std::endl; + + std::cout << a << " * " << b << " = " << a * b << std::endl; + + std::cout << a << " * " << 2.2 << " = " << a * 2.2 << std::endl; + + std::cout << a << " / " << b << " = " << a / b << std::endl; + + std::cout << a << " / " << 2.2 << " = " << a / 2.2 << std::endl; + + std::cout << 2.2 << " / " << b << " = " << 2.2 / b << std::endl; + + Quaternion component (ca,cb); + + std::cout << "Construct quaternion from complex " << ca << " and " << cb << " = " << component << std::endl; + + std::cout << "Quaternion " << component << " has complex component " << component.complex_a() << " and " << component.complex_b() << std::endl; + + Quaternion conversion = euler_to_quaternion(-1.14159, 0.141593, 0.858407); + + std::cout << "Convert Euler angles [roll = -1.14159, pitch = 0.141593, yaw = 0.858407] to quaternion: " << conversion << std::endl; + + auto [roll, pitch, yaw] = quaternion_to_euler(conversion); + + std::cout << "Convert quaternion " << conversion << " back to Euler angles: [roll = " << roll << ", pitch = "<< pitch <<", yaw = "<< yaw <<"]" << std::endl; + + std::cout << a << " is NaN? " << std::boolalpha << std::isnan(a) << std::endl; + + std::cout << a << " is infinite? " << std::boolalpha << std::isinf(a) << std::endl; + + std::cout << a << " is finite? " << std::boolalpha << std::isfinite(a) << std::endl; + + return 0; + +} diff --git a/Quaternion/test.cpp b/Quaternion/test.cpp new file mode 100644 index 0000000..0cfb067 --- /dev/null +++ b/Quaternion/test.cpp @@ -0,0 +1,218 @@ +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE "Quaternion tests" + +#include + +#include +#include "Quaternion.h" +#include //VERY IMPORTANT - include this last + + +/** + * Comparison operator for test + */ + +const double epsilon = 1e-05; + +bool operator==(const Quaternion& lhs, const Quaternion& rhs) { + bool check_a = std::abs(lhs.a() - rhs.a()) <= ((std::abs(lhs.a()) < std::abs(rhs.a()) ? std::abs(rhs.a()) : std::abs(lhs.a())) * epsilon); + bool check_b = std::abs(lhs.b() - rhs.b()) <= ((std::abs(lhs.b()) < std::abs(rhs.b()) ? std::abs(rhs.b()) : std::abs(lhs.b())) * epsilon); + bool check_c = std::abs(lhs.c() - rhs.c()) <= ((std::abs(lhs.c()) < std::abs(rhs.c()) ? std::abs(rhs.c()) : std::abs(lhs.c())) * epsilon); + bool check_d = std::abs(lhs.d() - rhs.d()) <= ((std::abs(lhs.d()) < std::abs(rhs.d()) ? std::abs(rhs.d()) : std::abs(lhs.d())) * epsilon); + return check_a && check_b && check_c && check_d; +} + +bool compare_double(const double& a, const double& b) { + return std::abs(a - b) <= ((std::abs(a) < std::abs(b) ? std::abs(b) : std::abs(a)) * epsilon); + +} + +/** CONSTRUCTION OF A QUATERNION **/ + +BOOST_AUTO_TEST_CASE(quaternion_costruction_from_components) { + Quaternion test(0.1,0.5,0.9,1); + BOOST_CHECK_EQUAL(test.a(), 0.1); + BOOST_CHECK_EQUAL(test.b(), 0.5); + BOOST_CHECK_EQUAL(test.c(), 0.9); + BOOST_CHECK_EQUAL(test.d(), 1); +} + +BOOST_AUTO_TEST_CASE(quaternion_costruction_from_complex) { + std::complex a(0.1,0.5); + std::complex b(0.9,1); + Quaternion test(a,b); + BOOST_CHECK_EQUAL(test.complex_a(), a); + BOOST_CHECK_EQUAL(test.complex_b(), b); +} + +BOOST_AUTO_TEST_CASE(quaternion_costruction_from_copy) { + Quaternion a(0.1,0.5,0.9,1); + Quaternion b(a); + BOOST_CHECK_EQUAL(a, b); +} + +/** UNARY OPERATORS **/ + +BOOST_AUTO_TEST_CASE(quaternion_conjugation) { + Quaternion a(0.1,0.5,0.9,1); + Quaternion b(0.1,-0.5,-0.9,-1); + BOOST_CHECK_EQUAL(std::conj(a), b); +} + +BOOST_AUTO_TEST_CASE(quaternion_norm) { + Quaternion a(0.1,0.5,0.9,1); + double b = 2.07000; + BOOST_CHECK_EQUAL(compare_double(std::norm(a), b), true); +} + +BOOST_AUTO_TEST_CASE(quaternion_abs) { + Quaternion a(0.1,0.5,0.9,1); + double b = 1.43875; + BOOST_CHECK_EQUAL(compare_double(std::abs(a), b), true); +} + +BOOST_AUTO_TEST_CASE(quaternion_normalization) { + Quaternion a(0.1,0.5,0.9,1); + Quaternion b(0.0695048,0.347524,0.625543,0.695048); + BOOST_CHECK_EQUAL(normalized(a), b); +} + +BOOST_AUTO_TEST_CASE(quaternion_inversion) { + Quaternion a(0.1,0.5,0.9,1); + Quaternion b(0.0483092,-0.241546,-0.434783,-0.483092); + BOOST_CHECK_EQUAL(inverse(a), b); +} + +/** BINARY OPERATOR: SUM **/ + +BOOST_AUTO_TEST_CASE(sum_between_quaternions) { + Quaternion a(0.1,0.5,0.9,1); + Quaternion b(0.9,0.5,0.1,0); + Quaternion c(1,1,1,1); + BOOST_CHECK_EQUAL(a + b, c); +} + +BOOST_AUTO_TEST_CASE(sum_between_scalar_and_quaternion) { + double a = 1; + Quaternion b(0.9,0.5,0.1,0); + Quaternion c(1.9,0.5,0.1,0); + BOOST_CHECK_EQUAL(a + b, c); +} + +BOOST_AUTO_TEST_CASE(sum_between_quaternion_and_scalar) { + Quaternion a(0.9,0.5,0.1,0); + double b = 1; + Quaternion c(1.9,0.5,0.1,0); + BOOST_CHECK_EQUAL(a + b, c); +} + +BOOST_AUTO_TEST_CASE(sum_between_complex_and_quaternion) { + std::complex a (1,1); + Quaternion b(0.9,0.5,0.1,0); + Quaternion c(1.9,1.5,0.1,0); + BOOST_CHECK_EQUAL(a + b, c); +} + +BOOST_AUTO_TEST_CASE(sum_between_quaternion_and_complex) { + Quaternion a(0.9,0.5,0.1,0); + std::complex b (1,1); + Quaternion c(1.9,1.5,0.1,0); + BOOST_CHECK_EQUAL(a + b, c); +} + +/** BINARY OPERATOR: DIFFERENCE **/ + +BOOST_AUTO_TEST_CASE(difference_between_quaternions) { + Quaternion a(1,1,1,1); + Quaternion b(0.1,0.5,0.9,1); + Quaternion c(0.9,0.5,0.1,0); + BOOST_CHECK_EQUAL(a - b, c); +} + +BOOST_AUTO_TEST_CASE(difference_between_scalar_and_quaternion) { + double a = 1; + Quaternion b(0.9,0.5,0.1,0); + Quaternion c(0.1,-0.5,-0.1,0); + BOOST_CHECK_EQUAL(a - b, c); +} + +BOOST_AUTO_TEST_CASE(difference_between_quaternion_and_scalar) { + Quaternion a(0.9,0.5,0.1,0); + double b = 1; + Quaternion c(-0.1,0.5,0.1,0); + BOOST_CHECK_EQUAL(a - b, c); +} + +BOOST_AUTO_TEST_CASE(difference_between_complex_and_quaternion) { + std::complex a (1,1); + Quaternion b(0.9,0.5,0.1,0); + Quaternion c(0.1,0.5,-0.1,0); + BOOST_CHECK_EQUAL(a - b, c); +} + +BOOST_AUTO_TEST_CASE(difference_between_quaternion_and_complex) { + Quaternion a(0.9,0.5,0.1,0); + std::complex b (1,1); + Quaternion c(-0.1,-0.5,0.1,0); + BOOST_CHECK_EQUAL(a - b, c); +} + +/** BINARY OPERATOR: MULTIPLICATION **/ + +BOOST_AUTO_TEST_CASE(multiplication_between_quaternions) { + Quaternion a(-1,1,-1,1); + Quaternion b(0.1,0.5,0.9,1); + Quaternion c(-0.7,-2.3,-1.5,0.5); + BOOST_CHECK_EQUAL(a * b, c); +} + +BOOST_AUTO_TEST_CASE(multiplication_between_scalar_and_quaternion) { + double a = 2; + Quaternion b(0.1,0.5,0.9,1); + Quaternion c(0.2,1,1.8,2); + BOOST_CHECK_EQUAL(a * b, c); +} + +BOOST_AUTO_TEST_CASE(multiplication_between_quaternion_and_scalar) { + Quaternion a(0.1,0.5,0.9,1); + double b = 2; + Quaternion c(0.2,1,1.8,2); + BOOST_CHECK_EQUAL(a * b, c); +} + +BOOST_AUTO_TEST_CASE(multiplication_between_complex_and_quaternion) { + std::complex a (1,1); + Quaternion b(0.1,0.5,0.9,1); + Quaternion c(-0.4,0.6,-0.1,1.9); + BOOST_CHECK_EQUAL(a * b, c); +} + +BOOST_AUTO_TEST_CASE(multiplication_between_quaternion_and_complex) { + Quaternion a(0.1,0.5,0.9,1); + std::complex b (1,1); + Quaternion c(-0.4,0.6,1.9,0.1); + BOOST_CHECK_EQUAL(a * b, c); +} + +/** BINARY OPERATOR: DIVISION **/ + +BOOST_AUTO_TEST_CASE(division_between_quaternions) { + Quaternion a(-1,1,-1,1); + Quaternion b(0.1,0.5,0.9,1); + Quaternion c(0.241546,1.207729,0.628019,-0.144928); + BOOST_CHECK_EQUAL(a / b, c); +} + +BOOST_AUTO_TEST_CASE(division_between_scalar_and_quaternion) { + double a = 2; + Quaternion b(0.1,0.5,0.9,1); + Quaternion c(0.0966184,-0.483092,-0.869565,-0.966184); + BOOST_CHECK_EQUAL(a / b, c); +} + +BOOST_AUTO_TEST_CASE(division_between_quaternion_and_scalar) { + Quaternion a(-1,1,-1,1); + double b = 2; + Quaternion c(-0.5,0.5,-0.5,0.5); + BOOST_CHECK_EQUAL(a / b, c); +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..b39a47f --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +CppExperiments +============== + +This is a collection of demos written in C ++, it isn't code suitable for use in projects. diff --git a/RangeIterator/CMakeLists.txt b/RangeIterator/CMakeLists.txt new file mode 100644 index 0000000..9598809 --- /dev/null +++ b/RangeIterator/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 2.6) +project(rangeiterator) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + +add_executable(rangeiterator main.cpp RangeIterator.cpp RangeIterator.h) + +install(TARGETS rangeiterator RUNTIME DESTINATION bin) diff --git a/RangeIterator/RangeIterator.cpp b/RangeIterator/RangeIterator.cpp new file mode 100644 index 0000000..4c9f5fa --- /dev/null +++ b/RangeIterator/RangeIterator.cpp @@ -0,0 +1,23 @@ +#include "RangeIterator.h" + +Range::Range(int a, int b) { + + if(a < b) { + this->startn = a; + this->endn = b; + } else { + this->startn = b; + this->endn = a; + } + +} + + +Range::MyIterator Range::begin() { + return MyIterator(this->startn); +} + +Range::MyIterator Range::end() { + return MyIterator(this->endn); + +} diff --git a/RangeIterator/RangeIterator.h b/RangeIterator/RangeIterator.h new file mode 100644 index 0000000..a69c31a --- /dev/null +++ b/RangeIterator/RangeIterator.h @@ -0,0 +1,33 @@ +#ifndef RANGEITER_H +#define RANGEITER_H + +#include + +class Range { + +private: + int startn, endn; + +public: + + class MyIterator : public std::iterator { + private: + int n; + public: + MyIterator(int x) :n(x) {} + MyIterator(const MyIterator& mit) : n(mit.n) {} + MyIterator& operator++() {++n;return *this;} + MyIterator operator++(int) {MyIterator tmp(*this); operator++(); return tmp;} + bool operator==(const MyIterator& rhs) {return this->n == rhs.n;} + bool operator!=(const MyIterator& rhs) {return this->n != rhs.n;} + int operator*() {return n;} + }; + + // Metodi Range + Range(int a, int b = 0); + MyIterator begin(); + MyIterator end(); + +}; + +#endif // RANGEITER_H diff --git a/RangeIterator/main.cpp b/RangeIterator/main.cpp new file mode 100644 index 0000000..aa29786 --- /dev/null +++ b/RangeIterator/main.cpp @@ -0,0 +1,14 @@ +#include +#include +#include + +#include "RangeIterator.h" + +int main(int argc, char **argv) { + + for(int i : Range(10)) { + std::cout << i << std::endl; + } + + return 0; +} diff --git a/SpMatrix/CMakeLists.txt b/SpMatrix/CMakeLists.txt new file mode 100644 index 0000000..5c7af8a --- /dev/null +++ b/SpMatrix/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.7) +project(rangeiterator) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + +add_executable(spmatrix main.cpp SpMatrix.h) + +install(TARGETS spmatrix RUNTIME DESTINATION bin) diff --git a/SpMatrix/SpMatrix.h b/SpMatrix/SpMatrix.h new file mode 100644 index 0000000..59e96bd --- /dev/null +++ b/SpMatrix/SpMatrix.h @@ -0,0 +1,91 @@ +#ifndef SPMATRIX_H +#define SPMATRIX_H + +#include +#include +#include +#include +#include + +struct Coordinate { + + int x,y; + + Coordinate(int x1, int y1) { + x = x1; + y = y1; + } + + int getUID() const { + int times = 10; + if(y != 0) { + times = (int)pow(10.0, (double)((int)log10((double)y)) + 1.0); + } + return x * times + y; + } + + + bool operator< ( const Coordinate &r ) const { + return getUID() < r.getUID(); + } + +}; + +template +class SpMatrix { + +private: + std::map dataset; + Coordinate max; + +public: + SpMatrix(std::initializer_list> list) : max(0,0) { + int x1 = 0; + int y1 = 0; + for(std::vector xVec: list) { + for(T yVec: xVec) { + Coordinate mIndex(x1, y1); + dataset[mIndex] = yVec; + y1++; + } + if (y1 > max.y) max.y = y1; + y1 = 0; + x1++; + } + max.x = x1; + } + + T at(Coordinate mIndex) { + if (dataset.find(mIndex) == dataset.end()) { + return ZERO; + } + return dataset[mIndex]; + } + + T at(int x1, int y1) { + Coordinate mIndex(x1, y1); + return at(mIndex); + } + + std::string getStr() { + std::stringstream output; + for(int x1 = 0; x1 < max.x; x1++) { + for(int y1 = 0; y1 < max.y; y1++) { + output << at(x1, y1) << " "; + } + output << std::endl; + } + return output.str(); + } + + inline int getX() { + return max.x; + } + + inline int getY(){ + return max.y; + } + +}; + +#endif // SPMATRIX_H diff --git a/SpMatrix/main.cpp b/SpMatrix/main.cpp new file mode 100644 index 0000000..7271f77 --- /dev/null +++ b/SpMatrix/main.cpp @@ -0,0 +1,16 @@ +#include + +#include "SpMatrix.h" + +int main(int argc, char **argv) { + + SpMatrix test = { + {1,2}, + {3,4,5} + }; + + std::cout << "(" << test.getX() << "," << test.getY() << ")" << std::endl; + std::cout << test.getStr() << std::endl; + + return 0; +} diff --git a/Sudoku/CMakeLists.txt b/Sudoku/CMakeLists.txt new file mode 100644 index 0000000..149805c --- /dev/null +++ b/Sudoku/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 2.6) +project(sudoku) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") + +add_executable(sudoku main.cpp sudoku.cpp sudoku.h) + +install(TARGETS sudoku RUNTIME DESTINATION bin) + diff --git a/Sudoku/main.cpp b/Sudoku/main.cpp new file mode 100644 index 0000000..d91355b --- /dev/null +++ b/Sudoku/main.cpp @@ -0,0 +1,31 @@ +#include +#include "sudoku.h" + +int main () { + + sudoku schema = { + {0,0,5,0,0,0,0,0,0}, + {0,0,2,4,0,1,0,7,0}, + {3,0,4,0,0,0,5,6,0}, + {0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,7,9,8,4}, + {8,0,0,0,9,0,0,1,0}, + {0,0,0,2,0,0,1,0,0}, + {0,9,0,0,7,0,0,0,2}, + {0,1,8,3,0,0,0,4,0} + }; + + std::cout << schema << std::endl; + + std::cout << "Is valid? " << std::boolalpha << schema.check() << std::endl; + + std::cout << "Solution..." << std::endl; + + if(schema.solve()) { + std::cout << schema << std::endl; + } else { + std::cout << "No solution found!" << std::endl; + } + +} + diff --git a/Sudoku/sudoku.cpp b/Sudoku/sudoku.cpp new file mode 100644 index 0000000..cc728b6 --- /dev/null +++ b/Sudoku/sudoku.cpp @@ -0,0 +1,124 @@ +#include +#include "sudoku.h" + +sudoku::sudoku() { + for(int y = 0; y < 9; ++y) { + for(int x = 0; x < 9; ++x) { + board[y][x] = 0; + } + } +} + +sudoku::sudoku(const sudoku& ref) { + board = ref.board; +} + +sudoku::sudoku(std::initializer_list> list) { + int y = 0; + for(auto sublist : list) { + int x = 0; + for(auto i : sublist) { + board[y][x] = i; + ++x; + } + for(;x < 9; ++x) { + board[y][x] = 0; + } + ++y; + } + for(; y < 9; ++y) { + for(int x = 0; x < 9; ++x) { + board[y][x] = 0; + } + } +} + + +bool sudoku::check() { + + + // Check row + for(int i = 0; i < 9; ++i) { + if(!check_subset(iterate_row(board, 0, i), iterate_row(board, 9, i))) return false; + } + + // Check column + for(int i = 0; i < 9; ++i) { + if(!check_subset(iterate_column(board, i, 0), iterate_column(board, i, 9))) return false; + } + + // Check subgrid + for(int i = 0; i < 9; ++i) { + if(!check_subset(iterate_subgrid(board, (i%3)*3, (i/3)*3), iterate_subgrid(board, 9, 9))) return false; + } + + return true; + +} + +bool sudoku::is_safe(int x, int y, int candidate) +{ + return check_subset(iterate_row(board, 0, y), iterate_row(board, 9, y), candidate) && + check_subset(iterate_column(board, x, 0), iterate_column(board, x, 9), candidate) && + check_subset(iterate_subgrid(board, x - x % 3, y - y % 3), iterate_subgrid(board, 9, 9), candidate); +} + +std::tuple sudoku::get_first_free_cell() +{ + + for(int y = 0; y < 9; ++y) { + for(int x = 0; x < 9; ++x) { + if(board[y][x] == 0) return {x, y}; + } + } + + return {9, 9}; + +} + + +bool sudoku::solve() { + + auto [x, y] = this->get_first_free_cell(); + + if(x == 9 && y == 9) return true; + + for (int candidate = 1; candidate <= 9; candidate++) { + if (is_safe(x, y, candidate)) { + board[y][x] = candidate; + if (solve()) return true; + board[y][x] = 0; + } + } + + return false; + +} + +std::ostream& operator<< ( std::ostream& os, sudoku& obj ) +{ + int x = 0, y = 0; + for ( sudoku::iterate_sudoku it = obj.begin(); it != obj.end(); ++it ) { + if(*it == 0) { + os << ". "; + }else { + os << *it << " "; + } + if ( x == 8 ) { + x = 0; + ++y; + if ( y != 9 ) { + os << std::endl; + if ( y % 3 == 0 ) { + os << std::endl; + } + } + } else { + ++x; + if ( x % 3 == 0 ) { + os << " "; + } + } + } + return os; +} diff --git a/Sudoku/sudoku.h b/Sudoku/sudoku.h new file mode 100644 index 0000000..a0533e1 --- /dev/null +++ b/Sudoku/sudoku.h @@ -0,0 +1,113 @@ +#ifndef LIBSUDOKU_H +#define LIBSUDOKU_H + +#include +#include +#include +#include + +class sudoku { + +private: + + std::array, 9> board; + +public: + + class iterate_sudoku : public std::iterator { + + protected: + std::array, 9> &ref; + int x, y; + + public: + + iterate_sudoku(std::array, 9> &ref, int x, int y) : ref(ref), x(x), y(y) {} + iterate_sudoku(const iterate_sudoku& mit) : ref(mit.ref), x(mit.x), y(mit.y) {} + iterate_sudoku& operator++() { + if(x == 8) { + x = 0; + ++y; + } else { + ++x; + } + return *this; + } + bool operator==(const iterate_sudoku& rhs) {return x==rhs.x && y==rhs.y;} + bool operator!=(const iterate_sudoku& rhs) {return x!=rhs.x || y!=rhs.y;} + int& operator*() {return ref[y][x];} + + }; + + iterate_sudoku begin() {return iterate_sudoku(board, 0, 0);} + iterate_sudoku end() {return iterate_sudoku(board, 0, 9);} + + sudoku(); + + sudoku(const sudoku& ref); + + sudoku(std::initializer_list> list); + + bool check(); + + bool is_safe(int x, int y, int candidate); + + bool solve(); + +private: + + class iterate_row : public iterate_sudoku { + public: + iterate_row(std::array, 9> &ref, int x, int y) : iterate_sudoku(ref, x, y) {} + iterate_row& operator++() {++x;return *this;} + + }; + + class iterate_column : public iterate_sudoku { + public: + iterate_column(std::array, 9> &ref, int x, int y) : iterate_sudoku(ref, x, y) {} + iterate_column& operator++() {++y;return *this;} + + }; + + class iterate_subgrid : public iterate_sudoku { + public: + iterate_subgrid(std::array, 9> &ref, int x, int y) : iterate_sudoku(ref, x, y) {} + iterate_subgrid& operator++() { + ++x; + if(x % 3 == 0) { + x -= 3; + ++y; + if(y % 3 == 0) { + x = 9; + y = 9; + } + } + return *this; + } + }; + + template + bool check_subset(iterate_sudoku start, iterate_sudoku end, int candidate = 0) { + + std::array count; + std::fill(std::begin(count), std::end(count), false); + if(candidate != 0) count[candidate-1] = true; + + for (iterate_sudoku it = start; it != end; ++it) { + if(*it == 0) continue; + if(count[(*it)-1]) return false; + count[(*it)-1] = true; + } + + return true; + + } + + std::tuple get_first_free_cell(); + +}; + +std::ostream& operator<< (std::ostream& os, sudoku& obj); + +#endif //LIBCART_H diff --git a/ThreadPool/CMakeLists.txt b/ThreadPool/CMakeLists.txt new file mode 100644 index 0000000..c49e184 --- /dev/null +++ b/ThreadPool/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 2.6) +project(threadpool) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + +add_executable(threadpool main.cpp ThreadPool.cpp ThreadPool.h) + +find_package (Threads) +target_link_libraries (threadpool ${CMAKE_THREAD_LIBS_INIT}) + +install(TARGETS threadpool RUNTIME DESTINATION bin) diff --git a/ThreadPool/ThreadPool.cpp b/ThreadPool/ThreadPool.cpp new file mode 100644 index 0000000..239a66e --- /dev/null +++ b/ThreadPool/ThreadPool.cpp @@ -0,0 +1,67 @@ +#include "ThreadPool.h" + +#include +#include + +ThreadPool::ThreadPool(int thread_number) : quit_signal(false){ + + for(int i = 0; i < thread_number; i++) { + std::unique_ptr myThread(new std::thread(&ThreadPool::worker, this)); + this->thread_list.push_back(std::move(myThread)); + std::stringstream a; + a << "[" << this->thread_list.back()->get_id() << "] CREO" << std::endl; + std::cout << a.str(); + } + +} + +ThreadPool::~ThreadPool() { + + this->quit_signal.store(true); + this->cvar_signal.notify_all(); + + for(auto const& i : this->thread_list) { + std::stringstream a; + a << "[" << i->get_id() << "] ESCO" << std::endl; + std::cout << a.str(); + i->join(); + } + +} + +void ThreadPool::addJob(std::function job) { + std::lock_guard lock(add_lock); + this->jobs.push(job); // Aggiungo la funzione alla coda + this->cvar_signal.notify_all(); // Notifico ai thread di eseguirla. +} + +void ThreadPool::worker() { + + // Ciclo di esecuzione + for(;;) { + + std::function func; + + // Scope zona critica + { + std::unique_lock lck(this->add_lock); + + // Ciclo di attesa + for(;;) { + if(this->quit_signal.load()) return; // Segnale uscita + if(!this->jobs.empty()) break; // Ho qualcosa da eseguire + this->cvar_signal.wait(lck); // Attendo segnale + } + + // Estraggo funzione da coda + func = this->jobs.front(); + this->jobs.pop(); + + } + + // Chiamo funzione + func(); + + } + +} diff --git a/ThreadPool/ThreadPool.h b/ThreadPool/ThreadPool.h new file mode 100644 index 0000000..9f593a1 --- /dev/null +++ b/ThreadPool/ThreadPool.h @@ -0,0 +1,30 @@ +#ifndef THREADPOOL_H +#define THREADPOOL_H + +#include +#include +#include +#include +#include +#include +#include +#include + +class ThreadPool { + +private: + std::queue> jobs; + std::list> thread_list; + std::atomic quit_signal; + std::mutex add_lock; + std::condition_variable cvar_signal; + void worker(); + +public: + ThreadPool(int thread_number); + ~ThreadPool(); + void addJob(std::function job); + +}; + +#endif // THREADPOOL_H diff --git a/ThreadPool/main.cpp b/ThreadPool/main.cpp new file mode 100644 index 0000000..4ad5fbd --- /dev/null +++ b/ThreadPool/main.cpp @@ -0,0 +1,23 @@ +#include +#include +#include + +#include "ThreadPool.h" + +int main(int argc, char **argv) { + + ThreadPool test(2); + + for(int i = 0; i < 10; i++) { + test.addJob([i](){ + std::this_thread::sleep_for(std::chrono::seconds(1)); + std::stringstream a; + a << "[" << std::this_thread::get_id() << "] Eseguo job " << i << std::endl; + std::cout << a.str(); + }); + } + + std::this_thread::sleep_for(std::chrono::seconds(10)); + + return 0; +} diff --git a/TopologicalSorting/CMakeLists.txt b/TopologicalSorting/CMakeLists.txt new file mode 100644 index 0000000..e1427d5 --- /dev/null +++ b/TopologicalSorting/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 2.0) +project(topologicalsorting) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + +add_executable(topsorting main.cpp TopologicalSorting.h TopologicalSorting.cpp) + +install(TARGETS topsorting RUNTIME DESTINATION bin) + diff --git a/TopologicalSorting/TopologicalSorting.cpp b/TopologicalSorting/TopologicalSorting.cpp new file mode 100644 index 0000000..a07a69e --- /dev/null +++ b/TopologicalSorting/TopologicalSorting.cpp @@ -0,0 +1,66 @@ +#include "TopologicalSorting.h" +#include +#include +#include +#include +#include + +void DependencyTree::insertDependency(int item, int dep) { + + tree[item].insert(dep); + + if(tree.find(dep) == std::end(tree)) { + tree[dep]; + } + +} + +void DependencyTree::resolver(std::vector& resolved, std::set& unresolved, int item) { + + // Insert item into unresolved set + unresolved.insert(item); + + for(auto &dep : tree[item]) { + + if (std::find(std::begin(resolved), std::end(resolved), dep) == std::end(resolved)) { + + if (unresolved.find(dep) == std::end(unresolved)) { + + // Resolve dependencies + resolver(resolved, unresolved, dep); + + } else { + + // Error! + std::stringstream error; + error << "Found circular dependency! [" << item << " -> " << dep << "]"; + throw std::runtime_error(error.str()); + + } + + } + + } + + // Item resolved! + if (std::find(std::begin(resolved), std::end(resolved), item) == std::end(resolved)) { + resolved.push_back(item); + } + + // Remove item from unresolved set + unresolved.erase(item); + +} + +std::vector DependencyTree::getOrder() { + + std::vector resolved = {}; + std::set unresolved = {}; + + for(auto &i : boost::adaptors::keys(tree)) { + resolver(resolved, unresolved, i); + } + + return resolved; + +} diff --git a/TopologicalSorting/TopologicalSorting.h b/TopologicalSorting/TopologicalSorting.h new file mode 100644 index 0000000..79eb6a6 --- /dev/null +++ b/TopologicalSorting/TopologicalSorting.h @@ -0,0 +1,24 @@ +#ifndef TOPSORTING_H +#define TOPSORTING_H + +#include +#include +#include + +class DependencyTree { + +private: + + std::map> tree; + + void resolver(std::vector &resolved, std::set &unresolved, int item); + +public: + + void insertDependency(int item, int dep); + + std::vector getOrder(); + +}; + +#endif // TOPSORTING_H diff --git a/TopologicalSorting/main.cpp b/TopologicalSorting/main.cpp new file mode 100644 index 0000000..0a97324 --- /dev/null +++ b/TopologicalSorting/main.cpp @@ -0,0 +1,17 @@ +#include +#include "TopologicalSorting.h" + +int main() { + + DependencyTree a; + + a.insertDependency(1,2); + a.insertDependency(1,3); + a.insertDependency(2,4); + a.insertDependency(3,4); + + for(auto &i : a.getOrder()) { + std::cout << i << std::endl; + } + +} diff --git a/TraceAllocator/CMakeLists.txt b/TraceAllocator/CMakeLists.txt new file mode 100644 index 0000000..ed40951 --- /dev/null +++ b/TraceAllocator/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 2.6) +project(rangeiterator) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + +add_executable(traceallocator main.cpp TraceAllocator.h) + +install(TARGETS traceallocator RUNTIME DESTINATION bin) diff --git a/TraceAllocator/TraceAllocator.h b/TraceAllocator/TraceAllocator.h new file mode 100644 index 0000000..0ff1d30 --- /dev/null +++ b/TraceAllocator/TraceAllocator.h @@ -0,0 +1,31 @@ +#ifndef TRACEALLO_H +#define TRACEALLO_H + +#include +#include +#include + +class TraceAllocator; + +std::list pointer_list = {}; + +class TraceAllocator { + +public: + + static void* operator new(std::size_t size) throw(std::bad_alloc) { + void* pointer = ::operator new(size); + pointer_list.push_back(static_cast(pointer)); + std::cout << "Allocati " << size << " byte all'indirizzo " << std::hex << pointer << std::endl; + return pointer; + } + + static void operator delete(void *pointer) throw() { + ::operator delete(pointer); + pointer_list.remove(static_cast(pointer)); + std::cout << "Deallocato l'indirizzo " << std::hex << pointer << std::endl; + } + +}; + +#endif // TRACEALLO_H diff --git a/TraceAllocator/main.cpp b/TraceAllocator/main.cpp new file mode 100644 index 0000000..31a5f2b --- /dev/null +++ b/TraceAllocator/main.cpp @@ -0,0 +1,24 @@ +#include +#include +#include +#include + +#include "TraceAllocator.h" + +int main(int argc, char **argv) { + + auto a = std::unique_ptr(new TraceAllocator); + auto b = new TraceAllocator; + + for(auto i : pointer_list) { + std::cout << "Pointer: " << std::hex << i << std::endl; + } + + delete b; + + for(auto i : pointer_list) { + std::cout << "Pointer: " << std::hex << i << std::endl; + } + + return 0; +}