aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorcathook <b01902109@csie.ntu.edu.tw>2014-04-19 16:21:17 +0800
committercathook <b01902109@csie.ntu.edu.tw>2014-04-19 16:21:17 +0800
commite9a16c4ef0ea782d7db8d788c455ea946eaab039 (patch)
tree5728aa2076a13079f0ff7f162cfd4cab95e1db91
downloadmeow-e9a16c4ef0ea782d7db8d788c455ea946eaab039.tar
meow-e9a16c4ef0ea782d7db8d788c455ea946eaab039.tar.gz
meow-e9a16c4ef0ea782d7db8d788c455ea946eaab039.tar.bz2
meow-e9a16c4ef0ea782d7db8d788c455ea946eaab039.tar.lz
meow-e9a16c4ef0ea782d7db8d788c455ea946eaab039.tar.xz
meow-e9a16c4ef0ea782d7db8d788c455ea946eaab039.tar.zst
meow-e9a16c4ef0ea782d7db8d788c455ea946eaab039.zip
init
-rw-r--r--Makefile23
-rw-r--r--README.asciidoc37
-rwxr-xr-x_test/meowppbin0 -> 410859 bytes
-rw-r--r--_test/meowpp.cpp59
-rw-r--r--description.asciidoc1
-rw-r--r--meowpp/Usage.h96
-rw-r--r--meowpp/Usage.hpp297
-rw-r--r--meowpp/colors/HSL.h64
-rw-r--r--meowpp/colors/HSL.hpp137
-rw-r--r--meowpp/colors/HSV.h69
-rw-r--r--meowpp/colors/HSV.hpp131
-rw-r--r--meowpp/colors/RGB.h66
-rw-r--r--meowpp/colors/RGB.hpp73
-rw-r--r--meowpp/colors/YUV.h59
-rw-r--r--meowpp/colors/YUV.hpp85
-rw-r--r--meowpp/dsa/DisjointSet.h32
-rw-r--r--meowpp/dsa/DisjointSet.hpp52
-rw-r--r--meowpp/dsa/Heaps.h84
-rw-r--r--meowpp/dsa/KD_Tree.h75
-rw-r--r--meowpp/dsa/KD_Tree.hpp196
-rw-r--r--meowpp/dsa/MergeableHeap.hpp146
-rw-r--r--meowpp/dsa/SplayTree.h103
-rw-r--r--meowpp/dsa/SplayTree.hpp505
-rw-r--r--meowpp/oo/Register_Implement.h33
-rw-r--r--meowpp/oo/Register_Implement.hpp24
-rw-r--r--meowpp/utility.h47
-rw-r--r--meowpp/utility.hpp176
-rwxr-xr-xreadme_generate.py86
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
new file mode 100755
index 0000000..c84d3b3
--- /dev/null
+++ b/_test/meowpp
Binary files differ
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();