diff options
author | cathook <b01902109@csie.ntu.edu.tw> | 2014-04-19 16:21:17 +0800 |
---|---|---|
committer | cathook <b01902109@csie.ntu.edu.tw> | 2014-04-19 16:21:17 +0800 |
commit | e9a16c4ef0ea782d7db8d788c455ea946eaab039 (patch) | |
tree | 5728aa2076a13079f0ff7f162cfd4cab95e1db91 | |
download | meow-e9a16c4ef0ea782d7db8d788c455ea946eaab039.tar.gz meow-e9a16c4ef0ea782d7db8d788c455ea946eaab039.tar.zst meow-e9a16c4ef0ea782d7db8d788c455ea946eaab039.zip |
init
-rw-r--r-- | Makefile | 23 | ||||
-rw-r--r-- | README.asciidoc | 37 | ||||
-rwxr-xr-x | _test/meowpp | bin | 0 -> 410859 bytes | |||
-rw-r--r-- | _test/meowpp.cpp | 59 | ||||
-rw-r--r-- | description.asciidoc | 1 | ||||
-rw-r--r-- | meowpp/Usage.h | 96 | ||||
-rw-r--r-- | meowpp/Usage.hpp | 297 | ||||
-rw-r--r-- | meowpp/colors/HSL.h | 64 | ||||
-rw-r--r-- | meowpp/colors/HSL.hpp | 137 | ||||
-rw-r--r-- | meowpp/colors/HSV.h | 69 | ||||
-rw-r--r-- | meowpp/colors/HSV.hpp | 131 | ||||
-rw-r--r-- | meowpp/colors/RGB.h | 66 | ||||
-rw-r--r-- | meowpp/colors/RGB.hpp | 73 | ||||
-rw-r--r-- | meowpp/colors/YUV.h | 59 | ||||
-rw-r--r-- | meowpp/colors/YUV.hpp | 85 | ||||
-rw-r--r-- | meowpp/dsa/DisjointSet.h | 32 | ||||
-rw-r--r-- | meowpp/dsa/DisjointSet.hpp | 52 | ||||
-rw-r--r-- | meowpp/dsa/Heaps.h | 84 | ||||
-rw-r--r-- | meowpp/dsa/KD_Tree.h | 75 | ||||
-rw-r--r-- | meowpp/dsa/KD_Tree.hpp | 196 | ||||
-rw-r--r-- | meowpp/dsa/MergeableHeap.hpp | 146 | ||||
-rw-r--r-- | meowpp/dsa/SplayTree.h | 103 | ||||
-rw-r--r-- | meowpp/dsa/SplayTree.hpp | 505 | ||||
-rw-r--r-- | meowpp/oo/Register_Implement.h | 33 | ||||
-rw-r--r-- | meowpp/oo/Register_Implement.hpp | 24 | ||||
-rw-r--r-- | meowpp/utility.h | 47 | ||||
-rw-r--r-- | meowpp/utility.hpp | 176 | ||||
-rwxr-xr-x | readme_generate.py | 86 |
28 files changed, 2756 insertions, 0 deletions
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..12c9cb8 --- /dev/null +++ b/Makefile @@ -0,0 +1,23 @@ +CXXFLAGS = -g -Imeowpp + +README = README.asciidoc + +TEST = _test +TESTS = meowpp + + + +all: $(TESTS) + +readme: + ./readme_generate.py $(README) + +$(TEST)/meowpp: $(TEST)/meowpp.cpp + g++ -o $@ $(CXXFLAGS) $^ + +$(TESTS): %: $(TEST)/% + $^ + +clean: + -rm -f $(foreach i,$(TESTS),$(TEST)/$i) + -rm -f $(README) diff --git a/README.asciidoc b/README.asciidoc new file mode 100644 index 0000000..8058527 --- /dev/null +++ b/README.asciidoc @@ -0,0 +1,37 @@ +==== hi!! + +=== MergeableHeap<Key, Value> +.Description +MergeableHeap is a kind of maximum-heap with an extra method `merge`, +which will merge another MergeableHeap into itself. + +.Support methods +* N <- number of elements in the heap +* M <- number of elements in the other heap if need +[options="header",width="100%",cols="1>,1<s,5<,1<,1<,10<",grid="rows"] +|======================================================================= +|Const?|Name| Parameters| Return Type| Time Complexity| Description +||operator= | (MergeableHeap const&)| *this | O(N) +| Copy operator. +||moveTo | (MergeableHeap*) | void | O(M) +| Transform the this->data to the heap specified in parameters +|const|top | () | Element | O(1) +| Return the maximum element in the heap. +|const|size | () | size_t | O(1) +| Return the number of elements in the heap. +|const|empty| () | bool | O(1) +| Return whether the heap is empty or not. +||push |(Element) |void | O(log N) +| Add a element into the heap +||pop |() |void | O(log N) +| Delete the maximum element from the heap +||merge |(MergeableHeap*) |void | O(log M) +| Merge the specified MergeableHeap(with size=M) into itself +||clear |() |void | O(N) +| Delete all elements from the heap +|======================================================================= + +WARNING: Consider there are two MergeableHeap `A` and `B`. +`B` will become empty after you call `A.merge(&B)`. +The data in `B` will override by data in `A` and `A` will become empty after +you call `A.moveTo(&B)` diff --git a/_test/meowpp b/_test/meowpp Binary files differnew file mode 100755 index 0000000..c84d3b3 --- /dev/null +++ b/_test/meowpp diff --git a/_test/meowpp.cpp b/_test/meowpp.cpp new file mode 100644 index 0000000..ae89e73 --- /dev/null +++ b/_test/meowpp.cpp @@ -0,0 +1,59 @@ +#include "dsa/KD_Tree.h" +#include "dsa/SplayTree.h" +#include "dsa/DisjointSet.h" +#include "dsa/Heaps.h" +#include "Usage.h" + +#include <cstdio> +#include <vector> + +int main(){ + meow::Usage usg("hi!"); + printf("==%s==\n", usg.getUsage().c_str()); + meow::DisjointSet dsj(10); + for(int i = 0; i < 10; i++) printf("%2d ", (int)dsj.root(i)); + dsj.merge(1, 2); + dsj.merge(1, 2); + dsj.merge(1, 3); + dsj.merge(2, 3); + dsj.merge(1, 5); + printf("\n"); + for(int i = 0; i < 10; i++) printf("%2d ", (int)dsj.root(i)); + printf("\n"); + dsj.reset(7); + meow::MergeableHeap<double> hp; + hp.push(5.7); + hp.push(5.3); + hp.push(5.2);// + hp.push(5.1);// + meow::MergeableHeap<double> hp2; + hp2.push(6.7); + hp2.push(4.3); + hp2.push(2.2); + hp2.push(8.1);// + hp.pop(); + hp2.pop(); + hp.pop(); + hp.merge(&hp2); + while(!hp.empty()){ + printf("==%f==\n", hp.top()); + hp.pop(); + } + meow::KD_Tree<std::vector<double>, double, double> kd(3); + std::vector<double> v(3); double k; + v[0] = 0; v[1] = 0; v[2] = 0; k = 0.0; kd.insert(v, k); + v[0] = 2; v[1] = 0; v[2] = 0; k = 0.1; kd.insert(v, k); + v[0] = 0; v[1] = 2; v[2] = 0; k = 0.2; kd.insert(v, k); + v[0] = 0; v[1] = 0; v[2] = 2; k = 0.3; kd.insert(v, k); + v[0] = 2; v[1] = 2; v[2] = 0; k = 0.4; kd.insert(v, k); + v[0] = 2; v[1] = 0; v[2] = 2; k = 0.5; kd.insert(v, k); + v[0] = 0; v[1] = 2; v[2] = 2; k = 0.6; kd.insert(v, k); + v[0] = 2; v[1] = 2; v[2] = 2; k = 0.7; kd.insert(v, k); + v[0] = 0.1; v[1] = 0.9; v[2] = 0.1; k = kd.query(v, 1); printf("//%f//\n", k); + v[0] = 0.1; v[1] = 1.9; v[2] = 0.1; k = kd.query(v, 1); printf("//%f//\n", k); + v[0] = 1.1; v[1] = 1.9; v[2] = 1.1; k = kd.query(v, 1); printf("//%f//\n", k); + v[0] = 0.1; v[1] = 1.9; v[2] = 3.1; k = kd.query(v, 1); printf("//%f//\n", k); + v[0] = 0.1; v[1] = -51.9; v[2] = 10.1; k = kd.query(v, 1); printf("//%f//\n", k); + + return 0; +} diff --git a/description.asciidoc b/description.asciidoc new file mode 100644 index 0000000..09b6ef9 --- /dev/null +++ b/description.asciidoc @@ -0,0 +1 @@ +== hi! diff --git a/meowpp/Usage.h b/meowpp/Usage.h new file mode 100644 index 0000000..b98a7ac --- /dev/null +++ b/meowpp/Usage.h @@ -0,0 +1,96 @@ +#ifndef USAGE_H_ +#define USAGE_H_ + +#include <string> +#include <vector> +#include <map> + +namespace meow{ + class Usage{ + private: + typedef std::string String; + typedef std::vector<String> Strings; + class Value{ + public: + Value(); + Value(String const& v); + Value(String const& v, String const& d); + String getUsage() const; + String getValue() const; + bool operator==(Value const& b) const; + private: + String value; + String description; + }; + typedef std::vector<Value> Values; + class Option{ + public: + Option(); + Option(String const& des); + Option(String const& des, + String const& typ, + String const& def, + bool must); + bool setValue(String const& str); + String getValue(size_t index) const; + size_t getValuesCount() const; + bool addValueAccept(String const& val, + String const& des); + bool hasSetup() const; + bool hasValue() const; + bool chkSetup() const; + String getUsage(unsigned char opt, bool detail) const; + private: + Strings values; + Values values_accept; + String value_default; + String value_type; + String description; + bool has_value; + bool has_setup; + bool must_setup; + }; + typedef std::map<unsigned char, Option> Options; + typedef Options::const_iterator OptionsIterator; + //typedef std::map<unsigned char, Option>::const_iterator OptionsIterator; + public: + Usage(); + Usage(String const& _name); + ////////// **# Add other options #** /////////// + bool import(Usage const& usage); + bool update(Usage const& usage); + /////////// **# add a option/value #** ///////// + bool addOption(unsigned char opt, String const& des); + bool addOption(unsigned char opt, String const& des, + String const& val_type, + String const& val_default, + bool must); + bool addOptionValueAccept(unsigned char opt, + String const& val, + String const& des); + ///////// **# access informations #** ////////// + bool hasOptionSetup(unsigned char opt ) const; + size_t getOptionValuesCount(unsigned char opt ) const; + String getOptionValue(unsigned char opt, size_t index) const; + size_t getProcArgsCount() const; + String getProcArg(size_t index) const; + Strings getProcArgs() const; + //////// **# add a usage description #** /////// + void addUsageBegin(String const& des); + void addUsageEnd (String const& des); + ///////////// **# access usages #** //////////// + String getUsage() const; + ////////// **# analysis argc,argv #** ////////// + bool setArguments(int argc, char** argv, String* errmsg); + private: + String name; + Options options; + Strings usage_begin; + Strings usage_end ; + Strings proc_arguments; + }; +} + +#include "Usage.hpp" + +#endif // USAGE_H_ diff --git a/meowpp/Usage.hpp b/meowpp/Usage.hpp new file mode 100644 index 0000000..40b933f --- /dev/null +++ b/meowpp/Usage.hpp @@ -0,0 +1,297 @@ +#include <string> +#include <vector> +#include <map> +#include <algorithm> +#include <cstdlib> + +#include "utility.h" + +extern "C"{ +#include <unistd.h> +} + +namespace meow{ + inline Usage::Usage(): name("nobody") { } + inline Usage::Usage(Usage::String const& _name): name(_name){ } + inline bool Usage::import(Usage const& usage){ + OptionsIterator it; + for(it = usage.options.begin(); it != usage.options.end(); it++){ + unsigned char const& chr = it->first; + Option const& opt = it->second; + if(options.find(chr) == options.end()){ + options[chr] = opt; + }else{ + return false; + } + } + for(size_t i = 0; i < usage.usage_begin.size(); i++){ + usage_begin.push_back(usage.usage_begin[i]); + } + for(size_t i = 0; i < usage.usage_end.size(); i++){ + usage_end.push_back(usage.usage_end[i]); + } + return true; + } + inline bool Usage::update(Usage const& usage){ + OptionsIterator it; + for(it = usage.options.begin(); it != usage.options.end(); it++){ + unsigned char const& chr = it->first; + if(options.find(chr) == options.end()){ + continue; + } + options[chr] = it->second; + } + return true; + } + inline bool Usage::addOption(unsigned char opt, Usage::String const& des){ + if(options.find(opt) != options.end()){ + return false; + } + options[opt] = Option(des); + return true; + } + inline bool Usage::addOption(unsigned char opt, Usage::String const& des, + Usage::String const& val_type, + Usage::String const& val_default, + bool must){ + if(options.find(opt) != options.end()){ + return false; + } + options[opt] = Option(des, val_type, val_default, must); + return true; + } + inline bool Usage::addOptionValueAccept(unsigned char opt, + Usage::String const& val, + Usage::String const& des){ + if(options.find(opt) == options.end()){ + return false; + } + return options[opt].addValueAccept(val, des); + } + inline bool Usage::hasOptionSetup(unsigned char opt) const { + return (options.find(opt) != options.end() && + options.find(opt)->second.hasSetup()); + } + inline size_t Usage::getOptionValuesCount(unsigned char opt) const { + if(options.find(opt) == options.end()){ + return 0; + } + return options.find(opt)->second.getValuesCount(); + } + inline Usage::String Usage::getOptionValue(unsigned char opt, + size_t index) const { + if(options.find(opt) == options.end()){ + return Usage::String(); + } + return options.find(opt)->second.getValue(index); + } + inline size_t Usage::getProcArgsCount() const{ + return proc_arguments.size(); + } + inline Usage::String Usage::getProcArg(size_t index) const { + if(index >= proc_arguments.size()){ + return Usage::String(); + } + return proc_arguments[index]; + } + inline Usage::Strings Usage::getProcArgs() const { + return proc_arguments; + } + inline void Usage::addUsageBegin(Usage::String const& des){ + usage_begin.push_back(stringReplace(des, "<name>", name)); + } + inline void Usage::addUsageEnd(Usage::String const& des){ + usage_end.push_back(stringReplace(des, "<name>", name)); + } + inline Usage::String Usage::getUsage() const { + Usage::String out = stringPrintf("USAGE\n %s", name.c_str()); + OptionsIterator it; + for(it = options.begin(); it != options.end(); it++){ + out += " " + it->second.getUsage(it->first, false); + } + out += "\n\nDESCRIPTION\n"; + for(size_t i = 0; i < usage_begin.size(); i++){ + out += " " + usage_begin[i] + "\n\n"; + } + for(it = options.begin(); it != options.end(); it++){ + out += it->second.getUsage(it->first, true); + } + for(size_t i = 0; i < usage_end.size(); i++){ + out += " " + usage_end[i] + "\n\n"; + } + return out; + } + inline bool Usage::setArguments(int argc, char** argv, Usage::String *errmsg){ + opterr = 0; + Usage::String s; + OptionsIterator it; + Usage::String zzz; + Usage::String& err = (errmsg == NULL ? zzz : *errmsg); + for(it = options.begin(); it != options.end(); it++){ + s += (char)(it->first); + if(it->second.hasValue()){ + s += ":"; + } + } + for(int opt; (opt = getopt(argc, argv, s.c_str())) != -1; ){ + if(options.find(opt) == options.end()){ + if(options.find(optopt) == options.end()){ + err += stringPrintf("Unknown option '-%c'\n", optopt); + }else{ + err += stringPrintf("No specify argument to '-%c'\n", + optopt); + } + opt = optopt; + return false; + } + if(options[opt].setValue(optarg == NULL ? "" : optarg) == false){ + err += stringPrintf( + "Option argument '%s' to '-%c' is not allowed\n" + , optarg, opt); + return false; + } + } + for(it = options.begin(); it != options.end(); it++){ + if(it->second.chkSetup() == false){ + err += stringPrintf("No specify argument to '-%c'\n", + it->first); + return false; + } + } + for(int i = optind; i < argc; i++){ + proc_arguments.push_back(Usage::String(argv[i])); + } + return true; + } + // + inline Usage::Value::Value(){ } + inline Usage::Value::Value(Usage::String const& v){ + value = v; + description = ""; + } + inline Usage::Value::Value(Usage::String const& v, Usage::String const& d){ + value = v; + description = stringReplace(d, "<value>", v); + } + inline Usage::String Usage::Value::getUsage() const { + if(description.length() > 0) + return stringPrintf("%8s%s : %s\n", + " ", value.c_str(), description.c_str()); + else + return ""; + } + inline Usage::String Usage::Value::getValue() const { + return value; + } + inline bool Usage::Value::operator==(Value const& b) const { + return (value == b.value); + } + // + inline Usage::Option::Option(){ } + inline Usage::Option::Option(Usage::String const& des){ + has_setup = false; + has_value = false; + description = des; + must_setup = false; + } + inline Usage::Option::Option(Usage::String const& des, + Usage::String const& typ, + Usage::String const& def, + bool must){ + has_setup = false; + has_value = true; + description = des; + value_type = typ; + value_default = def; + must_setup = must; + } + inline bool Usage::Option::setValue(Usage::String const& str){ + if(has_value){ + if(values_accept.size() > 0 && + std::find(values_accept.begin(), values_accept.end(), + Value(str, "")) == values_accept.end()){ + return false; + } + values.push_back(str); + } + has_setup = true; + return true; + } + inline size_t Usage::Option::getValuesCount()const{return values.size();} + inline Usage::String Usage::Option::getValue(size_t index) const{ + if(!has_value){ + return ""; + } + if(!has_setup || index >= values.size()){ + return value_default; + } + return values[index]; + } + inline bool Usage::Option::addValueAccept(Usage::String const& val, + Usage::String const& des){ + if(!has_value){ + return false; + } + if(std::find(values_accept.begin(), values_accept.end(), Value(val)) + == values_accept.end()){ + values_accept.push_back(Value(val, des)); + } + return true; + } + inline bool Usage::Option::hasSetup() const { return has_setup; } + inline bool Usage::Option::hasValue() const { return has_value; } + inline bool Usage::Option::chkSetup() const { + return !(must_setup && !has_setup); + } + inline Usage::String Usage::Option::getUsage(unsigned char opt, + bool detail) const { + Usage::String ret; + if(!detail){ + if(!has_value){ + ret = stringPrintf("-%c", opt); + }else{ + ret = stringPrintf("-%c %s", opt, value_type.c_str()); + } + if(!must_setup){ + ret = stringPrintf("[%s]", ret.c_str()); + } + }else{ + Usage::String tmp; + if(has_value){ + Usage::String tmp2; + if(value_default != ""){ + tmp2=stringPrintf("defuault='%s'",value_default.c_str()); + } + Usage::String tmp3 = must_setup ? "" : "optional"; + if(tmp2.length() + tmp3.length() > 0){ + if(tmp2.length() > 0 && tmp3.length() > 0){ + tmp = "(" + tmp3 + ", " + tmp2 + ")"; + }else{ + tmp = "(" + tmp3 + tmp2 + ")"; + } + } + tmp = value_type + " " + tmp; + } + ret = stringPrintf(" -%c %s\n", opt, tmp.c_str()); + tmp = stringReplace(description, "<type>", value_type); + Usage::String vs; + for(size_t i = 0; i < values_accept.size(); i++){ + if(i > 0){ + vs += (i + 1 < values_accept.size() ? ", " : " or "); + } + vs += "'" + values_accept[i].getValue() + "'"; + } + if(vs.length() == 0){ + vs = "... (anything)"; + } + tmp = stringReplace(tmp, "<values>", vs); + ret += " " + tmp + "\n"; + for(size_t i = 0; i < values_accept.size(); i++){ + ret += values_accept[i].getUsage(); + } + ret += "\n"; + } + return ret; + } +} + diff --git a/meowpp/colors/HSL.h b/meowpp/colors/HSL.h new file mode 100644 index 0000000..b16bb2d --- /dev/null +++ b/meowpp/colors/HSL.h @@ -0,0 +1,64 @@ +#ifndef HSL_H_ +#define HSL_H_ + +#include "RGB.h" +#include "YUV.h" + +namespace meow{ + template<class T> + class HSL{ + protected: + T hsl_[3]; + HSL(); + HSL(T const& h, T const& s, T const& l); + HSL(T const* hsl); + public: + virtual ~HSL(){ } + ///////////////// **# not force #** //////////////// + virtual T hMax() const = 0; + virtual T hMin() const = 0; + virtual T sMax() const = 0; + virtual T sMin() const = 0; + virtual T lMax() const = 0; + virtual T lMin() const = 0; + /////////////////// **# access #** ///////////////// + T h() const; + T s() const; + T l() const; + T hsl(size_t i) const; + T lsh(size_t i) const; + /////////////////// **# setting #** //////////////// + T h(T const& val); + T s(T const& val); + T l(T const& val); + T hsl(size_t i, T const& val); + T lsh(size_t i, T const& val); + }; + + class HSLf: public HSL<double>{ + public: + HSLf(); + ~HSLf(); + HSLf(double const&h,double const&s,double const&l); + HSLf(double const* hsl); + double hMin() const; + double hMax() const; + double sMin() const; + double sMax() const; + double lMin() const; + double lMax() const; + }; + + template<class RGB_T, class HSL_T> + inline void RGB_to_HSL(RGB<RGB_T> const& rgb, HSL<HSL_T>* hsl); + template<class HSL_T, class RGB_T> + inline void HSL_to_RGB(HSL<HSL_T> const& hsl, RGB<RGB_T>* rgb); + template<class YUV_T, class HSL_T> + inline void YUV_to_HSL(YUV<YUV_T> const& yuv, HSL<HSL_T>* hsl); + template<class HSL_T, class YUV_T> + inline void HSL_to_YUV(HSL<HSL_T> const& hsl, YUV<YUV_T>* yuv); +} + +#include "HSL.hpp" + +#endif // HSL_H_ diff --git a/meowpp/colors/HSL.hpp b/meowpp/colors/HSL.hpp new file mode 100644 index 0000000..18c01dc --- /dev/null +++ b/meowpp/colors/HSL.hpp @@ -0,0 +1,137 @@ +#include "HSL.h" + +#include "RGB.h" +#include "YUV.h" + +#include "../utility.h" + +namespace meow{ + template<class T> + inline HSL<T>::HSL(){ } + template<class T> + inline HSL<T>::HSL(T const& h, T const& s, T const& l){ + hsl_[0] = h; hsl_[1] = s; hsl_[2] = l; + } + template<class T> + inline HSL<T>::HSL(T const* hsl){ + for(int i = 0; i < 3; i++) hsl_[i] = hsl[i]; + } + + template<class T> + inline T HSL<T>::h() const { return hsl_[0]; } + template<class T> + inline T HSL<T>::s() const { return hsl_[1]; } + template<class T> + inline T HSL<T>::l() const { return hsl_[2]; } + template<class T> + inline T HSL<T>::hsl(size_t i) const { + return hsl_[std::min((size_t)3 - 1, i)]; + } + template<class T> + inline T HSL<T>::lsh(size_t i)const{return hsl(2-i);} + template<class T> + inline T HSL<T>::h(T const& val){return (hsl_[0]=val);} + template<class T> + inline T HSL<T>::s(T const& val){return (hsl_[1]=val);} + template<class T> + inline T HSL<T>::l(T const& val){return (hsl_[2]=val);} + template<class T> + inline T HSL<T>::hsl(size_t i, T const& val){ + return (hsl_[std::min((size_t)3 - 1, i)] = val); + } + template<class T> + inline T HSL<T>::lsh(size_t i, T const& val){ + return hsl(2 - i, val); + } + + + + + + inline HSLf:: HSLf(): HSL(){ } + inline HSLf::~HSLf(){ } + inline HSLf::HSLf(double const&h,double const&s,double const&l):HSL(h,s,l){} + inline HSLf::HSLf(double const* hsl):HSL(hsl){} + inline double HSLf::hMin() const { return 0.0; } + inline double HSLf::hMax() const { return 2.0 * PI; } + inline double HSLf::sMin() const { return 0.0; } + inline double HSLf::sMax() const { return 1.0; } + inline double HSLf::lMin() const { return 0.0; } + inline double HSLf::lMax() const { return 1.0; } + + + + + template<class RGB_T, class HSL_T> + inline void RGB_to_HSL(RGB<RGB_T> const& rgb, HSL<HSL_T>* hsl){ + double r = normalize(rgb.rMin(), rgb.rMax(), rgb.r()); + double g = normalize(rgb.gMin(), rgb.gMax(), rgb.g()); + double b = normalize(rgb.bMin(), rgb.bMax(), rgb.b()); + double mx = std::max(std::max(r, g), b); + double mn = std::min(std::min(r, g), b); + double h, s, l; + if (mx == mn ) h = 0; + else if(mx == r && g >= b) h = PI/3.0 * (g-b) / (mx-mn); + else if(mx == r && g < b) h = PI/3.0 * (g-b) / (mx-mn) + PI * 2.0; + else if(mx == g ) h = PI/3.0 * (b-r) / (mx-mn) + PI/3.0*2.0; + else h = PI/3.0 * (r-g) / (mx-mn) + PI/3.0*4.0; + l = 0.5 * (mx + mn); + if (l == 0 || mx == mn) s = 0; + else if(l < 0.5 ) s = (mx - mn) / (2.0 * l); + else s = (mx - mn) / (2 - 2.0 * l); + hsl->h(h); + hsl->s(s); + hsl->l(l); + } + template<class HSL_T, class RGB_T> + inline void HSL_to_RGB(HSL<HSL_T> const& hsl, RGB<RGB_T>* rgb){ + double h = normalize(hsl.hMin(), hsl.hMax(), hsl.h()); + double s = normalize(hsl.sMin(), hsl.sMax(), hsl.s()); + double l = normalize(hsl.lMin(), hsl.lMax(), hsl.l()); + if(s == 0){ + rgb->r(denormalize(rgb->rMin(), rgb->rMax(), l)); + rgb->g(denormalize(rgb->gMin(), rgb->gMax(), l)); + rgb->b(denormalize(rgb->bMin(), rgb->bMax(), l)); + return ; + } + double q = (l < 0.5 ? (l * (1 + s)) : (l + s - (l * s))); + double p = 2 * l - q; + double t_r = h + 1.0 / 3.0; + double t_g = h; + double t_b = h - 1.0 / 3.0; + if(t_r < 0) t_r = t_r + 1.0; + if(t_r > 1) t_r = t_r - 1.0; + if(t_g < 0) t_g = t_g + 1.0; + if(t_g > 1) t_g = t_g - 1.0; + if(t_b < 0) t_b = t_b + 1.0; + if(t_b > 1) t_b = t_b - 1.0; + double r, g, b; + if (t_r < 1.0 / 6.0) r = p + (q - p) * 6 * t_r; + else if(t_r < 0.5 ) r = q; + else if(t_r < 2.0 / 3.0) r = p + (q - p) * 6 * (2.0 / 3.0 - t_r); + else r = p; + if (t_g < 1.0 / 6.0) g = p + (q - p) * 6 * t_g; + else if(t_g < 0.5 ) g = q; + else if(t_g < 2.0 / 3.0) g = p + (q - p) * 6 * (2.0 / 3.0 - t_g); + else g = p; + if (t_b < 1.0 / 6.0) b = p + (q - p) * 6 * t_b; + else if(t_b < 0.5 ) b = q; + else if(t_b < 2.0 / 3.0) b = p + (q - p) * 6 * (2.0 / 3.0 - t_b); + else b = p; + rgb->r(denormalize(rgb->rMin(), rgb->rMax(), r)); + rgb->g(denormalize(rgb->gMin(), rgb->gMax(), g)); + rgb->b(denormalize(rgb->bMin(), rgb->bMax(), b)); + } + template<class YUV_T, class HSL_T> + inline void YUV_to_HSL(YUV<YUV_T> const& yuv, HSL<HSL_T>* hsl){ + RGBf tmp; + YUV_to_RGB(yuv, &tmp); + RGB_to_HSL(tmp, hsl); + } + template<class HSL_T, class YUV_T> + inline void HSL_to_YUV(HSL<HSL_T> const& hsl, YUV<YUV_T>* yuv){ + RGBf tmp; + HSL_to_RGB(hsl, &tmp); + RGB_to_YUV(tmp, yuv); + } +} diff --git a/meowpp/colors/HSV.h b/meowpp/colors/HSV.h new file mode 100644 index 0000000..d5e21a4 --- /dev/null +++ b/meowpp/colors/HSV.h @@ -0,0 +1,69 @@ +#ifndef HSV_H_ +#define HSV_H_ + +#include "RGB.h" +#include "YUV.h" +#include "HSL.h" + +namespace meow{ + template<class T> + class HSV{ + protected: + T hsv_[3]; + HSV(); + HSV(T const& h, T const& s, T const& v); + HSV(T const* hsv); + public: + virtual ~HSV(){ } + ///////////////// **# not force #** //////////////// + virtual T hMax() const = 0; + virtual T hMin() const = 0; + virtual T sMax() const = 0; + virtual T sMin() const = 0; + virtual T vMax() const = 0; + virtual T vMin() const = 0; + /////////////////// **# access #** ///////////////// + T h() const; + T s() const; + T v() const; + T hsv(size_t i) const; + T vsh(size_t i) const; + /////////////////// **# setting #** //////////////// + T h(T const& val); + T s(T const& val); + T v(T const& val); + T hsv(size_t i, T const& val); + T vsh(size_t i, T const& val); + }; + + class HSVf: public HSV<double>{ + public: + HSVf(); + ~HSVf(); + HSVf(double const&h,double const&s,double const&v); + HSVf(double const* hsv); + double hMin() const; + double hMax() const; + double sMin() const; + double sMax() const; + double vMin() const; + double vMax() const; + }; + + template<class RGB_T, class HSV_T> + inline void RGB_to_HSV(RGB<RGB_T> const& rgb, HSV<HSV_T>* hsv); + template<class HSV_T, class RGB_T> + inline void HSV_to_RGB(HSV<HSV_T> const& hsv, RGB<RGB_T>* rgb); + template<class YUV_T, class HSV_T> + inline void YUV_to_HSV(YUV<YUV_T> const& yuv, HSV<HSV_T>* hsv); + template<class HSV_T, class YUV_T> + inline void HSV_to_YUV(HSV<HSV_T> const& hsv, YUV<YUV_T>* yuv); + template<class HSL_T, class HSV_T> + inline void HSL_to_HSV(HSL<HSL_T> const& hsl, HSV<HSV_T>* hsv); + template<class HSV_T, class HSL_T> + inline void HSV_to_HSL(HSV<HSV_T> const& hsv, HSL<HSL_T>* hsl); +} + +#include "HSV.hpp" + +#endif // HSV_H_ diff --git a/meowpp/colors/HSV.hpp b/meowpp/colors/HSV.hpp new file mode 100644 index 0000000..f7a3004 --- /dev/null +++ b/meowpp/colors/HSV.hpp @@ -0,0 +1,131 @@ +#include "HSV.h" + +#include "RGB.h" +#include "YUV.h" +#include "HSL.h" + +#include "../utility.h" + +namespace meow{ + template<class T> + inline HSV<T>::HSV(){ } + template<class T> + inline HSV<T>::HSV(T const& h, T const& s, T const& v){ + hsv_[0] = h; hsv_[1] = s; hsv_[2] = v; + } + template<class T> + inline HSV<T>::HSV(T const* hsv){ + for(int i = 0; i < 3; i++) hsv_[i] = hsv[i]; + } + + template<class T> + inline T HSV<T>::h() const { return hsv_[0]; } + template<class T> + inline T HSV<T>::s() const { return hsv_[1]; } + template<class T> + inline T HSV<T>::v() const { return hsv_[2]; } + template<class T> + inline T HSV<T>::hsv(size_t i) const { + return hsv_[std::min((size_t)3 - 1, i)]; + } + template<class T> + inline T HSV<T>::vsh(size_t i)const{return hsv(2-i);} + template<class T> + inline T HSV<T>::h(T const& val){return (hsv_[0]=val);} + template<class T> + inline T HSV<T>::s(T const& val){return (hsv_[1]=val);} + template<class T> + inline T HSV<T>::v(T const& val){return (hsv_[2]=val);} + template<class T> + inline T HSV<T>::hsv(size_t i, T const& val){ + return (hsv_[std::min((size_t)3 - 1, i)] = val); + } + template<class T> + inline T HSV<T>::vsh(size_t i, T const& val){ + return hsv(2 - i, val); + } + + + + + + inline HSVf:: HSVf(): HSV(){ } + inline HSVf::~HSVf(){ } + inline HSVf::HSVf(double const&h,double const&s,double const&v):HSV(h,s,v){} + inline HSVf::HSVf(double const* hsv):HSV(hsv){} + inline double HSVf::hMin() const { return 0.0; } + inline double HSVf::hMax() const { return 2.0 * PI; } + inline double HSVf::sMin() const { return 0.0; } + inline double HSVf::sMax() const { return 1.0; } + inline double HSVf::vMin() const { return 0.0; } + inline double HSVf::vMax() const { return 1.0; } + + + + + template<class RGB_T, class HSV_T> + inline void RGB_to_HSV(RGB<RGB_T> const& rgb, HSV<HSV_T>* hsv){ + double r = normalize(rgb.rMin(), rgb.rMax(), rgb.r()); + double g = normalize(rgb.gMin(), rgb.gMax(), rgb.g()); + double b = normalize(rgb.bMin(), rgb.bMax(), rgb.b()); + double mx = std::max(std::max(r, g), b); + double mn = std::min(std::min(r, g), b); + double h, s, v; + if (mx == mn ) h = 0; + else if(mx == r && g >= b) h = PI/3.0 * (g-b) / (mx-mn); + else if(mx == r && g < b) h = PI/3.0 * (g-b) / (mx-mn) + PI * 2.0; + else if(mx == g ) h = PI/3.0 * (b-r) / (mx-mn) + PI/3.0*2.0; + else h = PI/3.0 * (r-g) / (mx-mn) + PI/3.0*4.0; + if(mx == 0) s = 0; + else s = 1 - mn / mx; + v = mx; + hsv->h(h); + hsv->s(s); + hsv->v(v); + } + template<class HSV_T, class RGB_T> + inline void HSV_to_RGB(HSV<HSV_T> const& hsv, RGB<RGB_T>* rgb){ + double h = normalize(hsv.hMin(), hsv.hMax(), hsv.h()) * 360; + double s = normalize(hsv.sMin(), hsv.sMax(), hsv.s()); + double v = normalize(hsv.vMin(), hsv.vMax(), hsv.v()); + int hi = (int)h / 60 % 6; + double f = h / 60.0 - hi; + double p = v * (1 - s); + double q = v * (1 - f * s); + double t = v * (1 - (1 - f) * s); + double r, g, b; + if (hi == 0){ r = v; g = t; b = p; } + else if(hi == 1){ r = q; g = v; b = p; } + else if(hi == 2){ r = p; g = v; b = t; } + else if(hi == 3){ r = p; g = q; b = v; } + else if(hi == 4){ r = t; g = p; b = v; } + else { r = v; g = p; b = q; } + rgb->r(denormalize(rgb->rMin(), rgb->rMax(), r)); + rgb->g(denormalize(rgb->gMin(), rgb->gMax(), g)); + rgb->b(denormalize(rgb->bMin(), rgb->bMax(), b)); + } + template<class YUV_T, class HSV_T> + inline void YUV_to_HSV(YUV<YUV_T> const& yuv, HSV<HSV_T>* hsv){ + RGBf tmp; + YUV_to_RGB(yuv, &tmp); + RGB_to_HSV(tmp, hsv); + } + template<class HSV_T, class YUV_T> + inline void HSV_to_YUV(HSV<HSV_T> const& hsv, YUV<YUV_T>* yuv){ + RGBf tmp; + HSV_to_RGB(hsv, &tmp); + RGB_to_YUV(tmp, yuv); + } + template<class HSL_T, class HSV_T> + inline void HSL_to_HSV(HSL<HSL_T> const& hsl, HSV<HSV_T>* hsv){ + RGBf tmp; + HSL_to_RGB(hsl, &tmp); + RGB_to_HSV(tmp, hsv); + } + template<class HSV_T, class HSL_T> + inline void HSV_to_HSL(HSV<HSV_T> const& hsv, HSL<HSL_T>* hsl){ + RGBf tmp; + HSV_to_RGB(hsv, &tmp); + RGB_to_HSL(tmp, hsl); + } +} diff --git a/meowpp/colors/RGB.h b/meowpp/colors/RGB.h new file mode 100644 index 0000000..04b52a1 --- /dev/null +++ b/meowpp/colors/RGB.h @@ -0,0 +1,66 @@ +#ifndef RGB_H_ +#define RGB_H_ + +namespace meow{ + template<class T> + class RGB{ + protected: + T rgb_[3]; + RGB(); + RGB(T const& r, T const& g, T const& b); + RGB(T const* rgb); + public: + virtual ~RGB() { } + ///////////////// **# not force #** //////////////// + virtual T rMax() const = 0; + virtual T rMin() const = 0; + virtual T gMax() const = 0; + virtual T gMin() const = 0; + virtual T bMax() const = 0; + virtual T bMin() const = 0; + /////////////////// **# access #** ///////////////// + T r() const; + T g() const; + T b() const; + T rgb(size_t i) const; + T bgr(size_t i) const; + /////////////////// **# setting #** //////////////// + T r(T const& val); + T g(T const& val); + T b(T const& val); + T rgb(size_t i, T const& val); + T bgr(size_t i, T const& val); + }; + + class RGBf: public RGB<double>{ + public: + RGBf(); + RGBf(double const&r,double const&g,double const&b); + RGBf(double const* rgb); + ~RGBf(); + double rMin() const; + double rMax() const; + double gMin() const; + double gMax() const; + double bMin() const; + double bMax() const; + }; + + class RGBi: public RGB<int32_t>{ + public: + RGBi(); + RGBi(int32_t const&r,int32_t const&g,int32_t const&b); + RGBi(int32_t const* rgb); + ~RGBi(); + int32_t rMin() const; + int32_t rMax() const; + int32_t gMin() const; + int32_t gMax() const; + int32_t bMin() const; + int32_t bMax() const; + }; +} + +#include "RGB.hpp" + +#endif // RGB_H_ diff --git a/meowpp/colors/RGB.hpp b/meowpp/colors/RGB.hpp new file mode 100644 index 0000000..c2fd599 --- /dev/null +++ b/meowpp/colors/RGB.hpp @@ -0,0 +1,73 @@ +#include <algorithm> +#include <cstdint> + +namespace meow{ + template<class T> + inline RGB<T>::RGB(){ } + template<class T> + inline RGB<T>::RGB(T const& r, T const& g, T const& b){ + rgb_[0] = r; rgb_[1] = g; rgb_[2] = b; + } + template<class T> + inline RGB<T>::RGB(T const* rgb){ + for(int i = 0; i < 3; i++){ + rgb_[i] = rgb[i]; + } + } + template<class T> + inline T RGB<T>::r() const { return rgb_[0]; } + template<class T> + inline T RGB<T>::g() const { return rgb_[1]; } + template<class T> + inline T RGB<T>::b() const { return rgb_[2]; } + template<class T> + inline T RGB<T>::rgb(size_t i) const { + return rgb_[std::min((size_t)3 - 1, i)]; + } + template<class T> + inline T RGB<T>::bgr(size_t i) const { return rgb(2 - i); } + /////////////////// **# setting #** //////////////// + template<class T> + inline T RGB<T>::r(T const& val){ return (rgb_[0] = val); } + template<class T> + inline T RGB<T>::g(T const& val){ return (rgb_[1] = val); } + template<class T> + inline T RGB<T>::b(T const& val){ return (rgb_[2] = val); } + template<class T> + inline T RGB<T>::rgb(size_t i, T const& val){ + i = std::min((size_t)3 - 1, i); + return (rgb_[i] = val); + } + template<class T> + inline T RGB<T>::bgr(size_t i, T const& val){ + return rgb(2 - i, val); + } + + + + inline RGBf::RGBf(): RGB(0.0, 0.0, 0.0){ } + inline RGBf::~RGBf(){ } + inline RGBf::RGBf(double const&r,double const&g,double const&b):RGB(r,g,b){} + inline RGBf::RGBf(double const* rgb): RGB(rgb){ } + inline double RGBf::rMin() const { return 0.0; } + inline double RGBf::rMax() const { return 1.0; } + inline double RGBf::gMin() const { return 0.0; } + inline double RGBf::gMax() const { return 1.0; } + inline double RGBf::bMin() const { return 0.0; } + inline double RGBf::bMax() const { return 1.0; } + + + + + inline RGBi::RGBi (): RGB(0.0, 0.0, 0.0){ } + inline RGBi::~RGBi(){ } + inline RGBi::RGBi(int32_t const&r,int32_t const&g,int32_t const&b):RGB(r,g,b) + {} + inline RGBi::RGBi(int32_t const* rgb): RGB(rgb){ } + inline int32_t RGBi::rMin() const { return 0; } + inline int32_t RGBi::rMax() const { return 255; } + inline int32_t RGBi::gMin() const { return 0; } + inline int32_t RGBi::gMax() const { return 255; } + inline int32_t RGBi::bMin() const { return 0; } + inline int32_t RGBi::bMax() const { return 255; } +} diff --git a/meowpp/colors/YUV.h b/meowpp/colors/YUV.h new file mode 100644 index 0000000..b3744d1 --- /dev/null +++ b/meowpp/colors/YUV.h @@ -0,0 +1,59 @@ +#ifndef YUV_H_ +#define YUV_H_ + +#include "RGB.h" + +namespace meow{ + template<class T> + class YUV{ + protected: + T yuv_[3]; + YUV(); + YUV(T const& y, T const& u, T const& v); + YUV(T const* yuv); + public: + virtual ~YUV() { } + ///////////////// **# not force #** //////////////// + virtual T yMax() const = 0; + virtual T yMin() const = 0; + virtual T uMax() const = 0; + virtual T uMin() const = 0; + virtual T vMax() const = 0; + virtual T vMin() const = 0; + /////////////////// **# access #** ///////////////// + T y() const; + T u() const; + T v() const; + T yuv(size_t i) const; + T vuy(size_t i) const; + /////////////////// **# setting #** //////////////// + T y(T const& val); + T u(T const& val); + T v(T const& val); + T yuv(size_t i, T const& val); + T vuy(size_t i, T const& val); + }; + + class YUVf: public YUV<double>{ + public: + YUVf(); + ~YUVf(); + YUVf(double const& y, double const& u, double const& v); + YUVf(double const* yuv); + double yMin() const; + double yMax() const; + double uMin() const; + double uMax() const; + double vMin() const; + double vMax() const; + }; + + template<class RGB_T, class YUV_T> + inline void RGB_to_YUV(RGB<RGB_T> const& rgb, YUV<YUV_T>* yuv); + template<class YUV_T, class RGB_T> + inline void YUV_to_RGB(YUV<YUV_T> const& yuv, RGB<RGB_T>* rgb); +} + +#include "YUV.hpp" + +#endif // YUV_H_ diff --git a/meowpp/colors/YUV.hpp b/meowpp/colors/YUV.hpp new file mode 100644 index 0000000..0f0d1d0 --- /dev/null +++ b/meowpp/colors/YUV.hpp @@ -0,0 +1,85 @@ +#include <algorithm> +#include "RGB.h" +#include "../utility.h" + +namespace meow{ + template<class T> + inline YUV<T>::YUV(){ } + template<class T> + inline YUV<T>::YUV(T const& y, T const& u, T const& v){ + yuv_[0] = y; yuv_[1] = u; yuv_[2] = v; + } + template<class T> + inline YUV<T>::YUV(T const* yuv){ + for(int i = 0; i < 3; i++){ + yuv_[i] = yuv[i]; + } + } + /////////////////// **# access #** ///////////////// + template<class T> + inline T YUV<T>::y() const { return yuv_[0]; } + template<class T> + inline T YUV<T>::u() const { return yuv_[1]; } + template<class T> + inline T YUV<T>::v() const { return yuv_[2]; } + template<class T> + inline T YUV<T>::yuv(size_t i) const { + return yuv_[std::min((size_t)3 - 1, i)]; + } + template<class T> + inline T YUV<T>::vuy(size_t i) const {return yuv(2-i);} + /////////////////// **# setting #** //////////////// + template<class T> + inline T YUV<T>::y(T const& val){return (yuv_[0]=val);} + template<class T> + inline T YUV<T>::u(T const& val){return (yuv_[1]=val);} + template<class T> + inline T YUV<T>::v(T const& val){return (yuv_[2]=val);} + template<class T> + inline T YUV<T>::yuv(size_t i, T const& val){ + i = std::min((size_t)3 - 1, i); + return (yuv_[i] = val); + } + template<class T> + inline T YUV<T>::vuy(size_t i, T const& val){ + return yuv(2 - i, val); + } + + inline YUVf:: YUVf(): YUV(0.0, 0.0, 0.0){ } + inline YUVf::~YUVf(){ } + inline YUVf::YUVf(double const& y, double const& u, double const& v): YUV(y, u, v){ } + inline YUVf::YUVf(double const* yuv): YUV(yuv){ } + inline double YUVf::yMin() const { return 0.0; } + inline double YUVf::yMax() const { return 1.0; } + inline double YUVf::uMin() const { return 0.0; } + inline double YUVf::uMax() const { return 1.0; } + inline double YUVf::vMin() const { return 0.0; } + inline double YUVf::vMax() const { return 1.0; } + + + template<class RGB_T, class YUV_T> + inline void RGB_to_YUV(RGB<RGB_T> const& rgb, YUV<YUV_T>* yuv){ + double r = normalize(rgb.rMin(), rgb.rMax(), rgb.r()); + double g = normalize(rgb.gMin(), rgb.gMax(), rgb.g()); + double b = normalize(rgb.bMin(), rgb.bMax(), rgb.b()); + double y = 0.299 * r + 0.587 * g + 0.114 * b; + double u = -0.169 * r - 0.331 * g + 0.500 * b + 0.5; + double v = 0.500 * r - 0.419 * g - 0.081 * b + 0.5; + yuv->y(denormalize(yuv->yMin(), yuv->yMax(), y)); + yuv->u(denormalize(yuv->uMin(), yuv->uMax(), u)); + yuv->v(denormalize(yuv->vMin(), yuv->vMax(), v)); + } + template<class YUV_T, class RGB_T> + inline void YUV_to_RGB(YUV<YUV_T> const& yuv, RGB<RGB_T>* rgb){ + double y = normalize(yuv.yMin(), yuv.yMax(), yuv.y()); + double u = normalize(yuv.uMin(), yuv.uMax(), yuv.u()); + double v = normalize(yuv.vMin(), yuv.vMax(), yuv.v()); + double r = y - 0.00093 * (u - 0.5) + 1.401687 * (v - 0.5); + double g = y - 0.34370 * (u - 0.5) - 0.714170 * (v - 0.5); + double b = y + 1.77216 * (u - 0.5) - 0.000990 * (v - 0.5); + rgb->r(denormalize(rgb->rMin(), rgb->rMax(), r)); + rgb->g(denormalize(rgb->gMin(), rgb->gMax(), g)); + rgb->b(denormalize(rgb->bMin(), rgb->bMax(), b)); + } +} + diff --git a/meowpp/dsa/DisjointSet.h b/meowpp/dsa/DisjointSet.h new file mode 100644 index 0000000..1ea6d97 --- /dev/null +++ b/meowpp/dsa/DisjointSet.h @@ -0,0 +1,32 @@ +#ifndef DisjointSet_H__ +#define DisjointSet_H__ + +#include <vector> +#include <cstdlib> + +namespace meow{ + class DisjointSet{ + private: + size_t n; + std::vector<size_t> father; + std::vector<size_t> depth; + // + size_t _root(size_t now); + size_t _merge(size_t a, size_t b); + public: + DisjointSet(); + DisjointSet(size_t _n); + DisjointSet(DisjointSet const& dsj); + // + size_t root (size_t a ) const; + size_t size ( ) const; + // + void reset(size_t _n ); + size_t merge(size_t a, size_t b); + }; +} + +#include "DisjointSet.hpp" + + +#endif // DisjointSet_H__ diff --git a/meowpp/dsa/DisjointSet.hpp b/meowpp/dsa/DisjointSet.hpp new file mode 100644 index 0000000..3b66626 --- /dev/null +++ b/meowpp/dsa/DisjointSet.hpp @@ -0,0 +1,52 @@ +#include <vector> +#include <cstdlib> + +namespace meow{ + inline size_t DisjointSet::_root(size_t now){ + if(father[now] == now) return now; + return (father[now] = _root(father[now])); + } + inline size_t DisjointSet::_merge(size_t a, size_t b){ + a = _root(a); + b = _root(b); + if(a == b) return a; + if(depth[a] > depth[b]){ + father[b] = a; + return a; + }else{ + father[a] = b; + if(depth[a] == depth[b]){ + depth[b]++; + } + return b; + } + } + // + inline DisjointSet::DisjointSet(): n(0){ } + inline DisjointSet::DisjointSet(size_t _n): n(0){ + reset(_n); + } + inline DisjointSet::DisjointSet(DisjointSet const& dsj){ + n = dsj.n; + father = dsj.father; + depth = dsj.depth; + } + // + inline size_t DisjointSet::root(size_t a) const{ + return ((DisjointSet*)this)->_root(a); + } + inline size_t DisjointSet::size() const{ return n; } + // + inline void DisjointSet::reset(size_t _n){ + n = _n; + father.resize(n); + depth .resize(n); + for(size_t i = 0; i < n; i++){ + father[i] = i; + depth [i] = 1; + } + } + inline size_t DisjointSet::merge(size_t a, size_t b){ + return _merge(a, b); + } +} diff --git a/meowpp/dsa/Heaps.h b/meowpp/dsa/Heaps.h new file mode 100644 index 0000000..cac3e01 --- /dev/null +++ b/meowpp/dsa/Heaps.h @@ -0,0 +1,84 @@ +#ifndef Heap_H__ +#define Heap_H__ + +#include <cstdlib> + +namespace meow{ + /********************************************************* + @asciidoc + === MergeableHeap<Key, Value> + .Description + MergeableHeap is a kind of maximum-heap with an extra method `merge`, + which will merge another MergeableHeap into itself. + + .Support methods + * N <- number of elements in the heap + * M <- number of elements in the other heap if need + [options="header",width="100%",cols="1>,1<s,5<,1<,1<,10<",grid="rows"] + |======================================================================= + |Const?|Name| Parameters| Return Type| Time Complexity| Description + ||operator= | (MergeableHeap const&)| *this | O(N) + | Copy operator. + ||moveTo | (MergeableHeap*) | void | O(M) + | Transform the this->data to the heap specified in parameters + |const|top | () | Element | O(1) + | Return the maximum element in the heap. + |const|size | () | size_t | O(1) + | Return the number of elements in the heap. + |const|empty| () | bool | O(1) + | Return whether the heap is empty or not. + ||push |(Element) |void | O(log N) + | Add a element into the heap + ||pop |() |void | O(log N) + | Delete the maximum element from the heap + ||merge |(MergeableHeap*) |void | O(log M) + | Merge the specified MergeableHeap(with size=M) into itself + ||clear |() |void | O(N) + | Delete all elements from the heap + |======================================================================= + +WARNING: Consider there are two MergeableHeap `A` and `B`. +`B` will become empty after you call `A.merge(&B)`. +The data in `B` will override by data in `A` and `A` will become empty after +you call `A.moveTo(&B)` + @asciidoc- + *********************************************************/ + template<class Element> + class MergeableHeap{ // maximum-heap + private: + struct Node{ + Element value; + Node* l_child; + Node* r_child; + size_t weight; + Node(Element const& _value); + }; + // + Node* root; + // + void clear(Node* _node ); + Node* dup (Node* _node2 ); + Node* merge(Node* _left, Node* _right); + public: + MergeableHeap(); + MergeableHeap(MergeableHeap const& _heap2); + // + ~MergeableHeap(); + // + MergeableHeap& operator=(MergeableHeap const& _heap2); + void moveTo(MergeableHeap* _heap2); + // + Element const& top () const; + size_t size () const; + size_t empty() const; + // + void push (Element const& _value); + void pop ( ); + void clear( ); + void merge(MergeableHeap* _heap2); + }; +} + +#include "MergeableHeap.hpp" + +#endif // Heap_H__ diff --git a/meowpp/dsa/KD_Tree.h b/meowpp/dsa/KD_Tree.h new file mode 100644 index 0000000..0abc358 --- /dev/null +++ b/meowpp/dsa/KD_Tree.h @@ -0,0 +1,75 @@ +#ifndef KD_Tree_H__ +#define KD_Tree_H__ + +#include <list> +#include <vector> +#include <cstdlib> + +namespace meow{ + template<class Keys, class Key, class Value> + class KD_Tree{ + private: + struct Node{ + Keys key; + Value value; + ssize_t lChild; + ssize_t rChild; + Node(Keys _key, Value _value, ssize_t _l_child, ssize_t _r_child); + }; + typedef std::vector<Node> Nodes; + class Sorter{ + private: + Nodes const& nodes; + size_t cmp; + public: + Sorter(Nodes const& _nodes, size_t _cmp); + bool operator()(size_t const& a, size_t const& b) const; + }; + typedef std::vector<Value> Values; + struct Answer{ + Node const& node; + Key dist2; + Answer(Node const& _node, Key _dist2); + bool operator<(Answer const& b) const; + }; + typedef typename std::list<Answer> AnswerList; + typedef typename AnswerList::iterator AnswerListIterator; + // + const ssize_t NIL; + // + Nodes nodes; + size_t root; + bool needRebuild; + size_t dimension; + // + Key distance2(Keys const& k1, Keys const& k2) const; + size_t query(Keys const& key, + size_t k, + size_t index, + int depth, + std::vector<Key>& dist2_v, + Key dist2_s, + AnswerList* ret) const; + ssize_t build(ssize_t beg, + ssize_t end, + std::vector<size_t>* orders, + int depth); + public: + KD_Tree(); + KD_Tree(size_t _dimension); + ~KD_Tree(); + // + void insert(Keys const& key, Value value); + void build(); + // + Value query (Keys const& point, int k) const; + Values rangeQuery(Keys const& point, int k) const; + // + void clear(); + void reset(size_t _dimension); + }; +} + +#include "KD_Tree.hpp" + +#endif // KD_Tree_H__ diff --git a/meowpp/dsa/KD_Tree.hpp b/meowpp/dsa/KD_Tree.hpp new file mode 100644 index 0000000..9e9a925 --- /dev/null +++ b/meowpp/dsa/KD_Tree.hpp @@ -0,0 +1,196 @@ +#include <cstdlib> +#include <list> +#include <vector> +#include <algorithm> +#include <set> +#include "utility.h" + +namespace meow{ + template<class Keys, class Key, class Value> + inline KD_Tree<Keys,Key,Value>::Node::Node(Keys _key, + Value _value, + ssize_t _l_child, + ssize_t _r_child): + key(_key), value(_value), lChild(_l_child), rChild(_r_child){ } + // + template<class Keys, class Key, class Value> + inline KD_Tree<Keys, Key, Value>::Sorter::Sorter(KD_Tree::Nodes const& _nodes, + size_t _cmp): + nodes(_nodes), cmp(_cmp){ } + template<class Keys, class Key, class Value> + inline bool + KD_Tree<Keys, Key, Value>::Sorter::operator()(size_t const& a, + size_t const& b) const{ + if(nodes[a].key[cmp] != nodes[b].key[cmp]){ + return (nodes[a].key[cmp] < nodes[b].key[cmp]); + } + return (nodes[a].value < nodes[b].value); + } + // + template<class Keys, class Key, class Value> + inline KD_Tree<Keys, Key, Value>::Answer::Answer(Node const& _node, + Key _dist2): + node(_node), dist2(_dist2){ } + template<class Keys, class Key, class Value> + inline bool + KD_Tree<Keys, Key, Value>::Answer::operator<(Answer const& b) const{ + if(dist2 != b.dist2) return (dist2 < b.dist2); + return (node.value < b.node.value); + } + // + template<class Keys, class Key, class Value> + inline Key KD_Tree<Keys, Key, Value>::distance2(Keys const& k1, + Keys const& k2) const{ + Key ret(0); + for(size_t i = 0; i < dimension; i++) + ret += squ(k1[i] - k2[i]); + return ret; + } + template<class Keys, class Key, class Value> + inline size_t KD_Tree<Keys, Key, Value>::query(Keys const& key, + size_t k, + size_t index, + int depth, + std::vector<Key>& dist2_v, + Key dist2_s, + KD_Tree::AnswerList* ret) const{ + if(index == NIL){ + return 0; + } + size_t cmp = depth % dimension; + ssize_t right_side, opposite, size; + ssize_t sz, other; + if(key[cmp] <= nodes[index].key[cmp]){ + right_side = nodes[index].lChild; + opposite = nodes[index].rChild; + }else{ + right_side = nodes[index].rChild; + opposite = nodes[index].lChild; + } + size = query(key, k, right_side, depth + 1, dist2_v, dist2_s, ret); + Answer my_ans(nodes[index], distance2(nodes[index].key, key)); + if(size < k || my_ans < *(ret->rbegin())){ + KD_Tree::AnswerListIterator it = ret->begin(); + while(it != ret->end() && !(my_ans < *it)) it++; + ret->insert(it, my_ans); + size++; + } + Key dist2_old = dist2_v[cmp]; + dist2_v[cmp] = squ(nodes[index].key[cmp] - key[cmp]); + dist2_s += dist2_v[cmp] - dist2_old; + if(size < k || (*(ret->rbegin())).dist2 >= dist2_s){ + KD_Tree::AnswerList ret2; + size += query(key, k, opposite, depth + 1, dist2_v, dist2_s, &ret2); + KD_Tree::AnswerListIterator it1, it2; + for(it1 = ret->begin(), it2 = ret2.begin(); it2 != ret2.end(); it2++){ + while(it1 != ret->end() && *it1 < *it2) it1++; + it1 = ++(ret->insert(it1, *it2)); + } + } + if(size > k){ + for(int i = size - k; i--; ){ + ret->pop_back(); + } + size = k; + } + dist2_v[cmp] = dist2_old; + return size; + } + template<class Keys, class Key, class Value> + inline ssize_t KD_Tree<Keys, Key, Value>::build(ssize_t beg, + ssize_t end, + std::vector<size_t>* orders, + int depth){ + if(beg > end){ + return NIL; + } + ssize_t mid = (beg + end) / 2; + size_t cmp = depth % 2; + std::set<size_t> right; + for(ssize_t i = mid + 1; i <= end; i++){ + right.insert(orders[cmp][i]); + } + for(int i = 0; i < dimension; i++){ + if(i == cmp) continue; + size_t aa = beg, bb = mid + 1; + for(int j = beg; j <= end; j++){ + if(orders[i][j] == orders[cmp][mid]){ + orders[dimension][mid] = orders[i][j]; + }else if(right.find(orders[i][j]) != right.end()){ + orders[dimension][bb++] = orders[i][j]; + }else{ + orders[dimension][aa++] = orders[i][j]; + } + } + for(int j = beg; j <= end; j++){ + orders[i][j] = orders[dimension][j]; + } + } + nodes[orders[cmp][mid]].lChild = build(beg, mid - 1, orders, depth + 1); + nodes[orders[cmp][mid]].rChild = build(mid + 1, end, orders, depth + 1); + return orders[cmp][mid]; + } + template<class Keys, class Key, class Value> + inline KD_Tree<Keys, Key, Value>::KD_Tree(): + NIL(-1), root(NIL), needRebuild(false), dimension(1){ } + template<class Keys, class Key, class Value> + inline KD_Tree<Keys, Key, Value>::KD_Tree(size_t _dimension): + NIL(-1), root(NIL), needRebuild(false), dimension(_dimension){ } + template<class Keys, class Key, class Value> + inline KD_Tree<Keys, Key, Value>::~KD_Tree(){ } + template<class Keys, class Key, class Value> + inline void KD_Tree<Keys, Key, Value>::insert(Keys const& key, Value value){ + nodes.push_back(Node(key, value, NIL, NIL)); + needRebuild = true; + } + template<class Keys, class Key, class Value> + inline void KD_Tree<Keys, Key, Value>::build(){ + if(needRebuild){ + std::vector<size_t> orders[dimension + 1]; + for(int j = 0; j < dimension + 1; j++){ + orders[j].resize(nodes.size()); + } + for(int j = 0; j < dimension; j++){ + for(size_t i = 0, I = nodes.size(); i < I; i++){ + orders[j][i] = i; + } + std::sort(orders[j].begin(), orders[j].end(), Sorter(nodes, j)); + } + root = build(0, (ssize_t)nodes.size() - 1, orders, 0); + needRebuild = false; + } + } + template<class Keys, class Key, class Value> + inline Value KD_Tree<Keys, Key, Value>::query(Keys const& point, int k) const{ + ((KD_Tree*)this)->build(); + KD_Tree::AnswerList ret; + std::vector<Key> tmp(dimension, Key(0)); + query(point, k, root, 0, tmp, Key(0), &ret); + return (*(ret.rbegin())).node.value; + } + template<class Keys, class Key, class Value> + inline typename KD_Tree<Keys, Key, Value>::Values + KD_Tree<Keys, Key, Value>::rangeQuery(Keys const& point, int k) const{ + ((KD_Tree*)this)->build(); + KD_Tree::AnswerList ret; + std::vector<Key> tmp(dimension, Key(0)); + query(point, k, root, 0, tmp, Key(0), &ret); + KD_Tree::Values ret_val(ret.size()); + int i = 0; + for(KD_Tree::AnswerListIterator it = ret.begin(); it != ret.end(); it++){ + ret_val[i++] = (*it).node.value; + } + return ret_val; + } + template<class Keys, class Key, class Value> + inline void KD_Tree<Keys, Key, Value>::clear(){ + root = NIL; + nodes.clear(); + needRebuild = false; + } + template<class Keys, class Key, class Value> + inline void KD_Tree<Keys, Key, Value>::reset(size_t _dimension){ + clear(); + dimension = _dimension; + } +} diff --git a/meowpp/dsa/MergeableHeap.hpp b/meowpp/dsa/MergeableHeap.hpp new file mode 100644 index 0000000..de3aea9 --- /dev/null +++ b/meowpp/dsa/MergeableHeap.hpp @@ -0,0 +1,146 @@ +// @class name : MergeableHeap +// @implement : Leftist Tree + +#include <cstdlib> + +namespace meow{ + ////////////////////////////////////////////////////////// + // **# MergeableHeap--Node-- constructor #** // + ////////////////////////////////////////////////////////// + template<class Element> + inline + MergeableHeap<Element>::Node::Node(Element const& _value): // Node + value(_value), l_child(NULL), r_child(NULL), weight(1){ } + + ////////////////////////////////////////////////////////// + // **# MergeableHeap -- clear, duplicate #** // + ////////////////////////////////////////////////////////// + template<class Element> + inline void + MergeableHeap<Element>::clear(Node* _node){ //clear + if(_node != NULL){ + clear(_node->l_child); + clear(_node->r_child); + delete _node; + } + } + template<class Element> + inline typename MergeableHeap<Element>::Node* + MergeableHeap<Element>::dup(Node* _node2){ // dup + if(_node2 == NULL) return NULL; + Node* ret = new Node(_node2->value); + ret->l_child = dup(_node2->l_child); + ret->r_child = dup(_node2->r_child); + ret->weight = 1; + ret->weight += (ret->l_child == NULL ? 0 : ret->l_child->weight); + ret->weight += (ret->r_child == NULL ? 0 : ret->r_child->weight); + return ret; + } + + ////////////////////////////////////////////////////////// + // **# MergeableHeap -- merge #** // + ////////////////////////////////////////////////////////// + template<class Element> + inline typename MergeableHeap<Element>::Node* + MergeableHeap<Element>::merge(Node* _left, Node* _right){ //merge + if(_left == NULL) return _right; + if(_right == NULL) return _left; + if(_left->value < _right->value){ + std::swap(_left, _right); + } + _left->r_child = merge(_left->r_child, _right); + size_t lw = (_left->l_child == NULL ? 0 : _left->l_child->weight); + size_t rw = (_left->r_child == NULL ? 0 : _left->r_child->weight); + if(lw < rw){ + std::swap(_left->l_child, _left->r_child); + } + _left->weight = 1 + lw + rw; + return _left; + } + + ////////////////////////////////////////////////////////// + // **# MergeableHeap -- constrctors/destructors #** // + ////////////////////////////////////////////////////////// + template<class Element> + inline + MergeableHeap<Element>::MergeableHeap(): //MergeableHeap + root(NULL){ } + template<class Element> + inline + MergeableHeap<Element>::MergeableHeap(MergeableHeap const& _heap2): + root(NULL){ + root = dup(_heap2.root); + } + template<class Element> + inline + MergeableHeap<Element>::~MergeableHeap(){ //~MergeableHeap + clear(root); + } + + ////////////////////////////////////////////////////////// + //**# MergeableHeap -- copy operation/data transform #**// + ////////////////////////////////////////////////////////// + template<class Element> + inline MergeableHeap<Element>& + MergeableHeap<Element>::operator=(MergeableHeap const& _heap2){ // = + root = dup(_heap2.root); + return *this; + } + template<class Element> + inline void + MergeableHeap<Element>::moveTo(MergeableHeap* _heap2){ // moveTo + _heap2->clear(); + _heap2->root = root; + root = NULL; + } + ////////////////////////////////////////////////////////// + // **# MergeableHeap -- access: top, size, emtpy #** // + ////////////////////////////////////////////////////////// + template<class Element> + inline Element const& + MergeableHeap<Element>::top() const{ // top + return root->value; + } + template<class Element> + inline size_t + MergeableHeap<Element>::size() const{ // size + return (root == NULL ? 0 : root->weight); + } + template<class Element> + inline size_t + MergeableHeap<Element>::empty() const{ // empty + return (size() == 0); + } + ////////////////////////////////////////////////////////// + // **# MergeableHeap -- update: push, pop, merge #** // + ////////////////////////////////////////////////////////// + template<class Element> + inline void + MergeableHeap<Element>::push(Element const& _value){ // push + Node* new_node = new Node(_value); + root = merge(root, new_node); + } + template<class Element> + inline void + MergeableHeap<Element>::pop(){ // pop + Node* l = root->l_child; + Node* r = root->r_child; + delete root; + root = merge(l, r); + } + template<class Element> + inline void + MergeableHeap<Element>::merge(MergeableHeap* _heap2){ // merge + root = merge(root, _heap2->root); + _heap2->root = NULL; + } + ////////////////////////////////////////////////////////// + // **# MergeableHeap -- refresh: clear #** // + ////////////////////////////////////////////////////////// + template<class Element> + inline void + MergeableHeap<Element>::clear(){ // clear + clear(root); + root = NULL; + } +} diff --git a/meowpp/dsa/SplayTree.h b/meowpp/dsa/SplayTree.h new file mode 100644 index 0000000..78b54f6 --- /dev/null +++ b/meowpp/dsa/SplayTree.h @@ -0,0 +1,103 @@ +#ifndef SplayTree_h__ +#define SplayTree_h__ + +#include "utility.h" + +namespace meow{ + template<class Key, class Value> + class SplayTree{ + private: + struct Node{ + Key _key; + Key _keyOffset; + Value _value; + size_t _size; + Node* _parent; + Node* _lChild; + Node* _rChild; + // + Node(Key const& __key, Value const& __value); + }; + // + Node* _root; + // + void offsetAdd (Node* __node, Key const& __delta) const; + void offsetDown (Node* __node ) const; + void sizeUpdate (Node* __node ) const; + void connectLChild(Node* __parent, Node* __child ) const; + void connectRChild(Node* __parent, Node* __child ) const; + // + Node* clear(Node* __node); + Node* dup (Node* __node); + // + void rotate( Node* __parent, Node* __child) const; + void rotate(Node* __grand, Node* __parent, Node* __child) const; + Node* splay(Node* __node) const; + // + Node* findKey (Node* __node, Key const& __key) const; + Node* findMinMax(Node* __node, bool minimum ) const; + Node* findOrder (Node* __node, size_t __order ) const; + // + void split(Node* __root, Node** __left, Node** __right); + Node* merge( Node* __left, Node* __right); + // + void print(Node* __now, int __depth) const; + public: + class Element{ + private: + typedef std::pair<Key const&, Value&> Entry; + Entry* _entry; + Node * _node; + // + void reset(Node* __node); + public: + Element(); + Element(Node* __node); + Element(Element const& __iterator2); + ~Element(); + // + Element& operator=(Element const& __e2); + // + Entry* operator->(); + Entry& operator *(); + // + bool operator==(Element const& __e2) const; + bool operator!=(Element const& __e2) const; + }; + // + SplayTree(); + SplayTree(SplayTree const& __tree2); + ~SplayTree(); + // + SplayTree& operator=(SplayTree const& __tree2); + void moveTo(SplayTree* __tree2); + // + Element lowerBound(Key const& __key) const; + Element upperBound(Key const& __key) const; + Element rLowerBound(Key const& __key) const; + Element rUpperBound(Key const& __key) const; + Element find (Key const& __key) const; + Element order(size_t __order ) const; + Element first( ) const; + Element last ( ) const; + Element end( ) const; + // + size_t size() const; + bool empty() const; + // + void clear(); + void keyOffset(Key const& __delta); + bool insert (Key const& __key, Value const& __value); + bool erase (Key const& __key); + Value& operator[](Key const& __key); + void splitOut(Key const& __upper_bound, SplayTree* __right); + bool mergeAfter(SplayTree* __tree2); + bool merge (SplayTree* __tree2); + // + void print() const; + }; +} + +#include "SplayTree.hpp" + +#endif // SplayTree_h__ diff --git a/meowpp/dsa/SplayTree.hpp b/meowpp/dsa/SplayTree.hpp new file mode 100644 index 0000000..835664f --- /dev/null +++ b/meowpp/dsa/SplayTree.hpp @@ -0,0 +1,505 @@ + +namespace meow{ + template<class Key, class Value> + inline SplayTree<Key, Value>::Node::Node(Key const& __key, + Value const& __value): + _key(__key), + _keyOffset(0), + _value(__value), + _size(1), + _parent(NULL), + _lChild(NULL), + _rChild(NULL){ } + // + template<class Key, class Value> + inline void SplayTree<Key, Value>::offsetAdd(Node* __node, + Key const& __delta) const{ + __node->_key = __node->_key + __delta; + __node->_keyOffset = __node->_keyOffset + __delta; + } + template<class Key, class Value> + inline void SplayTree<Key, Value>::sizeUpdate(Node* __node) const{ + __node->_size = 1; + if(__node->_lChild != NULL) __node->_size += __node->_lChild->_size; + if(__node->_rChild != NULL) __node->_size += __node->_rChild->_size; + } + template<class Key, class Value> + inline void + SplayTree<Key, Value>::offsetDown(Node* __node) const{ + if(__node->_lChild != NULL) offsetAdd(__node->_lChild, __node->_keyOffset); + if(__node->_rChild != NULL) offsetAdd(__node->_rChild, __node->_keyOffset); + __node->_keyOffset = 0; + } + // + template<class Key, class Value> + inline void SplayTree<Key, Value>::connectLChild(Node* __parent, + Node* __child) const{ + if(__parent != NULL) __parent->_lChild = __child; + if(__child != NULL) __child ->_parent = __parent; + } + template<class Key, class Value> + inline void SplayTree<Key, Value>::connectRChild(Node* __parent, + Node* __child) const{ + if(__parent != NULL) __parent->_rChild = __child; + if(__child != NULL) __child ->_parent = __parent; + } + // + template<class Key, class Value> + inline typename SplayTree<Key, Value>::Node* + SplayTree<Key, Value>::clear(Node* __node){ + if(__node != NULL){ + clear(__node->_lChild); + clear(__node->_rChild); + delete __node; + } + return NULL; + } + template<class Key, class Value> + inline typename SplayTree<Key, Value>::Node* SplayTree<Key, Value>::dup(Node* __node){ + if(__node == NULL){ + return NULL; + } + Node* node = Node(__node->_key, __node->_value); + connectLChild(node, dup(__node->_lChild)); + connectRChild(node, dup(__node->_rChild)); + return node; + } + // + template<class Key, class Value> + inline void SplayTree<Key, Value>::rotate(Node* __parent, + Node* __child) const{ + if(__parent->_lChild == __child){ + connectLChild(__parent, __child->_rChild); + connectRChild(__child , __parent); + }else{ + connectRChild(__parent, __child->_lChild); + connectLChild(__child , __parent); + } + sizeUpdate(__parent); + sizeUpdate(__child ); + } + template<class Key, class Value> + inline void SplayTree<Key, Value>::rotate(Node* __grand, + Node* __parent, + Node* __child) const{ + if(__grand->_lChild == __parent){ + if(__parent->_lChild == __child){ + connectLChild(__grand , __parent->_rChild); + connectLChild(__parent, __child ->_rChild); + connectRChild(__child , __parent); + connectRChild(__parent, __grand ); + }else{ + connectRChild(__parent, __child->_lChild); + connectLChild(__grand , __child->_rChild); + connectLChild(__child, __parent); + connectRChild(__child, __grand ); + } + }else if(__grand->_rChild == __parent){ + if(__parent->_rChild == __child){ + connectRChild(__grand , __parent->_lChild); + connectRChild(__parent, __child ->_lChild); + connectLChild(__child , __parent); + connectLChild(__parent, __grand ); + }else{ + connectRChild(__grand , __child->_lChild); + connectLChild(__parent, __child->_rChild); + connectLChild(__child, __grand ); + connectRChild(__child, __parent); + } + } + sizeUpdate(__grand ); + sizeUpdate(__parent); + sizeUpdate(__child ); + } + template<class Key, class Value> + inline typename SplayTree<Key, Value>::Node* SplayTree<Key, Value>::splay(Node* __node) const{ + if(__node == NULL){ + return NULL; + } + for(Node *parent, *grand, *child = __node; child->_parent != NULL; ){ + parent = child ->_parent; + grand = parent->_parent; + if(grand == NULL){ + rotate(parent, child); + break; + }else{ + Node* g_grand = grand->_parent; + rotate(grand, parent, child); + if(g_grand == NULL){ + break; + } + if(g_grand->_lChild == grand) connectLChild(g_grand, child); + else connectRChild(g_grand, child); + } + } + return __node; + } + template<class Key, class Value> + inline typename SplayTree<Key, Value>::Node* SplayTree<Key, Value>::findKey(Node* __node, + Key const& __key) const{ + Node* ret = __node; + for(Key offset_sum = 0; __node != NULL; offset_sum += ret->_keyOffset){ + offsetDown(__node); + ret = __node; + if(!(__key < offset_sum + __node->_key)){ + if(!(offset_sum + __node->_key< __key)){ + break; + } + __node = __node->_rChild; + }else{ + __node = __node->_lChild; + } + } + return ret; + } + template<class Key, class Value> + inline typename SplayTree<Key, Value>::Node* SplayTree<Key, Value>::findMinMax(Node* __node, + bool minimum) const{ + Node* ret = __node; + while(__node != NULL){ + offsetDown(__node); + ret = __node; + __node = (minimum ? __node->_lChild : __node->_rChild); + } + return ret; + } + template<class Key, class Value> + inline typename SplayTree<Key, Value>::Node* SplayTree<Key, Value>::findOrder(Node* __node, + size_t __order) const{ + Node* ret = __node; + while(__node != NULL){ + offsetDown(__node); + ret = __node; + size_t ord = 1 + (__node->_lChild == NULL ? 0 : __node->_lChild->_size); + if(ord == __order){ + return ret; + }else if(ord < __order){ + __node = __node->_rChild; + __order -= ord; + }else{ + __node = __node->_lChild; + } + } + return ret; + } + template<class Key, class Value> + inline void SplayTree<Key, Value>::split(Node* __root, + Node** __left, Node** __right){ + if(__root == NULL){ + *__left = NULL; + *__right = NULL; + return ; + } + offsetDown(__root); + *__left = __root; + *__right = __root->_rChild; + if(*__right != NULL){ + (*__left )->_rChild = NULL; + (*__right)->_parent = NULL; + sizeUpdate(*__left); + } + } + template<class Key, class Value> + inline typename SplayTree<Key, Value>::Node* SplayTree<Key, Value>::merge(Node* __left, Node* __right){ + if(__left == NULL) return __right; + if(__right == NULL) return __left ; + offsetDown(__left); + connectRChild(__left, __right); + sizeUpdate(__left); + return __left; + } + template<class Key, class Value> + inline void SplayTree<Key, Value>::print(Node* __now, int __depth) const{ + if(__now == NULL) return ; + printf("%*s [%llX]:\tParent=%llX Left=%llX Right=%llX\n", + __depth * 2, "", + (long long unsigned)__now, + (long long unsigned)__now->_parent, + (long long unsigned)__now->_lChild, + (long long unsigned)__now->_rChild); + print(__now->_lChild, __depth + 1); + print(__now->_rChild, __depth + 1); + } + // + template<class Key, class Value> + inline void SplayTree<Key, Value>::Element::reset(Node* __node){ + _node = __node; + delete _entry; + if(__node == NULL){ + _entry = NULL; + }else{ + _entry = new Entry(__node->_key, __node->_value); + } + } + template<class Key, class Value> + inline SplayTree<Key, Value>::Element::Element(): + _entry(NULL), + _node(NULL){ } + template<class Key, class Value> + inline SplayTree<Key, Value>::Element::Element(Node* __node): + _entry(NULL), + _node(NULL){ reset(__node); } + template<class Key, class Value> + inline SplayTree<Key, Value>::Element::Element(Element const& __element2): + _entry(NULL), + _node(NULL){ reset(__element2._node); } + template<class Key, class Value> + inline SplayTree<Key, Value>::Element::~Element(){ delete _entry; } + // + template<class Key, class Value> + inline typename SplayTree<Key, Value>::Element& + SplayTree<Key, Value>::Element::operator=(Element const& __e2){ + reset(__e2._node); + return *this; + } + // + template<class Key, class Value> + inline typename SplayTree<Key, Value>::Element::Entry* SplayTree<Key, Value>::Element::operator->(){ return _entry; } + template<class Key, class Value> + inline typename SplayTree<Key, Value>::Element::Entry& SplayTree<Key, Value>::Element::operator*(){ return *_entry; } + // + template<class Key, class Value> + inline bool + SplayTree<Key, Value>::Element::operator==(Element const& __e2) const{ + return (_node == __e2._node); + } + template<class Key, class Value> + inline bool + SplayTree<Key, Value>::Element::operator!=(Element const& __e2) const{ + return (_node != __e2._node); + } + // + template<class Key, class Value> + inline SplayTree<Key, Value>::SplayTree(): + _root(NULL){ } + template<class Key, class Value> + inline SplayTree<Key, Value>::SplayTree(SplayTree const& __tree2): + _root(NULL){ + _root = dup(__tree2._root); + } + template<class Key, class Value> + inline SplayTree<Key, Value>::~SplayTree(){ + clear(_root); + } + template<class Key, class Value> + inline SplayTree<Key, Value>& SplayTree<Key, Value>::operator=(SplayTree const& __tree2){ + clear(_root); + _root = dup(__tree2._root); + return *this; + } + // + template<class Key, class Value> + inline typename SplayTree<Key, Value>::Element SplayTree<Key, Value>::lowerBound(Key const& __key) const{ + SplayTree* me = (SplayTree*)this; + me->_root = splay(findKey(me->_root, __key)); + me->_root->_parent = NULL; + if(_root == NULL || !(_root->_key < __key)){ + return Element(_root); + } + if(_root->_rChild == NULL){ + return NULL; + } + me->_root = splay(findMinMax(me->_root->_rChild, true)); + me->_root->_parent = NULL; + return Element(_root); + } + template<class Key, class Value> + inline typename SplayTree<Key, Value>::Element SplayTree<Key, Value>::upperBound(Key const& __key) const{ + SplayTree* me = (SplayTree*)this; + me->_root = splay(findKey(me->_root, __key)); + me->_root->_parent = NULL; + if(_root == NULL || __key < _root->_key){ + return Element(_root); + } + if(_root->_rChild == NULL){ + return NULL; + } + me->_root = splay(findMinMax(me->_root->_rChild, true)); + me->_root->_parent = NULL; + return Element(_root); + } + template<class Key, class Value> + inline typename SplayTree<Key, Value>::Element SplayTree<Key, Value>::rLowerBound(Key const& __key) const{ + SplayTree* me = (SplayTree*)this; + me->_root = splay(findKey(me->_root, __key)); + me->_root->_parent = NULL; + if(_root == NULL || !(__key < _root->_key)){ + return Element(_root); + } + if(_root->_lChild == NULL){ + return NULL; + } + me->_root = splay(findMinMax(me->_root->_lChild, false)); + me->_root->_parent = NULL; + return Element(_root); + } + template<class Key, class Value> + inline typename SplayTree<Key, Value>::Element SplayTree<Key, Value>::rUpperBound(Key const& __key) const{ + SplayTree* me = (SplayTree*)this; + me->_root = splay(findKey(me->_root, __key)); + me->_root->_parent = NULL; + if(_root == NULL || _root->_key < __key){ + return Element(_root); + } + if(_root->_lChild == NULL){ + return NULL; + } + me->_root = splay(findMinMax(me->_root->_lChild, false)); + me->_root->_parent = NULL; + return Element(_root); + } + template<class Key, class Value> + inline typename SplayTree<Key, Value>::Element SplayTree<Key, Value>::find(Key const& __key) const{ + SplayTree* me = (SplayTree*)this; + me->_root = splay(findKey(me->_root, __key)); + me->_root->_parent = NULL; + if(_root != NULL && _root->_key == __key){ + return Element(_root); + } + return Element(NULL); + } + template<class Key, class Value> + inline typename SplayTree<Key, Value>::Element SplayTree<Key, Value>::order(size_t __order) const{ + SplayTree* me = (SplayTree*)this; + me->_root = splay(findOrder(me->_root, __order + 1)); + me->_root->_parent = NULL; + return Element(_root); + } + template<class Key, class Value> + inline typename SplayTree<Key, Value>::Element SplayTree<Key, Value>::first() const{ + SplayTree* me = (SplayTree*)this; + me->_root = splay(findMinMax(me->_root, true)); + me->_root->_parent = NULL; + return Element(_root); + } + template<class Key, class Value> + inline typename SplayTree<Key, Value>::Element SplayTree<Key, Value>::last() const{ + SplayTree* me = (SplayTree*)this; + me->_root = splay(findMinMax(me->_root, false)); + me->_root->_parent = NULL; + return Element(_root); + } + template<class Key, class Value> + inline typename SplayTree<Key, Value>::Element SplayTree<Key, Value>::end() const{ return Element(NULL); } + template<class Key, class Value> + inline size_t SplayTree<Key, Value>::size() const{ + return (_root == NULL ? 0 : _root->_size); + } + template<class Key, class Value> + inline bool SplayTree<Key, Value>::empty() const{ return (size() == 0); } + // + template<class Key, class Value> + inline void SplayTree<Key, Value>::clear(){ + clear(_root); + _root = NULL; + } + template<class Key, class Value> + inline void SplayTree<Key, Value>::keyOffset(Key const& __delta){ + if(_root != NULL){ + offsetAdd(_root, __delta); + } + } + template<class Key, class Value> + inline bool SplayTree<Key, Value>::insert(Key const& __key, + Value const& __value){ + if(_root == NULL){ + _root = new Node(__key, __value); + return true; + } + Node* parent = findKey(_root, __key); + Node* new_node; + if(parent->_key < __key){ + connectRChild(parent, new_node = new Node(__key, __value)); + }else if(__key < parent->_key){ + connectLChild(parent, new_node = new Node(__key, __value)); + }else{ + _root = splay(parent); + _root->_parent = NULL; + return false; + } + _root = splay(new_node); + _root->_parent = NULL; + return true; + } + template<class Key, class Value> + inline bool SplayTree<Key, Value>::erase(Key const& __key){ + if(_root == NULL){ + return false; + } + Node* body = findKey(_root, __key); + if(body->_key < __key || __key < body->_key){ + return false; + } + Node* ghost; + if(body->_rChild == NULL){ + ghost = body->_lChild; + }else{ + ghost = findMinMax(body->_rChild, true); + connectLChild(ghost, body->_lChild); + if(ghost != body->_rChild){ + connectLChild(ghost->_parent, ghost->_lChild); + connectLChild(ghost, body->_rChild); + } + } + if(body->_parent != NULL && body->_parent->_lChild == body){ + connectLChild(body->_parent, ghost); + }else{ + connectRChild(body->_parent, ghost); + } + _root = splay(ghost != NULL ? ghost : body->_parent); + _root->_parent = NULL; + return true; + } + template<class Key, class Value> + inline Value& SplayTree<Key, Value>::operator[](Key const& __key){ + if(find(__key) == end()){ + insert(__key, Value()); + } + return find(__key)->second; + } + template<class Key, class Value> + inline void SplayTree<Key, Value>::splitOut(Key const& __upper_bound, + SplayTree* __right){ + __right->clear(); + rLowerBound(__upper_bound); + split(_root, &_root, &(__right->_root)); + } + template<class Key, class Value> + inline bool SplayTree<Key, Value>::mergeAfter(SplayTree* __tree2){ + if(_root == NULL || __tree2->_root == NULL || + last()->first < __tree2->first()->first){ + _root = merge(_root, __tree2->_root); + __tree2->_root = NULL; + return true; + } + return false; + } + template<class Key, class Value> + inline bool SplayTree<Key, Value>::merge(SplayTree* __tree2){ + if(_root == NULL || __tree2->_root == NULL){ + _root = merge(_root, __tree2->_root); + }else{ + if(last()->first < __tree2->first()->first){ + _root = merge(_root, __tree2->_root); + __tree2->_root = NULL; + }else if(__tree2->last()->first < first()->first){ + _root = merge(__tree2->_root, _root); + }else{ + return false; + } + } + __tree2->_root = NULL; + return true; + } + template<class Key, class Value> + inline void SplayTree<Key, Value>::print() const{ + print(_root, 0); + } + template<class Key, class Value> + inline void SplayTree<Key, Value>::moveTo(SplayTree* __tree2){ + __tree2->clear(); + __tree2->_root = _root; + _root = NULL; + } +} + diff --git a/meowpp/oo/Register_Implement.h b/meowpp/oo/Register_Implement.h new file mode 100644 index 0000000..e46f86c --- /dev/null +++ b/meowpp/oo/Register_Implement.h @@ -0,0 +1,33 @@ +#ifndef REGISTER_IMPLEMENT_H_ +#define REGISTER_IMPLEMENT_H_ + +#include <map> + +namespace meow{ + template<class T> + class ImplementInterface{ + private: + T identify_; + protected: + ImplementInterface(T const& id): identify_(id) { } + public: + T const& identify() const { return identify_; } + virtual ~ImplementInterface(){ } + }; + // + template<class T> + class RegisterInterface{ + private: + std::map<T, ImplementInterface<T>*> implements; + protected: + RegisterInterface(); + public: + virtual bool regImplement(ImplementInterface<T>*imp); + virtual ImplementInterface<T>* getImplement(T const& identify); + virtual ~RegisterInterface(){ } + }; +} + +#include "Register_Implement.hpp" + +#endif // REGISTER_IMPLEMENT_H_ diff --git a/meowpp/oo/Register_Implement.hpp b/meowpp/oo/Register_Implement.hpp new file mode 100644 index 0000000..523f266 --- /dev/null +++ b/meowpp/oo/Register_Implement.hpp @@ -0,0 +1,24 @@ + +#include <map> + +namespace meow{ + template<class T> + inline RegisterInterface<T>::RegisterInterface(){ } + template<class T> + inline bool RegisterInterface<T>::regImplement(ImplementInterface<T>* imp){ + if(implements.find(imp->identify()) != implements.end()){ + return false; + } + implements[imp->identify()] = imp; + return true; + } + template<class T> + inline ImplementInterface<T>* RegisterInterface<T>::getImplement( + T const& identify + ){ + if(implements.find(identify) == implements.end()){ + return NULL; + } + return implements[identify]; + } +} diff --git a/meowpp/utility.h b/meowpp/utility.h new file mode 100644 index 0000000..156971a --- /dev/null +++ b/meowpp/utility.h @@ -0,0 +1,47 @@ +#ifndef UTILITY_H_ +#define UTILITY_H_ + +#include <string> +#include <stack> +#include <cctype> + +namespace meow{ + + inline std::string stringPrintf(char const * fmt, ...); + inline std::string stringReplace(std::string str, + std::string const& from, + std::string const& to); + inline bool cstringEndWith(char const* str, int n, ...); +#define debugPrintf(...) \ + meow::debugPrintf_(\ + __FILE__,\ + __PRETTY_FUNCTION__,\ + __LINE__,\ + meow::stringPrintf(__VA_ARGS__).c_str()) + inline void debugPrintf_(char const* file, + char const* func, + size_t line, + char const* msg); + inline void messagePrintf(int level_change, char const* fmt, ...); + + static const double PI = 3.14159265358979323846264338327950288; + + inline double noEPS(double value, double eps = 1e-9); + inline double normalize(double lower, double upper, double value); + inline double denormalize(double lower, double upper, double ratio); + inline double ratioMapping(double l1, double u1, double m1, + double l2, double u2); + template<class T> + inline T inRange(T const& mn, T const& mx, T const& v); + template<class T> + inline T squ(T const& x); + + template<class T> + inline double average(T const& beg, T const& end, double sigs); + template<class T> + inline double average(T const& beg, T const& end, T const& p, double sigs); +} + +#include "utility.hpp" + +#endif // UTILITY_H_ diff --git a/meowpp/utility.hpp b/meowpp/utility.hpp new file mode 100644 index 0000000..9f6d708 --- /dev/null +++ b/meowpp/utility.hpp @@ -0,0 +1,176 @@ +#include <string> +#include <stack> +#include <cstdio> +#include <cstdarg> +#include <algorithm> +#include <cctype> +#include <cstring> +#include <cmath> + +namespace meow{ + + inline std::string stringPrintf(char const * fmt, ...){ + char str[8192]; + va_list args; + va_start(args, fmt); + vsnprintf(str, 8192, fmt, args); + va_end(args); + return std::string(str); + } + + inline std::string stringReplace(std::string str, + std::string const& from, + std::string const& to){ + std::string out = str; + int len = from.length(); + for(size_t pos; (pos = out.find(from)) != std::string::npos; ){ + out.replace(pos, len, to); + } + return out; + } + + inline bool cstringEndWith(char const* str, int n, ...){ + int len = strlen(str); + va_list args; + va_start(args, n); + for(int i = 0; i < n; i++){ + char const* arg = va_arg(args, char const*); + int arglen = strlen(arg); + if(arglen <= len && strcmp(str + len - arglen, arg) == 0){ + return true; + } + } + va_end(args); + return false; + } + + inline void debugPrintf_(char const* file, + char const* func, + size_t line, + char const* msg){ +#ifdef DEBUG + fprintf(stderr, "%s[%d] %s >> %s", file, line, func, msg); +#endif // DEBUG + } + + inline void messagePrintf(int level_change, char const* fmt, ...){ + static int level = 0; + static int last_level = -5; + char str[8192]; + va_list args; + va_start(args, fmt); + vsnprintf(str, 8192, fmt, args); + va_end(args); + if(last_level == 1 && level_change == -1){ + printf(" ...%s\n", str); + }else{ + if(last_level == 1) printf("\n"); + int level2 = level + (level_change == -1 ? -1 : 0); + for(int i = 0; i < level2; i++) printf("| "); + printf("%s%s", (level_change == -1 ? "..." : ""), str); + if(level_change != 1) printf("\n"); + } + level += level_change; + last_level = level_change; + fflush(stdout); + } + + inline double noEPS(double value, double eps){ + return (fabs(value) <= fabs(eps) ? 0 : value); + } + + inline double normalize(double lower, double upper, double value){ + return (value - lower) / (upper - lower); + } + + inline double denormalize(double lower, double upper, double ratio){ + return lower + ratio * (upper - lower); + } + + inline double ratioMapping(double l1, double u1, double m1, + double l2, double u2){ + return denormalize(l2, u2, normalize(l1, u1, m1)); + } + + inline bool filenameCompare(std::string const& f1, std::string const& f2){ + char const* s1 = f1.c_str(); + char const* s2 = f2.c_str(); + int l1 = f1.length(); + int l2 = f2.length(); + int i1, i2; + for(i1 = i2 = 0; i1 < l1 || i2 < l2; i1++, i2++){ + if(isdigit(s1[i1]) && isdigit(s2[i2])){ + int n1 = atoi(s1 + i1); + int n2 = atoi(s2 + i2); + if(n1 != n2){ + return (n1 < n2); + } + while(i1 + 1 < l1 && isdigit(s1[i1 + 1])) i1++; + while(i2 + 1 < l2 && isdigit(s2[i2 + 1])) i2++; + }else{ + if(s1[i1] != s2[i2]){ + return s1[i1] < s2[i2]; + } + } + } + return false; + } + template<class T> + inline T inRange(T const& mn, T const& mx, T const& v){ + return std::min(mx, std::max(mn, v)); + } + template<class T> + inline T squ(T const& x){ + return x * x; + } + template<class T> + inline double average( T const& beg, T const& end, double sigs){ + int N = 0; + double av = 0; + for(T it = beg; it != end; it++, N++){ + av += *it; + } + av /= N; + double sig = 0; + for(T it = beg; it != end; it++){ + sig += (*it - av) * (*it - av); + } + sig = sqrt(sig / N); + double lower = av - sig * sigs, upper = av + sig * sigs; + double ret = 0, retn = 0; + for(T it = beg; it != end; it++){ + if(lower <= *it && *it <= upper){ + ret += *it; + retn++; + } + } + return ret / retn; + } + template<class T> + inline double average( T const& beg, T const& end, T const& p, double sigs){ + int N = 0; + double ps = 0; + for(T it = beg, ip = p; it != end; it++, N++, ip++){ + ps += *ip; + } + double av = 0; + for(T it = beg, ip = p; it != end; it++, ip++){ + av += *it * *ip / ps; + } + double sig = 0; + for(T it = beg, ip = p; it != end; it++, ip++){ + sig += *ip / ps * (*it - av) * (*it - av); + } + sig = sqrt(sig); + double lower = av - sig * sigs, upper = av + sig * sigs; + double ret = 0, retn = 0; + for(T it = beg, ip = p; it != end; it++, ip++){ + if(lower <= *it && *it <= upper){ + ret += *it * *ip; + retn += *ip; + } + } + if(retn <= 1e-10) return av; + return ret / retn; + } +} diff --git a/readme_generate.py b/readme_generate.py new file mode 100755 index 0000000..781e2d3 --- /dev/null +++ b/readme_generate.py @@ -0,0 +1,86 @@ +#! /usr/bin/python + +import sys; +import os; + +class Reader(): + def __init__(self, suffix): + self.suffix = suffix; + # + def checkOk(self, pathname): + for suffix in self.suffix: + if pathname.endswith(suffix): + return True; + return False; + def read(self, pathname): + f = open(pathname, 'r'); + input_string = f.read(); + f.close(); + return self.getOutputString(input_string); + def getOutputString(self, input_string): + return '' +# +class AsciidocReader(Reader): + def __init__(self): + Reader.__init__(self, ['.asciidoc', + '.adoc', + '.ascii', + ]); + def getOutputString(self, input_string): + return input_string; +# +class InReader(Reader): + def __init__(self, suffix, start_string, end_string): + Reader.__init__(self, suffix); + self.start_string = start_string; + self. end_string = end_string; + def getOutputString(self, input_string): + start_index = 0; + ret = '' + while True: + start = input_string.find(self.start_string, start_index); + if start == -1: + break; + end = input_string.find(self.end_string, + start + len(self.start_string)); + if end == -1: + break; + start_index = end + len(self.end_string); + ret += input_string[start + len(self.start_string) : end]; + index = 0; + while index < len(ret): + if index == 0 or ret[index - 1] == "\n": + if ret[index] == ' ' or ret == "\t": + ret = ret[:index] + ret[index + 1:]; + else: + index += 1; + else: + index += 1; + return ret; +# +class CppReader(InReader): + def __init__(self): + InReader.__init__(self, + ['.c', '.cpp', '.h', '.hpp'], + '@asciidoc', + '@asciidoc-'); +# +readers = [AsciidocReader(), + CppReader(), + ]; + +if len(sys.argv) <= 1: readme = 'README.asciidoc'; +else : readme = sys.argv[1]; + +readme_f = open(readme, 'w'); + +for (root, sub_folders, files) in os.walk('./'): + for reader in readers: + for filename in files: + path = os.path.join(root, filename); + if path == './' + readme: + continue; + if reader.checkOk(filename): + readme_f.write(reader.read(path)); + files.remove(filename); +readme_f.close(); |