├── .gitignore ├── .ycm_extra_conf.py ├── LICENSE ├── Makefile ├── README ├── plot-gmm.py ├── plot-point-3d.py ├── plot-point.py ├── python ├── pygmm.py └── test.py └── src ├── Threadpool.cc ├── Threadpool ├── COPYING ├── Makefile ├── README.md ├── Threadpool.hpp ├── main.cpp.prevent-compile └── threadpool-example ├── common.hh ├── datamanip.cc ├── datamanip.hh ├── dataset.hh ├── fastexp.cc ├── fastexp.hh ├── gmm.c.hh ├── gmm.cc ├── gmm.hh ├── helper.hh ├── kmeans++.cc ├── kmeans++.hh ├── kmeans.cc ├── kmeans.hh ├── kmeansII.cc ├── kmeansII.hh ├── main.cc ├── pygmm.cc ├── pygmm.hh ├── random.hh ├── tclap ├── Arg.h ├── ArgException.h ├── ArgTraits.h ├── CmdLine.h ├── CmdLineInterface.h ├── CmdLineOutput.h ├── Constraint.h ├── DocBookOutput.h ├── HelpVisitor.h ├── IgnoreRestVisitor.h ├── Makefile ├── Makefile.am ├── Makefile.in ├── MultiArg.h ├── MultiSwitchArg.h ├── OptionalUnlabeledTracker.h ├── StandardTraits.h ├── StdOutput.h ├── SwitchArg.h ├── UnlabeledMultiArg.h ├── UnlabeledValueArg.h ├── ValueArg.h ├── ValuesConstraint.h ├── VersionVisitor.h ├── Visitor.h ├── XorHandler.h └── ZshCompletionOutput.h ├── timer.hh └── type.hh /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.pyc 3 | -------------------------------------------------------------------------------- /.ycm_extra_conf.py: -------------------------------------------------------------------------------- 1 | # This file is NOT licensed under the GPLv3, which is the license for the rest 2 | # of YouCompleteMe. 3 | # 4 | # Here's the license text for this file: 5 | # 6 | # This is free and unencumbered software released into the public domain. 7 | # 8 | # Anyone is free to copy, modify, publish, use, compile, sell, or 9 | # distribute this software, either in source code form or as a compiled 10 | # binary, for any purpose, commercial or non-commercial, and by any 11 | # means. 12 | # 13 | # In jurisdictions that recognize copyright laws, the author or authors 14 | # of this software dedicate any and all copyright interest in the 15 | # software to the public domain. We make this dedication for the benefit 16 | # of the public at large and to the detriment of our heirs and 17 | # successors. We intend this dedication to be an overt act of 18 | # relinquishment in perpetuity of all present and future rights to this 19 | # software under copyright law. 20 | # 21 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 24 | # IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 25 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 26 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 27 | # OTHER DEALINGS IN THE SOFTWARE. 28 | # 29 | # For more information, please refer to 30 | 31 | import os 32 | import ycm_core 33 | 34 | # These are the compilation flags that will be used in case there's no 35 | # compilation database set (by default, one is not set). 36 | # CHANGE THIS LIST OF FLAGS. YES, THIS IS THE DROID YOU HAVE BEEN LOOKING FOR. 37 | flags = [ 38 | '-Wall', 39 | '-Wextra', 40 | '-DUSER_CLANG_COMPLETER', 41 | # THIS IS IMPORTANT! Without a "-std=" flag, clang won't know which 42 | # language to use when compiling headers. So it will guess. Badly. So C++ 43 | # headers will be compiled as C headers. You don't want that so ALWAYS specify 44 | # a "-std=". 45 | # For a C project, you would set this to something like 'c99' instead of 46 | # 'c++11'. 47 | '-std=c++11', 48 | # ...and the same thing goes for the magic -x option which specifies the 49 | # language that the files to be compiled are written in. This is mostly 50 | # relevant for c++ headers. 51 | # For a C project, you would set this to 'c' instead of 'c++'. 52 | '-x', 53 | 'c++', 54 | '-I', 55 | 'src', 56 | # This path will only work on OS X, but extra paths that don't exist are not 57 | # harmful 58 | ] 59 | 60 | # Set this to the absolute path to the folder (NOT the file!) containing the 61 | # compile_commands.json file to use that instead of 'flags'. See here for 62 | # more details: http://clang.llvm.org/docs/JSONCompilationDatabase.html 63 | # 64 | # Most projects will NOT need to set this to anything; you can just change the 65 | # 'flags' list of compilation flags. Notice that YCM itself uses that approach. 66 | compilation_database_folder = '' 67 | 68 | if compilation_database_folder: 69 | database = ycm_core.CompilationDatabase( compilation_database_folder ) 70 | else: 71 | database = None 72 | 73 | 74 | def DirectoryOfThisScript(): 75 | return os.path.dirname( os.path.abspath( __file__ ) ) 76 | 77 | 78 | def MakeRelativePathsInFlagsAbsolute( flags, working_directory ): 79 | if not working_directory: 80 | return list( flags ) 81 | new_flags = [] 82 | make_next_absolute = False 83 | path_flags = [ '-isystem', '-I', '-iquote', '--sysroot=' ] 84 | for flag in flags: 85 | new_flag = flag 86 | 87 | if make_next_absolute: 88 | make_next_absolute = False 89 | if not flag.startswith( '/' ): 90 | new_flag = os.path.join( working_directory, flag ) 91 | 92 | for path_flag in path_flags: 93 | if flag == path_flag: 94 | make_next_absolute = True 95 | break 96 | 97 | if flag.startswith( path_flag ): 98 | path = flag[ len( path_flag ): ] 99 | new_flag = path_flag + os.path.join( working_directory, path ) 100 | break 101 | 102 | if new_flag: 103 | new_flags.append( new_flag ) 104 | return new_flags 105 | 106 | 107 | def FlagsForFile( filename ): 108 | if database: 109 | # Bear in mind that compilation_info.compiler_flags_ does NOT return a 110 | # python list, but a "list-like" StringVec object 111 | compilation_info = database.GetCompilationInfoForFile( filename ) 112 | final_flags = MakeRelativePathsInFlagsAbsolute( 113 | compilation_info.compiler_flags_, 114 | compilation_info.compiler_working_dir_ ) 115 | 116 | # NOTE: This is just for YouCompleteMe; it's highly likely that your project 117 | # does NOT need to remove the stdlib flag. DO NOT USE THIS IN YOUR 118 | # ycm_extra_conf IF YOU'RE NOT 100% YOU NEED IT. 119 | try: 120 | final_flags.remove( '-stdlib=libc++' ) 121 | except ValueError: 122 | pass 123 | else: 124 | relative_to = DirectoryOfThisScript() 125 | final_flags = MakeRelativePathsInFlagsAbsolute( flags, relative_to ) 126 | 127 | return { 128 | 'flags': final_flags, 129 | 'do_cache': True 130 | } 131 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013,2014 Xinyu Zhou 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | 21 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # $File: Makefile 3 | # $Date: Wed Dec 11 18:57:54 2013 +0800 4 | # 5 | # A single output portable Makefile for 6 | # simple c++ project 7 | 8 | SRC_DIR = src 9 | OBJ_DIR = obj 10 | BIN_DIR = bin 11 | LIB_DIR = lib 12 | TARGET = gmm 13 | 14 | CXX = g++ 15 | #CXX = clang++ 16 | 17 | BIN_TARGET = $(BIN_DIR)/$(TARGET) 18 | PROF_FILE = $(BIN_TARGET).prof 19 | 20 | INCLUDE_DIR = -I $(SRC_DIR) 21 | #LDFLAGS = -L /home/zhanpeng/.local/lib -lGClasses 22 | #LDFLAGS += -lprofiler 23 | #DEFINES += -D__DEBUG 24 | #DEFINES += -D__DEBUG_CHECK 25 | 26 | 27 | CXXFLAGS += -O3 28 | # CXXFLAGS += -g -O0 29 | # CXXFLAGS += -pg 30 | CXXFLAGS += -fomit-frame-pointer -msse2 -mfpmath=sse -ffast-math -lm 31 | 32 | CXXFLAGS += #$(DEFINES) 33 | CXXFLAGS += -std=c++11 34 | #CXXFLAGS += -ansi 35 | CXXFLAGS += -Wall -Wextra 36 | CXXFLAGS += $(INCLUDE_DIR) 37 | CXXFLAGS += $(LDFLAGS) 38 | #CXXFLAGS += $(shell pkg-config --libs --cflags opencv) 39 | #CXXFLAGS += -pthread 40 | CXXFLAGS += -lpthread 41 | #CXXFLAGS += -fopenmp 42 | 43 | CXXFLAGS += -fPIC 44 | 45 | #CC = /usr/share/clang/scan-build/ccc-analyzer 46 | #CXX = /usr/share/clang/scan-build/c++-analyzer 47 | CXXSOURCES = $(shell find $(SRC_DIR)/ -name "*.cc") 48 | OBJS = $(addprefix $(OBJ_DIR)/,$(CXXSOURCES:.cc=.o)) 49 | DEPFILES = $(OBJS:.o=.d) 50 | 51 | .PHONY: all clean run rebuild gdb 52 | 53 | all: $(BIN_TARGET) $(LIB_DIR)/pygmm.so 54 | 55 | $(LIB_DIR)/pygmm.so: $(OBJS) $(LIB_DIR) 56 | g++ -shared $(OBJS) -o $(LIB_DIR)/pygmm.so $(CXXFLAGS) 57 | 58 | $(LIB_DIR)/pygmm.o: $(OBJ_DIR)/$(SRC_DIR)/pygmm.o $(LIB_DIR) 59 | cp $(OBJ_DIR)/$(SRC_DIR)/pygmm.o $(LIB_DIR)/pygmm.o 60 | 61 | $(LIB_DIR): 62 | mkdir $(LIB_DIR) 63 | 64 | $(OBJ_DIR)/%.o: %.cc 65 | @echo "[cc] $< ..." 66 | @$(CXX) -c $< $(CXXFLAGS) -o $@ 67 | 68 | $(OBJ_DIR)/%.d: %.cc 69 | @mkdir -pv $(dir $@) 70 | @echo "[dep] $< ..." 71 | @$(CXX) $(INCLUDE_DIR) $(CXXFLAGS) -MM -MT "$(OBJ_DIR)/$(<:.cc=.o) $(OBJ_DIR)/$(<:.cc=.d)" "$<" > "$@" 72 | 73 | sinclude $(DEPFILES) 74 | 75 | $(BIN_TARGET): $(OBJS) 76 | @echo "[link] $< ..." 77 | @mkdir -p $(BIN_DIR) 78 | @$(CXX) $(OBJS) -o $@ $(LDFLAGS) $(CXXFLAGS) 79 | @echo have a nice day! 80 | 81 | clean: 82 | rm -rf $(OBJ_DIR) $(BIN_DIR) $(LIB_DIR) 83 | 84 | run: $(BIN_TARGET) 85 | ./$(BIN_TARGET) 86 | 87 | rebuild: 88 | +@make clean 89 | +@make 90 | 91 | gdb: $(BIN_TARGET) 92 | gdb ./$(BIN_TARGET) 93 | 94 | run-prof $(PROF_FILE): $(BIN_TARGET) 95 | CPUPROFILE=$(PROF_FILE) CPUPROFILE_FREQUENCY=1000 ./$(BIN_TARGET) 96 | 97 | show-prof: $(PROF_FILE) 98 | google-pprof --text $(BIN_TARGET) $(PROF_FILE) | tee prof.txt 99 | 100 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Fast GMM 2 | ======== 3 | A fast Gaussian Mixture Model implementation. 4 | 5 | Features 6 | ======== 7 | - Multi-thread utilization 8 | - fast exponential function computation 9 | 10 | Thanks 11 | ====== 12 | - fastexp 13 | - Threadpool 14 | - tclap 15 | -------------------------------------------------------------------------------- /plot-gmm.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python2 2 | # -*- coding: utf-8 -*- 3 | # $File: plot-gmm.py 4 | # $Date: Tue Dec 10 16:14:53 2013 +0800 5 | # $Author: Xinyu Zhou 6 | 7 | import matplotlib.pyplot as plt 8 | import matplotlib.mlab as mlab 9 | from matplotlib import cm 10 | from scipy import stats, mgrid, c_, reshape, random, rot90 11 | import argparse 12 | from numpy import * 13 | import numpy as np 14 | 15 | class GassianTypeNotImplemented(Exception): 16 | pass 17 | 18 | def get_args(): 19 | description = 'plot gmm' 20 | parser = argparse.ArgumentParser(description = description) 21 | 22 | parser.add_argument('-i', '--input', help = 'data file', required = True) 23 | parser.add_argument('-m', '--model', help = 'model file', required = True) 24 | 25 | args = parser.parse_args() 26 | 27 | return args 28 | 29 | 30 | class Gaussian(object): 31 | def __init__(self): 32 | self.covtype = 1 33 | self.dim = 0 34 | self.mean = array([]) 35 | self.sigma = array([]) 36 | self.covariance = array([[]]) 37 | 38 | def probability_of(self, x): 39 | assert len(x) == self.dim 40 | 41 | return exp((x - mean)**2 / (2 * self.sigma**2)) / (2 * pi * self.sigma) 42 | 43 | 44 | class GMM(object): 45 | def __init__(self): 46 | self.nr_mixtures = 0 47 | self.weights = array([]) 48 | self.gaussians = [] 49 | 50 | def read_data(fname): 51 | with open(fname) as fin: 52 | return zip(*map( lambda line: map(float, line.rstrip().split()), fin)) 53 | 54 | 55 | def read_gaussian(fin): 56 | gaussian = Gaussian() 57 | gaussian.dim, gaussian.covtype = map(int, fin.readline().rstrip().split()) 58 | if gaussian.covtype == 1: 59 | gaussian.mean = map(float, fin.readline().rstrip().split()) 60 | gaussian.sigma = map(float, fin.readline().rstrip().split()) 61 | assert len(gaussian.mean) == gaussian.dim 62 | assert len(gaussian.sigma) == gaussian.dim 63 | else: 64 | raise GassianTypeNotImplemented() 65 | return gaussian 66 | 67 | def read_model(fname): 68 | gmm = GMM() 69 | with open(fname) as fin: 70 | gmm.nr_mixtures = int(fin.readline().rstrip()) 71 | gmm.weights = map(float, fin.readline().rstrip().split()) 72 | for i in range(gmm.nr_mixtures): 73 | gmm.gaussians.append(read_gaussian(fin)) 74 | 75 | return gmm 76 | 77 | def main(): 78 | args = get_args() 79 | data = read_data(args.input) 80 | x, y = data[:2] 81 | gmm = read_model(args.model) 82 | 83 | fig = plt.figure() 84 | ax = fig.add_subplot(111, aspect = 'equal') 85 | ax.scatter(x, y) 86 | x0, x1, y0, y1 = ax.axis() 87 | 88 | x = linspace(x0, x1, 1000) 89 | y = linspace(y0, y1, 1000) 90 | X, Y = meshgrid(x, y) 91 | 92 | def get_Z(X, Y, gaussian): 93 | return mlab.bivariate_normal(X, Y, gaussian.sigma[0], gaussian.sigma[1], 94 | gaussian.mean[0], gaussian.mean[1], 0) 95 | 96 | Z = get_Z(X, Y, gmm.gaussians[0]) 97 | for gaussian in gmm.gaussians[1:]: 98 | Z += get_Z(X, Y, gaussian) 99 | plt.contour(X, Y, Z, cmap=cm.PuBu_r) 100 | for gaussian in gmm.gaussians: 101 | # print gaussian.mean 102 | plt.scatter(gaussian.mean[0], gaussian.mean[1], s = 50, c = 'yellow') 103 | 104 | plt.show() 105 | 106 | 107 | if __name__ == '__main__': 108 | main() 109 | 110 | 111 | # vim: foldmethod=marker 112 | 113 | -------------------------------------------------------------------------------- /plot-point-3d.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python2 2 | 3 | import numpy as np 4 | import matplotlib.pyplot as plt 5 | from mpl_toolkits.mplot3d import Axes3D 6 | import argparse, sys 7 | 8 | stdin_fname = '$stdin$' 9 | 10 | def get_args(): 11 | description = "plot points into graph. x and y seperated with white space in one line, or just y's" 12 | parser = argparse.ArgumentParser(description = description) 13 | parser.add_argument('-i', '--input', 14 | help = 'input data file, "-" for stdin, default stdin', 15 | default = '-') 16 | parser.add_argument('-o', '--output', 17 | help = 'output image', default = '') 18 | parser.add_argument('--show', 19 | help = 'show the figure after rendered', 20 | action = 'store_true') 21 | parser.add_argument('-t', '--title', 22 | help = 'title of the graph', 23 | default = '') 24 | parser.add_argument('--xlabel', 25 | help = 'x label', 26 | default = 'x') 27 | parser.add_argument('--ylabel', 28 | help = 'y label', 29 | default = 'y') 30 | parser.add_argument('--zlabel', 31 | help = 'z label', 32 | default = 'z') 33 | parser.add_argument('--xlim', help = 'xlim') 34 | parser.add_argument('--ylim', help = 'ylim') 35 | parser.add_argument('--zlim', help = 'zlim') 36 | 37 | parser.add_argument('--annotate-maximum', 38 | help = 'annonate maximum value in graph', 39 | action = 'store_true') 40 | parser.add_argument('--annotate-minimum', 41 | help = 'annonate minimum value in graph', 42 | action = 'store_true') 43 | parser.add_argument('--xkcd', 44 | help = 'xkcd style', 45 | action = 'store_true') 46 | 47 | args = parser.parse_args(); 48 | 49 | if (not args.show) and len(args.output) == 0: 50 | raise Exception("at least one of --show and --output/-o must be specified") 51 | if args.xlim: 52 | args.xlim = map(float, args.xlim.rstrip().split(',')) 53 | if args.ylim: 54 | args.ylim = map(float, args.ylim.rstrip().split(',')) 55 | if args.zlim: 56 | args.zlim = map(float, args.zlim.rstrip().split(',')) 57 | 58 | return args 59 | 60 | 61 | def filter_valid_range(points, rect): 62 | """rect = (min_x, max_x, min_y, max_y)""" 63 | ret = [] 64 | for x, y in points: 65 | if x >= rect[0] and x <= rect[1] and y >= rect[2] and y <= rect[3]: 66 | ret.append((x, y)) 67 | if len(ret) == 0: 68 | ret.append(points[0]) 69 | return ret 70 | 71 | def do_plot(data_x, data_y, data_z, args): 72 | fig = plt.figure(figsize = (16.18, 10)) 73 | projection = '2d' 74 | if len(data_z) > 0: 75 | projection = '3d' 76 | ax = fig.add_axes((0.1, 0.2, 0.8, 0.7), projection = projection) 77 | if projection == '2d': 78 | ax.scatter(data_x, data_y) 79 | else: 80 | ax.scatter(data_x, data_y, data_z) 81 | if args.xlim: 82 | ax.set_xlim(args.xlim) 83 | if args.ylim: 84 | ax.set_ylim(args.ylim) 85 | if args.zlim: 86 | ax.set_zlim3d(args.zlim) 87 | if args.xlim or args.ylim or args.zlim: 88 | pass 89 | ax.set_aspect('equal') 90 | else: 91 | ax.set_aspect('equal', 'datalim') 92 | #ax.spines['right'].set_color('none') 93 | #ax.spines['left'].set_color('none') 94 | #plt.xticks([]) 95 | #plt.yticks([]) 96 | 97 | if args.annotate_maximum or args.annotate_minimum: 98 | max_x, min_x = max(data_x), min(data_x) 99 | max_y, min_y = max(data_y), min(data_y) 100 | x_range = max_x - min_x 101 | y_range = max_y - min_y 102 | x_max, y_max = data_y[0], data_y[0] 103 | x_min, y_min = data_x[0], data_y[0] 104 | 105 | rect = ax.axis() 106 | 107 | for i in xrange(1, len(data_x)): 108 | if data_y[i] > y_max: 109 | y_max = data_y[i] 110 | x_max = data_x[i] 111 | if data_y[i] < y_min: 112 | y_min = data_y[i] 113 | x_min = data_x[i] 114 | if args.annotate_maximum: 115 | text_x, text_y = filter_valid_range([ 116 | (x_max + 0.05 * x_range, 117 | y_max + 0.025 * y_range), 118 | (x_max - 0.05 * x_range, 119 | y_max + 0.025 * y_range), 120 | (x_max + 0.05 * x_range, 121 | y_max - 0.025 * y_range), 122 | (x_max - 0.05 * x_range, 123 | y_max - 0.025 * y_range)], 124 | rect)[0] 125 | ax.annotate('maximum ({:.3f},{:.3f})' . format(x_max, y_max), 126 | xy = (x_max, y_max), 127 | xytext = (text_x, text_y), 128 | arrowprops = dict(arrowstyle = '->')) 129 | if args.annotate_minimum: 130 | text_x, text_y = filter_valid_range([ 131 | (x_min + 0.05 * x_range, 132 | y_min - 0.025 * y_range), 133 | (x_min - 0.05 * x_range, 134 | y_min - 0.025 * y_range), 135 | (x_min + 0.05 * x_range, 136 | y_min + 0.025 * y_range), 137 | (x_min - 0.05 * x_range, 138 | y_min + 0.025 * y_range)], 139 | rect)[0] 140 | ax.annotate('minimum ({:.3f},{:.3f})' . format(x_min, y_min), 141 | xy = (x_min, y_min), 142 | xytext = (text_x, text_y), 143 | arrowprops = dict(arrowstyle = '->')) 144 | 145 | ax.set_xlabel(args.xlabel) 146 | ax.set_ylabel(args.ylabel) 147 | if projection == '3d': 148 | ax.set_zlabel(args.zlabel) 149 | 150 | fig.text(0.5, 0.05, args.title, ha = 'center') 151 | if args.output != '': 152 | plt.savefig(args.output) 153 | 154 | if args.show: 155 | plt.show() 156 | 157 | def main(): 158 | args = get_args() 159 | if args.input == stdin_fname: 160 | fin = sys.stdin 161 | else: 162 | fin = open(args.input) 163 | 164 | data_x = [] 165 | data_y = [] 166 | data_z = [] 167 | data_format = -1 168 | for lineno, line in enumerate(fin.readlines()): 169 | line = [float(i) for i in line.rstrip().split()] 170 | line_data_format = -1 171 | x, y, z = None, None, None 172 | if len(line) == 0: 173 | continue 174 | if len(line) == 2: 175 | line_data_format = 0 176 | x, y = line 177 | elif len(line) == 1: 178 | line_data_format = 1 179 | x, y = lineno, line[0] 180 | elif len(line) == 3: 181 | x, y, z = line 182 | line_data_format = 2; 183 | else: 184 | raise RuntimeError('Can not parse input data at line {}' . format(lineno + 1)) 185 | 186 | if data_format == -1: 187 | data_format = line_data_format 188 | else: 189 | if line_data_format != data_format: 190 | raise RuntimeError('data format is not consistent, at line {}' \ 191 | . format(lineno + 1)) 192 | data_x.append(x) 193 | data_y.append(y) 194 | if z != None: 195 | data_z.append(z) 196 | print len(data_x) 197 | if args.input != stdin_fname: 198 | fin.close() 199 | 200 | if len(data_x) == 1: 201 | return 202 | 203 | if args.xkcd: 204 | with plt.xkcd(): 205 | do_plot(data_x, data_y, data_z, args) 206 | else: 207 | do_plot(data_x, data_y, data_z, args) 208 | 209 | 210 | 211 | if __name__ == '__main__': 212 | main() 213 | -------------------------------------------------------------------------------- /plot-point.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python2 2 | 3 | import numpy as np 4 | import matplotlib.pyplot as plt 5 | import argparse, sys 6 | 7 | stdin_fname = '$stdin$' 8 | 9 | def get_args(): 10 | description = "plot points into graph. x and y seperated with white space in one line, or just y's" 11 | parser = argparse.ArgumentParser(description = description) 12 | parser.add_argument('-i', '--input', 13 | help = 'input data file, "-" for stdin, default stdin', 14 | default = '-') 15 | parser.add_argument('-o', '--output', 16 | help = 'output image', default = '') 17 | parser.add_argument('--show', 18 | help = 'show the figure after rendered', 19 | action = 'store_true') 20 | parser.add_argument('-t', '--title', 21 | help = 'title of the graph', 22 | default = '') 23 | parser.add_argument('--xlabel', 24 | help = 'x label', 25 | default = 'x') 26 | parser.add_argument('--ylabel', 27 | help = 'y label', 28 | default = 'y') 29 | parser.add_argument('--annotate-maximum', 30 | help = 'annonate maximum value in graph', 31 | action = 'store_true') 32 | parser.add_argument('--annotate-minimum', 33 | help = 'annonate minimum value in graph', 34 | action = 'store_true') 35 | parser.add_argument('--xkcd', 36 | help = 'xkcd style', 37 | action = 'store_true') 38 | 39 | args = parser.parse_args(); 40 | 41 | if (not args.show) and len(args.output) == 0: 42 | raise Exception("at least one of --show and --output/-o must be specified") 43 | 44 | return args 45 | 46 | 47 | def filter_valid_range(points, rect): 48 | """rect = (min_x, max_x, min_y, max_y)""" 49 | ret = [] 50 | for x, y in points: 51 | if x >= rect[0] and x <= rect[1] and y >= rect[2] and y <= rect[3]: 52 | ret.append((x, y)) 53 | if len(ret) == 0: 54 | ret.append(points[0]) 55 | return ret 56 | 57 | def do_plot(data_x, data_y, args): 58 | fig = plt.figure(figsize = (16.18, 10)) 59 | ax = fig.add_axes((0.1, 0.2, 0.8, 0.7)) 60 | plt.scatter(data_x, data_y) 61 | # ax.set_aspect('equal', 'datalim') 62 | #ax.spines['right'].set_color('none') 63 | #ax.spines['left'].set_color('none') 64 | #plt.xticks([]) 65 | #plt.yticks([]) 66 | 67 | if args.annotate_maximum or args.annotate_minimum: 68 | max_x, min_x = max(data_x), min(data_x) 69 | max_y, min_y = max(data_y), min(data_y) 70 | x_range = max_x - min_x 71 | y_range = max_y - min_y 72 | x_max, y_max = data_y[0], data_y[0] 73 | x_min, y_min = data_x[0], data_y[0] 74 | 75 | rect = ax.axis() 76 | 77 | for i in xrange(1, len(data_x)): 78 | if data_y[i] > y_max: 79 | y_max = data_y[i] 80 | x_max = data_x[i] 81 | if data_y[i] < y_min: 82 | y_min = data_y[i] 83 | x_min = data_x[i] 84 | if args.annotate_maximum: 85 | text_x, text_y = filter_valid_range([ 86 | (x_max + 0.05 * x_range, 87 | y_max + 0.025 * y_range), 88 | (x_max - 0.05 * x_range, 89 | y_max + 0.025 * y_range), 90 | (x_max + 0.05 * x_range, 91 | y_max - 0.025 * y_range), 92 | (x_max - 0.05 * x_range, 93 | y_max - 0.025 * y_range)], 94 | rect)[0] 95 | ax.annotate('maximum ({:.3f},{:.3f})' . format(x_max, y_max), 96 | xy = (x_max, y_max), 97 | xytext = (text_x, text_y), 98 | arrowprops = dict(arrowstyle = '->')) 99 | if args.annotate_minimum: 100 | text_x, text_y = filter_valid_range([ 101 | (x_min + 0.05 * x_range, 102 | y_min - 0.025 * y_range), 103 | (x_min - 0.05 * x_range, 104 | y_min - 0.025 * y_range), 105 | (x_min + 0.05 * x_range, 106 | y_min + 0.025 * y_range), 107 | (x_min - 0.05 * x_range, 108 | y_min + 0.025 * y_range)], 109 | rect)[0] 110 | ax.annotate('minimum ({:.3f},{:.3f})' . format(x_min, y_min), 111 | xy = (x_min, y_min), 112 | xytext = (text_x, text_y), 113 | arrowprops = dict(arrowstyle = '->')) 114 | 115 | plt.xlabel(args.xlabel) 116 | plt.ylabel(args.ylabel) 117 | 118 | ax.grid(color = 'gray', linestyle = 'dashed') 119 | 120 | fig.text(0.5, 0.05, args.title, ha = 'center') 121 | if args.output != '': 122 | plt.savefig(args.output) 123 | 124 | if args.show: 125 | plt.show() 126 | 127 | def main(): 128 | args = get_args() 129 | if args.input == stdin_fname: 130 | fin = sys.stdin 131 | else: 132 | fin = open(args.input) 133 | 134 | data_x = [] 135 | data_y = [] 136 | data_format = -1 137 | for lineno, line in enumerate(fin.readlines()): 138 | line = [float(i) for i in line.rstrip().split()] 139 | line_data_format = -1 140 | if len(line) == 0: 141 | continue 142 | if len(line) == 2: 143 | line_data_format = 0 144 | x, y = line 145 | elif len(line) == 1: 146 | line_data_format = 1 147 | x, y = lineno, line[0] 148 | else: 149 | raise RuntimeError('Can not parse input data at line {}' . format(lineno + 1)) 150 | 151 | if data_format == -1: 152 | data_format = line_data_format 153 | else: 154 | if line_data_format != data_format: 155 | raise RuntimeError('data format is not consistent, at line {}' \ 156 | . format(lineno + 1)) 157 | data_x.append(x) 158 | data_y.append(y) 159 | print len(data_x) 160 | if args.input != stdin_fname: 161 | fin.close() 162 | 163 | if len(data_x) == 1: 164 | return 165 | 166 | if args.xkcd: 167 | with plt.xkcd(): 168 | do_plot(data_x, data_y, args) 169 | else: 170 | do_plot(data_x, data_y, args) 171 | 172 | 173 | 174 | if __name__ == '__main__': 175 | main() 176 | -------------------------------------------------------------------------------- /python/pygmm.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python2 2 | # -*- coding: utf-8 -*- 3 | # $File: pygmm.py 4 | # $Date: Wed Dec 11 18:49:34 2013 +0800 5 | # $Author: Xinyu Zhou 6 | 7 | from ctypes import * 8 | import os 9 | from os import path 10 | from numpy import array 11 | 12 | 13 | dirname = path.dirname(path.abspath(__file__)) 14 | 15 | pygmm = cdll.LoadLibrary(path.join(dirname, '../lib/pygmm.so')) 16 | 17 | class GMMParameter(Structure): 18 | _fields_ = [("nr_instance", c_int), 19 | ("nr_dim", c_int), 20 | ("nr_mixture", c_int), 21 | ("min_covar", c_double), 22 | ("threshold", c_double), 23 | ("nr_iteration", c_int), 24 | ("init_with_kmeans", c_int), 25 | ("concurrency", c_int), 26 | ("verbosity", c_int)] 27 | 28 | #pygmm.train_model.argtypes = [c_char_p, POINTER(POINTER(c_double)), POINTER(GMMParameter)] 29 | pygmm.score_all.restype = c_double 30 | pygmm.score_instance.restype = c_double 31 | 32 | for num, var in enumerate(['COVTYPE_SPHEREICAL', 'COVTYPE_DIAGONAL', 33 | 'COVTYPE_FULL']): 34 | exec("{} = {}" . format(var, num)) 35 | 36 | class GMM(object): 37 | def __init__(self, nr_mixture = 10, 38 | covariance_type = COVTYPE_DIAGONAL, 39 | min_covar = 1e-3, 40 | threshold = 0.01, 41 | nr_iteration = 200, 42 | init_with_kmeans = 1, 43 | concurrency = 1, 44 | verbosity = 2): 45 | for name, c_type in GMMParameter._fields_: 46 | if name in ['nr_instance', 'nr_dim']: 47 | continue 48 | exec("self.{0} = {0}" . format(name)) 49 | 50 | self.gmm = pygmm.new_gmm(c_int(nr_mixture), c_int(covariance_type)) 51 | 52 | 53 | def _fill_param_from_model_file(self, model_file): 54 | with open(model_file) as f: 55 | self.nr_mixture = int(f.readline().rstrip()) 56 | 57 | @staticmethod 58 | def load(model_file): 59 | gmm = GMM() 60 | gmm._fill_param_from_model_file(model_file) 61 | gmm.gmm = pygmm.load(c_char_p(model_file)) 62 | return gmm 63 | 64 | def dump(self, model_file): 65 | pygmm.dump(self.gmm, c_char_p(model_file)) 66 | 67 | 68 | def _double_array_python_to_ctype(self, X_py): 69 | X_c = [] 70 | for x in X_py: 71 | xs = (c_double * len(x))(*x) 72 | X_c.append(xs) 73 | X_c = (POINTER(c_double) * len(X_c))(*X_c) 74 | return X_c 75 | 76 | def _gen_param(self, X): 77 | param = GMMParameter() 78 | for name, c_type in GMMParameter._fields_: 79 | if name in ['nr_instance', 'nr_dim']: 80 | continue 81 | exec("param.{0} = {1}(self.{0})" . format(name, c_type.__name__)) 82 | 83 | param.nr_instance = c_int(len(X)) 84 | param.nr_dim = c_int(len(X[0])) 85 | return param 86 | 87 | def fit(self, X): 88 | X_c = self._double_array_python_to_ctype(X) 89 | param = self._gen_param(X) 90 | param_ptr = pointer(param) 91 | pygmm.train_model(self.gmm, X_c, param_ptr) 92 | 93 | def score(self, X): 94 | X_c = self._double_array_python_to_ctype(X) 95 | param = self._gen_param(X) 96 | prob = (c_double * len(X))(*([0.0] * len(X))) 97 | pygmm.score_batch(self.gmm, X_c, prob, param.nr_instance, param.nr_dim, \ 98 | param.concurrency) 99 | return array(list(prob)) 100 | 101 | 102 | # vim: foldmethod=marker 103 | 104 | -------------------------------------------------------------------------------- /python/test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python2 2 | # -*- coding: utf-8 -*- 3 | # $File: test.py 4 | # $Date: Wed Dec 11 18:56:21 2013 +0800 5 | # $Author: Xinyu Zhou 6 | 7 | import pygmm 8 | from sklearn.mixture import GMM as SKGMM 9 | from numpy import * 10 | import numpy as np 11 | 12 | 13 | def read_data(fname): 14 | with open(fname) as fin: 15 | return map(lambda line: map(float, line.rstrip().split()), fin) 16 | 17 | def get_gmm(where): 18 | nr_mixture = 256 19 | nr_iteration = 1000 20 | if where == 'pygmm': 21 | return pygmm.GMM(nr_mixture = nr_mixture, 22 | min_covar = 1e-3, 23 | nr_iteration = nr_iteration, 24 | concurrency = 4) 25 | elif where == 'sklearn': 26 | return SKGMM(nr_mixture, n_iter = nr_iteration) 27 | return None 28 | 29 | def random_vector(n, dim): 30 | import random 31 | ret = [] 32 | for j in range(n): 33 | ret.append([random.random() for i in range(dim)]) 34 | return ret 35 | 36 | def extend_X(X, n): 37 | import copy 38 | Xt = copy.deepcopy(X) 39 | for i in range(n - 1): 40 | X.extend(Xt) 41 | 42 | X = read_data('../test.data') 43 | X.extend(X + X + X) 44 | #X = random_vector(100, 13) 45 | #extend_X(X, 10) 46 | #print(len(X)) 47 | 48 | 49 | #gmm_type = 'sklearn' 50 | 51 | global gmm 52 | 53 | def timing(code): 54 | global gmm 55 | import time 56 | start = time.time() 57 | exec(code) 58 | print(time.time() - start) 59 | 60 | def test(): 61 | global gmm 62 | for gmm_type in ['pygmm', 'sklearn']: 63 | print(gmm_type) 64 | gmm = get_gmm(gmm_type) 65 | timing("gmm.fit(X)") 66 | if gmm_type == 'pygmm': 67 | gmm.dump('gmm.model') 68 | print(np.sum(gmm.score(X))) 69 | print("-------") 70 | 71 | test() 72 | 73 | # vim: foldmethod=marker 74 | 75 | -------------------------------------------------------------------------------- /src/Threadpool.cc: -------------------------------------------------------------------------------- 1 | #include "Threadpool/Threadpool.hpp" 2 | 3 | namespace ThreadLib { 4 | 5 | void Worker::operator()() { 6 | while(true) { 7 | std::unique_lock lock(pool.queue_mutex); 8 | 9 | while(!pool.stop && pool.tasks.empty()) 10 | pool.condition.wait(lock); 11 | 12 | if(pool.stop && pool.tasks.empty()) 13 | return; 14 | 15 | std::function task(pool.tasks.top().second); 16 | pool.tasks.pop(); 17 | 18 | lock.unlock(); 19 | 20 | task(); 21 | } 22 | } 23 | 24 | // the constructor just launches some amount of workers 25 | Threadpool::Threadpool(Threadpool::size_type threads) : stop(false) { 26 | workers.reserve(threads); 27 | 28 | for(Threadpool::size_type i = 0; i < threads; ++i) 29 | workers.emplace_back(Worker(*this)); 30 | } 31 | 32 | // the destructor joins all threads 33 | Threadpool::~Threadpool() { 34 | { 35 | std::unique_lock lock(queue_mutex); 36 | stop = true; 37 | condition.notify_all(); 38 | } 39 | 40 | for(Threadpool::size_type i = 0; i < workers.size(); ++i) { 41 | workers[i].join(); 42 | } 43 | 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Threadpool/COPYING: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Jakob Progsch 2 | 3 | This software is provided 'as-is', without any express or implied 4 | warranty. In no event will the authors be held liable for any damages 5 | arising from the use of this software. 6 | 7 | Permission is granted to anyone to use this software for any purpose, 8 | including commercial applications, and to alter it and redistribute it 9 | freely, subject to the following restrictions: 10 | 11 | 1. The origin of this software must not be misrepresented; you must not 12 | claim that you wrote the original software. If you use this software 13 | in a product, an acknowledgment in the product documentation would be 14 | appreciated but is not required. 15 | 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 19 | 3. This notice may not be removed or altered from any source 20 | distribution. 21 | -------------------------------------------------------------------------------- /src/Threadpool/Makefile: -------------------------------------------------------------------------------- 1 | CXX = g++ 2 | CXXFLAGS = -std=c++11 -Wall -Wextra -O2 3 | LDFLAGS = -lpthread 4 | TARGET = threadpool-example 5 | 6 | 7 | all: $(TARGET) 8 | 9 | 10 | $(TARGET): main.o Threadpool.hpp 11 | $(CXX) $(LDFLAGS) $(CXXFLAGS) main.o -o $(TARGET) 12 | 13 | main.o: main.cpp Threadpool.hpp 14 | $(CXX) $(CXXFLAGS) -c $< 15 | 16 | 17 | clean: 18 | rm -f *.o $(TARGET) 19 | -------------------------------------------------------------------------------- /src/Threadpool/README.md: -------------------------------------------------------------------------------- 1 | ThreadPool 2 | ========== 3 | 4 | A simple C++11 Thread Pool implementation, providing an optional task priority. 5 | 6 | Fork from [Jakob Progsch' repository](https://github.com/progschj/ThreadPool). 7 | 8 | 9 | Possible improvements 10 | --------------------- 11 | 12 | * variadic enqueue, no need for std::bind 13 | * prevent starvation, priority aging 14 | -------------------------------------------------------------------------------- /src/Threadpool/Threadpool.hpp: -------------------------------------------------------------------------------- 1 | #ifndef THREAD_POOL_HPP 2 | #define THREAD_POOL_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | // MODIFICATION: wrap inside namespace ThreadLib 17 | namespace ThreadLib { 18 | 19 | class Threadpool; 20 | 21 | class Worker { 22 | public: 23 | Worker(Threadpool& s) : pool(s) { } 24 | 25 | void operator()(); 26 | 27 | private: 28 | Threadpool& pool; 29 | }; 30 | 31 | class Threadpool { 32 | public: 33 | typedef std::vector::size_type size_type; 34 | 35 | Threadpool() : Threadpool(std::max(1u, std::thread::hardware_concurrency())) { } 36 | Threadpool(size_type); 37 | ~Threadpool(); 38 | 39 | //template auto enqueue(F&& f, int priority = 0) -> std::future(f)())>; 40 | 41 | // add new work item to the pool 42 | template 43 | auto enqueue(F&& f, int priority) -> std::future(f)())> { 44 | typedef decltype(std::forward(f)()) R; 45 | 46 | if(stop) 47 | throw std::runtime_error("enqueue on stopped threadpool"); 48 | 49 | auto task = std::make_shared>(std::forward(f)); 50 | std::future res = task->get_future(); 51 | 52 | { 53 | std::unique_lock lock(queue_mutex); 54 | tasks.emplace(priority, [task]{ (*task)(); }); 55 | } 56 | 57 | condition.notify_one(); 58 | 59 | return res; 60 | } 61 | 62 | private: 63 | friend class Worker; 64 | 65 | // need to keep track of threads so we can join them 66 | std::vector workers; 67 | 68 | typedef std::pair> priority_task; 69 | 70 | // emulate 'nice' 71 | struct task_comp { 72 | bool operator()(const priority_task& lhs, const priority_task& rhs) const { 73 | return lhs.first > rhs.first; 74 | } 75 | }; 76 | 77 | // the prioritized task queue 78 | std::priority_queue, task_comp> tasks; 79 | 80 | // synchronization 81 | std::mutex queue_mutex; 82 | std::condition_variable condition; 83 | bool volatile stop; 84 | }; 85 | } 86 | 87 | #endif 88 | -------------------------------------------------------------------------------- /src/Threadpool/main.cpp.prevent-compile: -------------------------------------------------------------------------------- 1 | // workaround 2 | #define _GLIBCXX_USE_NANOSLEEP 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "Threadpool.hpp" 11 | 12 | 13 | int main() { 14 | // feel free to raise the number of threads; 15 | // or use the default constructor for automatic detection 16 | Threadpool pool(1); 17 | 18 | // dummy task 19 | auto task = [](int priority, int sleep_sec) -> int { 20 | std::cout << "processing task with priority " << priority << " in thread with id " << std::this_thread::get_id() <> results; 29 | 30 | // priority is cycled every 4 tasks, in order to see the prioritizing effect 31 | for(auto i = 0; i < num_tasks; ++i) 32 | results.emplace_back(pool.enqueue(std::bind(task, i % 4, 1))); 33 | 34 | // we need the results here 35 | for(auto i = 0; i < num_tasks; ++i) 36 | std::cout << "result of task " << i << " is " << results[i].get() << std::endl; 37 | } 38 | 39 | /** 40 | * vim: syntax=cpp11 41 | */ 42 | 43 | -------------------------------------------------------------------------------- /src/Threadpool/threadpool-example: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zxytim/fast-gmm/5b6940d62c950889d51d5a3dfc99907e3b631958/src/Threadpool/threadpool-example -------------------------------------------------------------------------------- /src/common.hh: -------------------------------------------------------------------------------- 1 | /* 2 | * $File: common.hh 3 | * $Date: Sun Sep 08 08:35:24 2013 +0800 4 | * $Author: Xinyu Zhou 5 | */ 6 | 7 | #include "type.hh" 8 | #include "dataset.hh" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #define For(i, n) for (__decltype(n) i = 0; i < (n); i ++) 24 | #define Forr(i, l, r) for (__decltype(r) i = (l); i <= (r); i ++) 25 | 26 | /** 27 | * vim: syntax=cpp11 foldmethod=marker 28 | */ 29 | 30 | -------------------------------------------------------------------------------- /src/datamanip.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * $File: datamanip.cc 3 | * $Date: Thu Dec 05 00:08:18 2013 +0000 4 | * $Author: Xinyu Zhou 5 | */ 6 | 7 | #include "datamanip.hh" 8 | 9 | #include "common.hh" 10 | 11 | #include 12 | #include 13 | 14 | using namespace std; 15 | 16 | static const int BUF_SIZE = 65536; 17 | 18 | void read_svm_data(const char *fpath, Dataset &dataset, Labels &labels) { 19 | FILE *fin = fopen(fpath, "r"); 20 | dataset.resize(0); 21 | labels.resize(0); 22 | 23 | char *buf = new char[BUF_SIZE]; 24 | while (fgets(buf, BUF_SIZE, fin) == buf) { 25 | Instance x; 26 | char *ptr; 27 | for (ptr = buf; *ptr; ptr ++) { 28 | if (*ptr == ' ' || *ptr == '\n' || *ptr == '\r') { 29 | *ptr = 0; 30 | int label = atoi(buf); 31 | /* 32 | if (label != 0 && label != 1) { 33 | printf("!!!!%d\n", label); 34 | } 35 | */ 36 | labels.push_back(label); 37 | *ptr = ' '; 38 | break; 39 | } 40 | } 41 | char *last = ptr; 42 | int ind = -1; 43 | double val; 44 | for (; ; ptr ++) { 45 | if (*ptr == ' ' || *ptr == '\n' || *ptr == '\r' || *ptr == 0) { 46 | if (ind != -1) { 47 | char orig = *ptr; 48 | *ptr = 0; 49 | val = atof(last); 50 | x.push_back(make_pair(ind, val)); 51 | *ptr = orig; 52 | ind = -1; 53 | } 54 | last = ptr + 1; 55 | } else if (*ptr == ':') { 56 | *ptr = 0; 57 | ind = atoi(last); 58 | last = ptr + 1; 59 | *ptr = ':'; 60 | } 61 | if (*ptr == 0) 62 | break; 63 | } 64 | dataset.push_back(x); 65 | } 66 | delete [] buf; 67 | fclose(fin); 68 | } 69 | 70 | void read_svm_data(const char *fpath, Dataset &dataset, RealLabels &labels) { 71 | FILE *fin = fopen(fpath, "r"); 72 | dataset.resize(0); 73 | labels.resize(0); 74 | 75 | char *buf = new char[BUF_SIZE]; 76 | while (fgets(buf, BUF_SIZE, fin) == buf) { 77 | Instance x; 78 | char *ptr; 79 | for (ptr = buf; *ptr; ptr ++) { 80 | if (*ptr == ' ' || *ptr == '\n' || *ptr == '\r') { 81 | *ptr = 0; 82 | real_t label = atof(buf); 83 | /* 84 | if (label != 0 && label != 1) { 85 | printf("!!!!%d\n", label); 86 | } 87 | */ 88 | labels.push_back(label); 89 | *ptr = ' '; 90 | break; 91 | } 92 | } 93 | char *last = ptr; 94 | int ind = -1; 95 | double val; 96 | for (; ; ptr ++) { 97 | if (*ptr == ' ' || *ptr == '\n' || *ptr == '\r' || *ptr == 0) { 98 | if (ind != -1) { 99 | char orig = *ptr; 100 | *ptr = 0; 101 | val = atof(last); 102 | x.push_back(make_pair(ind, val)); 103 | *ptr = orig; 104 | ind = -1; 105 | } 106 | last = ptr + 1; 107 | } else if (*ptr == ':') { 108 | *ptr = 0; 109 | ind = atoi(last); 110 | last = ptr + 1; 111 | *ptr = ':'; 112 | } 113 | if (*ptr == 0) 114 | break; 115 | } 116 | dataset.push_back(x); 117 | } 118 | delete [] buf; 119 | fclose(fin); 120 | } 121 | 122 | void print_instance(FILE *fout, const Instance &instance) { 123 | for (auto item: instance) 124 | fprintf(fout, "%d:%lf ", item.first, item.second); 125 | } 126 | 127 | void print_data(FILE *fout, const Dataset &dataset) { 128 | for (auto instance: dataset) { 129 | print_instance(fout, instance); 130 | fprintf(fout, "\n"); 131 | } 132 | } 133 | 134 | void print_data(FILE *fout, const Dataset &dataset, const Labels &labels) { 135 | assert(dataset.size() == labels.size()); 136 | For(i, dataset.size()) { 137 | fprintf(fout, "%d ", labels[i]); 138 | print_instance(fout, dataset[i]); 139 | fprintf(fout, "\n"); 140 | } 141 | } 142 | 143 | void print_data(FILE *fout, const Dataset &dataset, const RealLabels &labels) { 144 | assert(dataset.size() == labels.size()); 145 | For(i, dataset.size()) { 146 | fprintf(fout, "%f ", labels[i]); 147 | print_instance(fout, dataset[i]); 148 | fprintf(fout, "\n"); 149 | } 150 | } 151 | 152 | void print_labels(FILE *fout, const Labels &labels) { 153 | for (auto i: labels) 154 | fprintf(fout, "%d\n", i); 155 | } 156 | 157 | void print_labels(FILE *fout, const RealLabels &labels) { 158 | for (auto i: labels) 159 | fprintf(fout, "%f\n", i); 160 | } 161 | 162 | void get_data_metric(const Dataset &x, int &n, int &m) { 163 | n = x.size(); 164 | m = 0; 165 | for (size_t i = 0; i < x.size(); i ++) { 166 | const Instance &xi = x[i]; 167 | for (size_t j = 0; j < xi.size(); j ++) 168 | if (xi[j].first + 1 > m) 169 | m = xi[j].first + 1; 170 | } 171 | } 172 | 173 | void get_data_metric(const std::vector >&x, int &n, int &m) { 174 | if (x.size() == 0) { 175 | n = m = -1; 176 | return; 177 | } 178 | n = x.size(); 179 | m = x[0].size(); 180 | for (size_t i = 0; i < x.size(); i ++) 181 | if ((int)x[i].size() != m) { 182 | n = m = -1; 183 | break; 184 | } 185 | } 186 | 187 | 188 | 189 | 190 | 191 | /** 192 | * vim: syntax=cpp11 foldmethod=marker 193 | */ 194 | 195 | -------------------------------------------------------------------------------- /src/datamanip.hh: -------------------------------------------------------------------------------- 1 | /* 2 | * $File: datamanip.hh 3 | * $Date: Thu Dec 05 00:08:15 2013 +0000 4 | * $Author: Xinyu Zhou 5 | */ 6 | 7 | #pragma once 8 | 9 | #include "dataset.hh" 10 | 11 | #include 12 | #include 13 | #include "random.hh" 14 | 15 | // integer label 16 | void read_svm_data(const char *fpath, Dataset &dataset, Labels &labels); 17 | void read_svm_data(const char *fpath, Dataset &dataset, RealLabels &labels); 18 | void print_data(FILE *fout, const Dataset &dataset); 19 | void print_data(FILE *fout, const Dataset &dataset, const Labels &labels); 20 | void print_data(FILE *fout, const Dataset &dataset, const RealLabels &labels); 21 | void print_labels(FILE *fout, const Labels &labels); 22 | void print_labels(FILE *fout, const RealLabels &labels); 23 | void print_instance(FILE *fout, const Instance &instance); 24 | 25 | void get_data_metric(const Dataset &x, int &n, int &m); 26 | void get_data_metric(const std::vector >&x, int &n, int &m); 27 | 28 | template 29 | void get_refdata_metric(const Dataset &x, int &n, int &m) { 30 | n = x.size(); 31 | m = 0; 32 | for (size_t i = 0; i < x.size(); i ++) { 33 | auto &xi = *x[i]; 34 | for (size_t j = 0; j < xi.size(); j ++) 35 | if (xi[j].first + 1 > m) 36 | m = xi[j].first + 1; 37 | } 38 | } 39 | 40 | // n_choose == -1 means the same number as dataset.size() 41 | template 42 | void bootstrap_samples(const Dataset_t &dataset, const Labels_t &labels, 43 | Dataset_t &subdataset, Labels_t &sublabels, int n_choose = -1) { 44 | Random random; 45 | assert(dataset.size() == labels.size()); 46 | subdataset.resize(0); sublabels.resize(0); 47 | if (n_choose == -1) 48 | n_choose = dataset.size(); 49 | for (int i = 0; i < n_choose; i ++) { 50 | int index = random.rand_int(dataset.size()); 51 | subdataset.push_back(dataset[index]); 52 | sublabels.push_back(labels[index]); 53 | } 54 | } 55 | 56 | /** 57 | * vim: syntax=cpp11 foldmethod=marker 58 | */ 59 | 60 | -------------------------------------------------------------------------------- /src/dataset.hh: -------------------------------------------------------------------------------- 1 | /* 2 | * $File: dataset.hh 3 | * $Date: Wed Dec 11 16:56:55 2013 +0800 4 | * $Author: Xinyu Zhou 5 | */ 6 | 7 | #pragma once 8 | 9 | #include "type.hh" 10 | 11 | #include 12 | 13 | typedef std::vector > Instance; 14 | typedef std::vector Dataset; 15 | typedef std::vector RefDataset; 16 | typedef std::vector ConstRefDataset; 17 | typedef std::vector Labels; 18 | typedef std::vector RealLabels; 19 | 20 | typedef std::vector Vector; 21 | 22 | /** 23 | * vim: syntax=cpp11 foldmethod=marker 24 | */ 25 | 26 | -------------------------------------------------------------------------------- /src/fastexp.hh: -------------------------------------------------------------------------------- 1 | /* 2 | * $File: fastexp.hh 3 | * $Date: Tue Dec 10 13:46:58 2013 +0800 4 | * $Author: Xinyu Zhou 5 | */ 6 | 7 | #pragma once 8 | 9 | void remez5_0_log2_sse(double *values, int num); 10 | void remez7_0_log2_sse(double *values, int num); 11 | void remez9_0_log2_sse(double *values, int num); 12 | void remez11_0_log2_sse(double *values, int num); 13 | void remez5_0_log2(double *values, int num); 14 | void remez7_0_log2(double *values, int num); 15 | void remez9_0_log2(double *values, int num); 16 | void remez11_0_log2(double *values, int num); 17 | void remez13_0_log2(double *values, int num); 18 | void vecexp_remez5_05_05(double *values, int num); 19 | void vecexp_remez7_05_05(double *values, int num); 20 | void vecexp_remez9_05_05(double *values, int num); 21 | void vecexp_remez11_05_05(double *values, int num); 22 | void vecexp_remez13_05_05(double *values, int num); 23 | void vecexp_taylor5(double *values, int num); 24 | void vecexp_taylor7(double *values, int num); 25 | void vecexp_taylor9(double *values, int num); 26 | void vecexp_taylor11(double *values, int num); 27 | void vecexp_taylor13(double *values, int num); 28 | void vecexp_cephes(double *values, int num); 29 | 30 | /** 31 | * vim: syntax=cpp11 foldmethod=marker 32 | */ 33 | -------------------------------------------------------------------------------- /src/gmm.c.hh: -------------------------------------------------------------------------------- 1 | /* 2 | * $File: gmm.c.hh 3 | * $Date: Tue Dec 10 20:17:50 2013 +0800 4 | * $Author: Xinyu Zhou 5 | */ 6 | 7 | #pragma once 8 | 9 | #include "gmm.hh" 10 | 11 | 12 | /** 13 | * vim: syntax=cpp11 foldmethod=marker 14 | */ 15 | 16 | -------------------------------------------------------------------------------- /src/gmm.hh: -------------------------------------------------------------------------------- 1 | /* 2 | * $File: gmm.hh 3 | * $Date: Wed Dec 11 18:42:55 2013 +0800 4 | * $Author: Xinyu Zhou 5 | */ 6 | 7 | #pragma once 8 | 9 | #include "type.hh" 10 | #include "random.hh" 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | 18 | enum CovType { 19 | COVTYPE_SPHERICAL, 20 | COVTYPE_DIAGONAL, 21 | COVTYPE_FULL 22 | }; 23 | 24 | class Gaussian { 25 | public: 26 | Gaussian(int dim, int covariance_type = COVTYPE_DIAGONAL); 27 | 28 | int dim, covariance_type; 29 | std::vector mean; 30 | std::vector sigma; 31 | std::vector> covariance; // not used 32 | 33 | real_t log_probability_of(std::vector &x); 34 | real_t probability_of(std::vector &x); 35 | real_t probability_of_fast_exp(std::vector &x, double *buffer = NULL); 36 | 37 | // sample a point to @x 38 | void sample(std::vector &x); 39 | std::vector sample(); 40 | 41 | void dump(std::ostream &out); 42 | void load(std::istream &in); 43 | 44 | Random random; 45 | int fast_gaussian_dim; 46 | }; 47 | 48 | class GMM; 49 | class GMMTrainer { 50 | public: 51 | virtual void train(GMM *gmm, std::vector> &X) = 0; 52 | virtual ~GMMTrainer() {} 53 | }; 54 | 55 | class GMMTrainerBaseline : public GMMTrainer { 56 | public: 57 | GMMTrainerBaseline(int nr_iter = 10, real_t min_covar = 1e-3, real_t threshold = 0.01, 58 | int init_with_kmeans = 1, int concurrency = 1, 59 | int verbosity = 0); 60 | virtual void train(GMM *gmm, std::vector> &X); 61 | void clear_gaussians(); 62 | 63 | // init gaussians along with its weight 64 | virtual void init_gaussians(std::vector> &X); 65 | 66 | virtual void iteration(std::vector> &X); 67 | 68 | int dim; 69 | 70 | Random random; 71 | GMM *gmm; 72 | 73 | int nr_iter; 74 | real_t min_covar; 75 | real_t threshold; 76 | 77 | int init_with_kmeans; 78 | 79 | int concurrency; 80 | int verbosity; 81 | 82 | std::vector> prob_of_y_given_x; // y, x 83 | std::vector N_k; 84 | }; 85 | 86 | class GMM { 87 | public: 88 | GMM(int nr_mixtures, int covariance_type = COVTYPE_DIAGONAL, 89 | GMMTrainer *trainer = NULL); 90 | GMM(const std::string &model_file); 91 | ~GMM(); 92 | 93 | template 94 | void fit(std::vector &X) { 95 | bool new_trainer = false; 96 | if (trainer == NULL) { 97 | trainer = new GMMTrainerBaseline(); 98 | new_trainer = true; 99 | } 100 | trainer->train(this, X); 101 | if (new_trainer) 102 | delete trainer; 103 | } 104 | 105 | void dump(std::ostream &out); 106 | void load(std::istream &in); 107 | 108 | int nr_mixtures; 109 | int covariance_type; 110 | 111 | int dim; 112 | GMMTrainer *trainer; 113 | 114 | std::vector weights; 115 | std::vector gaussians; 116 | 117 | real_t log_probability_of(std::vector &x); 118 | real_t log_probability_of(std::vector> &X); 119 | 120 | real_t log_probability_of_fast_exp(std::vector &x, double *buffer = NULL); 121 | real_t log_probability_of_fast_exp(std::vector> &X, double *buffer = NULL); 122 | real_t log_probability_of_fast_exp_threaded(std::vector> &X, int concurrency); 123 | void log_probability_of_fast_exp_threaded( 124 | std::vector> &X, std::vector &prob_out, int concurrency); 125 | 126 | 127 | real_t probability_of(std::vector &x); 128 | 129 | void normalize_weights(); 130 | 131 | }; 132 | 133 | /** 134 | * vim: syntax=cpp11 foldmethod=marker 135 | */ 136 | 137 | -------------------------------------------------------------------------------- /src/helper.hh: -------------------------------------------------------------------------------- 1 | /* 2 | * $File: helper.hh 3 | * $Date: Mon Aug 19 21:28:30 2013 +0000 4 | * $Author: Xinyu Zhou 5 | */ 6 | 7 | #pragma once 8 | 9 | #include "dataset.hh" 10 | void dataset2constrefdataset(const Dataset &dataset, ConstRefDataset &constrefdataset); 11 | 12 | 13 | /** 14 | * vim: syntax=cpp11 foldmethod=marker 15 | */ 16 | 17 | -------------------------------------------------------------------------------- /src/kmeans++.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * $File: kmeans++.cc 3 | * $Date: Wed Dec 11 17:36:56 2013 +0800 4 | * $Author: Xinyu Zhou 5 | */ 6 | 7 | #include "kmeans++.hh" 8 | #include "Threadpool/Threadpool.hpp" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | using ThreadLib::Threadpool; 19 | 20 | using namespace std; 21 | 22 | static void analyse_dataset(const Dataset &dataset, int &n, int &m) { 23 | n = dataset.size(); 24 | m = 0; 25 | for (auto point: dataset) 26 | for (auto dim: point) 27 | if (dim.first > m) 28 | m = dim.first; 29 | m ++; 30 | } 31 | 32 | KMeansppSolver::KMeansppSolver(int concurrency) : 33 | KMeansSolver(concurrency) { 34 | } 35 | 36 | static void Instance2Vector(const Instance &instance, Vector &ret, int dim) { 37 | ret.resize(dim); 38 | for (auto &item: instance) 39 | ret[item.first] = item.second; 40 | } 41 | 42 | static void Vector2Instance(const Vector &vec, Instance &instance) { 43 | instance.resize(0); 44 | for (size_t i = 0; i < vec.size(); i ++) { 45 | real_t coord = vec[i]; 46 | if (fabs(coord) < 1e-15) 47 | continue; 48 | instance.emplace_back(make_pair(i, coord)); 49 | } 50 | } 51 | namespace KMeansppSolverImpl { 52 | real_t distancesqr(const Instance &inst, const Vector &point) { 53 | real_t dist = 0; 54 | for (auto &item: inst) { 55 | real_t delta = item.second - point[item.first]; 56 | dist += delta * delta; 57 | } 58 | return dist; 59 | } 60 | 61 | real_t update_distances( 62 | const Dataset &dataset, 63 | const Vector ¢roid, 64 | vector &distances, 65 | int begin, int end) { 66 | 67 | real_t distsqr_sum = 0; 68 | 69 | for (int i = begin; i < end; i ++) { 70 | const Instance &inst = dataset[i]; 71 | real_t &min_distsqr = distances[i]; 72 | real_t distsqr = distancesqr(inst, centroid); 73 | min_distsqr = min(min_distsqr, distsqr); 74 | distsqr_sum += min_distsqr; 75 | } 76 | return distsqr_sum; 77 | } 78 | 79 | real_t update_distances_weighted ( 80 | const Dataset &dataset, 81 | const Vector ¢roid, 82 | const vector &weight, 83 | vector &distances, 84 | int begin, int end) { 85 | 86 | real_t distsqr_sum = 0; 87 | 88 | for (int i = begin; i < end; i ++) { 89 | const Instance &inst = dataset[i]; 90 | real_t &min_distsqr = distances[i]; 91 | real_t distsqr = distancesqr(inst, centroid) * weight[i]; 92 | min_distsqr = min(min_distsqr, distsqr); 93 | distsqr_sum += min_distsqr; 94 | } 95 | return distsqr_sum; 96 | } 97 | } 98 | 99 | using namespace KMeansppSolverImpl; 100 | 101 | 102 | real_t KMeansppSolver::cluster(const Dataset &dataset, std::vector ¢roids, int K) { 103 | // trivial initialization 104 | int n, m; 105 | analyse_dataset(dataset, n, m); 106 | centroids.resize(K); 107 | for (auto &p: centroids) 108 | p.resize(m); 109 | 110 | printf("kmeans++ initializing ...\n"); 111 | 112 | // initial cluster with one random point 113 | Instance2Vector(dataset[random.rand_int() % n], centroids[0], m); 114 | 115 | vector distances(n); 116 | // initialize distances to large numbers 117 | for (auto &d: distances) d = numeric_limits::max(); 118 | 119 | Threadpool pool(concurrency); 120 | int block_size = ceil((double)n / (concurrency)); 121 | for (int k = 1; k < K; k ++) { 122 | // calculate distances 123 | vector> results; 124 | for (int i = 0, c = 0; i < n; i += block_size, c ++) { 125 | assert(c < concurrency); 126 | results.emplace_back(pool.enqueue(bind(update_distances, 127 | std::cref(dataset), 128 | std::cref(centroids[k - 1]), 129 | std::ref(distances), 130 | i, min(i + block_size, n)), 0)); 131 | } 132 | 133 | real_t distsqr_sum = 0; 134 | for (auto &rst: results) 135 | distsqr_sum += rst.get(); 136 | 137 | #ifdef __DEBUG_CHECK 138 | real_t distsqr_sum_check = 0; 139 | for (auto &d: distances) distsqr_sum_check += d; 140 | assert(distsqr_sum_check == distsqr_sum); 141 | #endif 142 | 143 | real_t random_weight = random.rand_int() / (double)RAND_MAX * distsqr_sum; 144 | for (int i = 0; i < n; i ++) { 145 | random_weight -= distances[i]; 146 | if (random_weight <= 0) { 147 | Instance2Vector(dataset[i], centroids[k], m); 148 | printf("kmeans++ iteration %3d: %f, #%d has been choosen\n", k, distsqr_sum, i); fflush(stdout); 149 | break; 150 | } 151 | } 152 | } 153 | 154 | return Lloyds_iteration(dataset, centroids); 155 | } 156 | 157 | real_t KMeansppSolver::cluster_weighted( 158 | const Dataset &dataset, const std::vector &weight, 159 | std::vector ¢roids, int K) { 160 | 161 | // trivial initialization 162 | int n, m; 163 | analyse_dataset(dataset, n, m); 164 | centroids.resize(K); 165 | for (auto &p: centroids) 166 | p.resize(m); 167 | 168 | printf("kmeans++ initializing ...\n"); 169 | 170 | // initial cluster with one random point 171 | Instance2Vector(dataset[random.rand_int() % n], centroids[0], m); 172 | 173 | vector distances(n); 174 | // initialize distances to large numbers 175 | for (auto &d: distances) d = numeric_limits::max(); 176 | 177 | Threadpool pool(concurrency); 178 | int block_size = ceil((double)n / (concurrency)); 179 | for (int k = 1; k < K; k ++) { 180 | // calculate distances 181 | vector> results; 182 | for (int i = 0, c = 0; i < n; i += block_size, c ++) { 183 | assert(c < concurrency); 184 | results.emplace_back(pool.enqueue(bind(update_distances_weighted, 185 | std::cref(dataset), 186 | std::cref(centroids[k - 1]), 187 | std::cref(weight), 188 | std::ref(distances), 189 | i, min(i + block_size, n)), 0)); 190 | } 191 | 192 | real_t distsqr_sum = 0; 193 | for (auto &rst: results) 194 | distsqr_sum += rst.get(); 195 | 196 | #ifdef __DEBUG_CHECK 197 | real_t distsqr_sum_check = 0; 198 | for (auto &d: distances) distsqr_sum_check += d; 199 | assert(distsqr_sum_check == distsqr_sum); 200 | #endif 201 | 202 | real_t random_weight = random.rand_int() / (double)RAND_MAX * distsqr_sum; 203 | for (int i = 0; i < n; i ++) { 204 | random_weight -= distances[i]; 205 | if (random_weight <= 0) { 206 | Instance2Vector(dataset[i], centroids[k], m); 207 | printf("kmeans++ iteration %3d: %f, #%d has been choosen\n", k, distsqr_sum, i); fflush(stdout); 208 | break; 209 | } 210 | } 211 | } 212 | 213 | return Lloyds_iteration_weighted(dataset, weight, centroids); 214 | } 215 | 216 | real_t KMeansppSolver::cluster_weighted(const std::vector &dataset, const std::vector &weight, 217 | std::vector ¢roids, int K) { 218 | if (dataset.size() == 0) { 219 | printf("[WARNING] no data given"); 220 | return 0; 221 | } 222 | // TODO: not to waste that much memory, write start from scratch 223 | Dataset inst_dataset(dataset.size()); 224 | for (size_t i = 0; i < dataset.size(); i ++) 225 | Vector2Instance(dataset[i], inst_dataset[i]); 226 | 227 | return cluster_weighted(inst_dataset, weight, centroids, K); 228 | } 229 | -------------------------------------------------------------------------------- /src/kmeans++.hh: -------------------------------------------------------------------------------- 1 | /* 2 | * $File: kmeans++.hh 3 | * $Date: Wed Dec 11 17:36:01 2013 +0800 4 | * $Author: Xinyu Zhou 5 | */ 6 | 7 | #pragma once 8 | #include "dataset.hh" 9 | #include "kmeans.hh" 10 | #include "random.hh" 11 | 12 | /** 13 | * A KMeans++ clustering algorithm 14 | */ 15 | class KMeansppSolver : public KMeansSolver { 16 | public: 17 | /** 18 | * number of parallel workers. 19 | */ 20 | KMeansppSolver(int concurrency); 21 | 22 | /** 23 | * cluster point in dataset into K partitions 24 | * situation when K <= dataset.size() should be correctly dealt with 25 | */ 26 | virtual real_t cluster(const Dataset &dataset, std::vector ¢roids, int K); 27 | virtual real_t cluster_weighted(const Dataset &dataset, const std::vector &weight, 28 | std::vector ¢roids, int K); 29 | virtual real_t cluster_weighted(const std::vector &dataset, const std::vector &weight, 30 | std::vector ¢roids, int K); 31 | 32 | Random random; 33 | 34 | }; 35 | 36 | 37 | /** 38 | * vim: syntax=cpp11 foldmethod=marker 39 | */ 40 | 41 | -------------------------------------------------------------------------------- /src/kmeans.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * $File: kmeans.cc 3 | * $Date: Wed Dec 11 17:12:03 2013 +0800 4 | * $Author: Xinyu Zhou 5 | */ 6 | 7 | #include "kmeans.hh" 8 | #include "Threadpool/Threadpool.hpp" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | using ThreadLib::Threadpool; 18 | 19 | using namespace std; 20 | 21 | static void analyse_dataset(const Dataset &dataset, int &n, int &m) { 22 | n = dataset.size(); 23 | m = 0; 24 | for (auto point: dataset) 25 | for (auto dim: point) 26 | if (dim.first > m) 27 | m = dim.first; 28 | m ++; 29 | } 30 | 31 | KMeansSolver::KMeansSolver(int concurrency) { 32 | this->concurrency = concurrency; 33 | } 34 | 35 | static void Instance2Vector(const Instance &instance, Vector &ret, int dim) { 36 | ret.resize(dim); 37 | for (auto &item: instance) 38 | ret[item.first] = item.second; 39 | } 40 | 41 | real_t KMeansSolver::cluster(const Dataset &dataset, std::vector ¢roids, int K) { 42 | // trivial initialization 43 | int n, m; 44 | analyse_dataset(dataset, n, m); 45 | centroids.resize(K); 46 | for (auto &p: centroids) 47 | p.resize(m); 48 | 49 | // randomly choose K points with equal probability 50 | vector perm(min(n, K)); 51 | for (int i = 0; i < n && i < K; i ++) perm[i] = i; 52 | random_shuffle(perm.begin(), perm.end()); 53 | for (int i = 0; i < n && i < K; i ++) 54 | Instance2Vector(dataset[i], centroids[i], m); 55 | 56 | return Lloyds_iteration(dataset, centroids); 57 | } 58 | 59 | namespace KMeansSolverImpl { 60 | 61 | real_t distancesqr(const Instance &inst, const Vector &point) { 62 | real_t dist = 0; 63 | for (auto &item: inst) { 64 | real_t delta = item.second - point[item.first]; 65 | dist += delta * delta; 66 | } 67 | return dist; 68 | } 69 | 70 | // return distsqr sum 71 | real_t calc_belonging(const Dataset &dataset, 72 | const vector ¢roids, 73 | vector &new_centroids, // this parameter is exclusive 74 | vector &cluster_size, // this parameter is exclusive 75 | int begin, int end) { 76 | 77 | // initialize 78 | for (auto &i: cluster_size) i = 0; 79 | for (auto &vec: new_centroids) 80 | for (auto &point: vec) 81 | point = 0; 82 | 83 | 84 | real_t distsqr_sum = 0; 85 | 86 | for (int i = begin; i < end; i ++) { 87 | const Instance &inst = dataset[i]; 88 | real_t min_distsqr = numeric_limits::max(); 89 | int min_dist_id = -1; 90 | for (size_t j = 0; j < centroids.size(); j ++) { // K 91 | auto &vec = centroids[j]; 92 | real_t distsqr = distancesqr(inst, vec); 93 | if (distsqr < min_distsqr) { 94 | min_distsqr = distsqr; 95 | min_dist_id = j; 96 | } 97 | } 98 | 99 | cluster_size[min_dist_id] += 1; 100 | auto ¢roid = new_centroids[min_dist_id]; 101 | for (auto &item: inst) 102 | centroid[item.first] += item.second; 103 | distsqr_sum += min_distsqr; 104 | } 105 | return distsqr_sum; 106 | } 107 | 108 | real_t calc_belonging_weighted(const Dataset &dataset, 109 | const vector ¢roids, 110 | const vector &weight, 111 | vector &new_centroids, // this parameter is exclusive 112 | vector &cluster_size, // this parameter is exclusive 113 | int begin, int end) { 114 | 115 | // initialize 116 | for (auto &i: cluster_size) i = 0; 117 | for (auto &vec: new_centroids) 118 | for (auto &point: vec) 119 | point = 0; 120 | 121 | 122 | real_t distsqr_sum = 0; 123 | 124 | for (int i = begin; i < end; i ++) { 125 | const Instance &inst = dataset[i]; 126 | real_t min_distsqr = numeric_limits::max(); 127 | int min_dist_id = -1; 128 | for (size_t j = 0; j < centroids.size(); j ++) { // K 129 | auto &vec = centroids[j]; 130 | real_t distsqr = distancesqr(inst, vec) * weight[i]; 131 | if (distsqr < min_distsqr) { 132 | min_distsqr = distsqr; 133 | min_dist_id = j; 134 | } 135 | } 136 | 137 | cluster_size[min_dist_id] += weight[i]; 138 | auto ¢roid = new_centroids[min_dist_id]; 139 | for (auto &item: inst) 140 | centroid[item.first] += item.second * weight[i]; 141 | distsqr_sum += min_distsqr; 142 | } 143 | return distsqr_sum; 144 | } 145 | } 146 | 147 | using namespace KMeansSolverImpl; 148 | 149 | real_t KMeansSolver::Lloyds_iteration( 150 | const Dataset &dataset, std::vector ¢roids) { 151 | 152 | printf("entering Lloyds_iteration\n"); fflush(stdout); 153 | 154 | Threadpool p(concurrency); 155 | int n = dataset.size(); 156 | int m = centroids[0].size(); 157 | int K = centroids.size(); 158 | 159 | vector centroids_best; 160 | real_t distsqr_best = numeric_limits::max(); 161 | 162 | vector belong(n); 163 | 164 | int block_size = ceil((double)n / concurrency); 165 | 166 | vector> cluster_size_buf(concurrency, vector(K)); 167 | vector> centroids_buf(concurrency, vector(K, Vector(m))); 168 | 169 | real_t last_distsqr_sum = numeric_limits::max(); 170 | const int n_iter_max = 200; 171 | for (int iter_id = 0; iter_id < n_iter_max; iter_id ++) { 172 | vector> results; 173 | // Calculate belonging 174 | for (int i = 0, c = 0; i < n; i += block_size, c ++) { 175 | assert(c < concurrency); 176 | results.emplace_back(p.enqueue(bind(calc_belonging, 177 | std::cref(dataset), 178 | std::cref(centroids), std::ref(centroids_buf[c]), 179 | std::ref(cluster_size_buf[c]), 180 | i, min(n, i + block_size)), 0)); 181 | } 182 | 183 | real_t distsqr_sum = 0; 184 | for (auto &rst: results) 185 | distsqr_sum += rst.get(); 186 | 187 | if (distsqr_sum < distsqr_best) { 188 | distsqr_best = distsqr_sum; 189 | centroids_best = centroids; 190 | } 191 | printf("iteration %3d: %f\n", iter_id, distsqr_sum); fflush(stdout); 192 | if (fabs(last_distsqr_sum - distsqr_sum) < 1e-6) { // || fabs(distsqr_sum - last_distsqr_sum) / last_distsqr_sum < 1e-6) 193 | printf("distance squared sum not changing, converged.\n"); 194 | break; 195 | } 196 | 197 | const real_t terminate_cost_factor = 1.5; 198 | if (distsqr_sum > distsqr_best * terminate_cost_factor) { 199 | printf("distance square sum %f is worse than best found by a factor of %f. ternimating.\n", distsqr_sum, terminate_cost_factor); 200 | break; 201 | } 202 | 203 | 204 | // aggregate cluster_size 205 | vector cluster_size(K); 206 | for (auto &cs: cluster_size_buf) { 207 | assert(cs.size() == (size_t)K); 208 | for (int i = 0; i < K; i ++) 209 | cluster_size[i] += cs[i]; 210 | } 211 | 212 | for (auto &point: centroids) 213 | for (auto &coord: point) 214 | coord = 0; 215 | 216 | // aggregate centroids 217 | for (auto ctrds: centroids_buf) { 218 | assert(ctrds.size() == (size_t)K); 219 | assert(centroids.size() == (size_t)K); 220 | for (int i = 0; i < K; i ++) { // id of centroid 221 | assert(centroids[i].size() == (size_t)m); 222 | assert(ctrds[i].size() == (size_t)m); 223 | for (int j = 0; j < m; j ++) // coord index 224 | centroids[i][j] += ctrds[i][j]; 225 | } 226 | } 227 | 228 | // compute new centroids 229 | for (int i = 0; i < K; i ++) 230 | for (int j = 0; j < m; j ++) 231 | centroids[i][j] /= (real_t)cluster_size[i]; 232 | 233 | last_distsqr_sum = distsqr_sum; 234 | 235 | if (iter_id == n_iter_max - 1) { 236 | printf("max number of iterations(%d) reached, quit iteration\n", n_iter_max); fflush(stdout); 237 | } 238 | } 239 | 240 | centroids = centroids_best; 241 | printf("minimum distance squared sum(Lloyds_iteration): %f\n", distsqr_best); fflush(stdout); 242 | 243 | return distsqr_best; 244 | } 245 | 246 | 247 | real_t KMeansSolver::Lloyds_iteration_weighted( 248 | const Dataset &dataset, const std::vector &weight, 249 | std::vector ¢roids) { 250 | 251 | printf("entering Lloyds_iteration_weighted\n"); fflush(stdout); 252 | 253 | Threadpool p(concurrency); 254 | int n = dataset.size(); 255 | 256 | 257 | int m = centroids[0].size(); 258 | int K = centroids.size(); 259 | 260 | vector centroids_best; 261 | real_t distsqr_best = numeric_limits::max(); 262 | 263 | vector belong(n); 264 | 265 | int block_size = ceil((double)n / concurrency); 266 | 267 | vector> cluster_size_buf(concurrency, vector(K)); 268 | vector> centroids_buf(concurrency, vector(K, Vector(m))); 269 | 270 | const int n_iter_max = 200; 271 | 272 | real_t last_distsqr_sum = numeric_limits::max(); 273 | for (int iter_id = 0; iter_id < n_iter_max; iter_id ++) { 274 | vector> results; 275 | // Calculate belonging 276 | for (int i = 0, c = 0; i < n; i += block_size, c ++) { 277 | assert(c < concurrency); 278 | results.emplace_back(p.enqueue(bind(calc_belonging_weighted, 279 | std::cref(dataset), 280 | std::cref(centroids), 281 | std::cref(weight), 282 | std::ref(centroids_buf[c]), 283 | std::ref(cluster_size_buf[c]), 284 | i, min(n, i + block_size)), 0)); 285 | } 286 | 287 | real_t distsqr_sum = 0; 288 | for (auto &rst: results) 289 | distsqr_sum += rst.get(); 290 | 291 | if (distsqr_sum < distsqr_best) { 292 | distsqr_best = distsqr_sum; 293 | centroids_best = centroids; 294 | } 295 | 296 | printf("iteration %3d: %f\n", iter_id, distsqr_sum); fflush(stdout); 297 | if (fabs(last_distsqr_sum - distsqr_sum) < 1e-6)// || fabs(distsqr_sum - last_distsqr_sum) / last_distsqr_sum < 1e-6) 298 | break; 299 | 300 | // aggregate cluster_size 301 | vector cluster_size(K); 302 | for (auto &cs: cluster_size_buf) { 303 | assert(cs.size() == (size_t)K); 304 | for (int i = 0; i < K; i ++) 305 | cluster_size[i] += cs[i]; 306 | } 307 | 308 | for (auto &point: centroids) 309 | for (auto &coord: point) 310 | coord = 0; 311 | 312 | // aggregate centroids 313 | for (auto ctrds: centroids_buf) { 314 | assert(ctrds.size() == (size_t)K); 315 | assert(centroids.size() == (size_t)K); 316 | for (int i = 0; i < K; i ++) { // id of centroid 317 | assert(centroids[i].size() == (size_t)m); 318 | assert(ctrds[i].size() == (size_t)m); 319 | for (int j = 0; j < m; j ++) // coord index 320 | centroids[i][j] += ctrds[i][j]; 321 | } 322 | } 323 | 324 | // compute new centroids 325 | for (int i = 0; i < K; i ++) 326 | for (int j = 0; j < m; j ++) 327 | centroids[i][j] /= cluster_size[i]; 328 | 329 | last_distsqr_sum = distsqr_sum; 330 | 331 | if (iter_id == n_iter_max - 1) { 332 | printf("max number of iterations(%d) reached, quit iteration\n", n_iter_max); fflush(stdout); 333 | } 334 | } 335 | 336 | centroids = centroids_best; 337 | printf("minimum distance squared sum(Lloyds_iteration_weighted): %f\n", distsqr_best); fflush(stdout); 338 | return distsqr_best; 339 | } 340 | 341 | 342 | /** 343 | * vim: syntax=cpp11 foldmethod=marker 344 | */ 345 | 346 | -------------------------------------------------------------------------------- /src/kmeans.hh: -------------------------------------------------------------------------------- 1 | /* 2 | * $File: kmeans.hh 3 | * $Date: Wed Dec 11 19:03:51 2013 +0800 4 | * $Author: Xinyu Zhou 5 | */ 6 | 7 | #pragma once 8 | #include "dataset.hh" 9 | 10 | /** 11 | * A KMeans clustering algorithm 12 | */ 13 | class KMeansSolver { 14 | public: 15 | /** 16 | * number of parallel workers. 17 | * TODO: 18 | * @threshold_relative stop when the ratio between cost reduction 19 | * and cost is less than @threshold_relative, default 0.0001 20 | */ 21 | KMeansSolver(int concurrency); 22 | 23 | /** 24 | * cluster point in dataset into K partitions 25 | * situation when K <= dataset.size() should be correctly dealt with 26 | */ 27 | virtual real_t cluster(const Dataset &dataset, std::vector ¢roids, int K); 28 | 29 | /** 30 | * iteration step 31 | */ 32 | real_t Lloyds_iteration(const Dataset &dataset, std::vector ¢roids); 33 | real_t Lloyds_iteration_weighted(const Dataset &dataset, const std::vector &weight, 34 | std::vector ¢roids); 35 | 36 | protected: 37 | int concurrency; 38 | }; 39 | 40 | 41 | /** 42 | * vim: syntax=cpp11 foldmethod=marker 43 | */ 44 | 45 | -------------------------------------------------------------------------------- /src/kmeansII.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * $File: kmeansII.cc 3 | * $Date: Wed Dec 11 18:52:25 2013 +0800 4 | * $Author: Xinyu Zhou 5 | */ 6 | 7 | #include "kmeansII.hh" 8 | #include "kmeans++.hh" 9 | #include "Threadpool/Threadpool.hpp" 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | using ThreadLib::Threadpool; 20 | 21 | using namespace std; 22 | 23 | static void analyse_dataset(const Dataset &dataset, int &n, int &m) { 24 | n = dataset.size(); 25 | m = 0; 26 | for (auto point: dataset) 27 | for (auto dim: point) 28 | if (dim.first > m) 29 | m = dim.first; 30 | m ++; 31 | } 32 | 33 | KMeansIISolver::KMeansIISolver(int concurrency, real_t oversampling_factor, real_t size_factor) : 34 | KMeansSolver(concurrency), oversampling_factor(oversampling_factor), size_factor(size_factor) { 35 | } 36 | 37 | static void Instance2Vector(const Instance &instance, Vector &ret, int dim) { 38 | ret.resize(dim); 39 | for (auto &item: instance) 40 | ret[item.first] = item.second; 41 | } 42 | 43 | namespace KMeansIISolverImpl { 44 | 45 | real_t distancesqr(const Instance &inst, const Vector &point) { 46 | real_t dist = 0; 47 | for (auto &item: inst) { 48 | real_t delta = item.second - point[item.first]; 49 | dist += delta * delta; 50 | } 51 | return dist; 52 | } 53 | 54 | real_t update_distances( 55 | const Dataset &dataset, 56 | const vector ¢roids, 57 | int centroid_begin, int centroid_end, 58 | vector &distances, 59 | vector &belong, 60 | int begin, int end) { 61 | 62 | real_t distsqr_sum = 0; 63 | 64 | for (int i = begin; i < end; i ++) { 65 | const Instance &inst = dataset[i]; 66 | real_t &min_distsqr = distances[i]; 67 | for (int j = centroid_begin; j < centroid_end; j ++) { 68 | real_t distsqr = distancesqr(inst, centroids[j]); 69 | if (distsqr < min_distsqr) { 70 | min_distsqr = distsqr; 71 | belong[i] = j; 72 | } 73 | } 74 | distsqr_sum += min_distsqr; 75 | } 76 | return distsqr_sum; 77 | } 78 | } 79 | 80 | using namespace KMeansIISolverImpl; 81 | 82 | real_t KMeansIISolver::cluster(const Dataset &dataset, std::vector ¢roids_param, int K) { 83 | // trivial initialization 84 | int n, m; 85 | analyse_dataset(dataset, n, m); 86 | centroids_param.resize(K); 87 | for (auto &p: centroids_param) 88 | p.resize(m); 89 | 90 | printf("kmeansII initializing ...\n"); 91 | 92 | // initial cluster with one random point 93 | std::vector centroids(1, centroids_param[0]); 94 | Instance2Vector(dataset[rand() % n], centroids[0], m); 95 | 96 | vector distances(n); 97 | vector belong(n); 98 | // initialize distances to large numbers 99 | for (auto &d: distances) d = numeric_limits::max(); 100 | 101 | 102 | int block_size = ceil((double)n / (concurrency)); 103 | 104 | // guard for thread pool 105 | { 106 | int last_size = 0; 107 | Threadpool pool(concurrency); 108 | int iter_id = 0; 109 | while (true) { 110 | // calculate distances 111 | vector> results; 112 | for (int i = 0, c = 0; i < n; i += block_size, c ++) { 113 | assert(c < concurrency); 114 | 115 | results.emplace_back(pool.enqueue(bind(update_distances, 116 | std::cref(dataset), 117 | std::cref(centroids), 118 | last_size, centroids.size(), 119 | std::ref(distances), 120 | std::ref(belong), 121 | i, min(i + block_size, n)), 0)); 122 | } 123 | if (centroids.size() > size_factor * K) 124 | break; 125 | 126 | real_t distsqr_sum = 0; 127 | for (auto &rst: results) 128 | distsqr_sum += rst.get(); 129 | 130 | #ifdef __DEBUG_CHECK 131 | real_t distsqr_sum_check = 0; 132 | for (auto &d: distances) distsqr_sum_check += d; 133 | assert(distsqr_sum_check == distsqr_sum); 134 | #endif 135 | last_size = centroids.size(); 136 | 137 | for (int i = 0; i < n; i ++) { 138 | real_t random_weight = rand() / (double)RAND_MAX * distsqr_sum; 139 | if (random_weight < distances[i] * oversampling_factor * K) { 140 | centroids.emplace_back(Vector()); 141 | Instance2Vector(dataset[i], centroids.back(), m); 142 | } 143 | } 144 | 145 | printf("kmeansII iteration %3d: %f, #new: %lu, #all: %lu\n", 146 | iter_id, distsqr_sum, centroids.size() - last_size, centroids.size()); 147 | fflush(stdout); 148 | 149 | if (centroids.size() - last_size == 0) 150 | break; 151 | iter_id ++; 152 | } 153 | 154 | } 155 | 156 | while (centroids.size() <= size_factor * K) { 157 | centroids.emplace_back(Vector()); 158 | Instance2Vector(dataset[random.rand_int(n)], centroids.back(), m); 159 | } 160 | // calculate weight 161 | vector weight(centroids.size()); 162 | for (auto &bl: belong) 163 | weight[bl] += 1.0; 164 | 165 | // weighted clustering 166 | KMeansppSolver kmeanspp_solver(concurrency); 167 | kmeanspp_solver.cluster_weighted(centroids, weight, centroids_param, K); 168 | 169 | return Lloyds_iteration(dataset, centroids_param); 170 | } 171 | 172 | -------------------------------------------------------------------------------- /src/kmeansII.hh: -------------------------------------------------------------------------------- 1 | /* 2 | * $File: kmeansII.hh 3 | * $Date: Wed Dec 11 18:52:39 2013 +0800 4 | * $Author: Xinyu Zhou 5 | */ 6 | 7 | #pragma once 8 | #include "dataset.hh" 9 | #include "kmeans.hh" 10 | #include "random.hh" 11 | 12 | /** 13 | * A KMeans++ clustering algorithm 14 | */ 15 | class KMeansIISolver : public KMeansSolver { 16 | public: 17 | /** 18 | * oversampling factor and number of parallel workers. 19 | * see [1] for explanation, although the definition 20 | * is not quite the same: l_orig = l_here * K 21 | * 22 | * number of rounds for sampling is not presented here, as 23 | * it is substituted by sampling_size_factor, by which means as long as 24 | * the number of points sampled is less than size_factor * K, 25 | * we'll continue sampling. 26 | * [1] Bahmani, B., Moseley, B., Vattani, A., Kumar, R., & Vassilvitskii, S. (2012). 27 | * Scalable k-means++. Proceedings of the VLDB Endowment, 5(7), 622-633. 28 | */ 29 | KMeansIISolver(int concurrency, real_t oversampling_factor = 2.0, real_t sampling_size_factor = 2.0); 30 | 31 | /** 32 | * cluster point in dataset into K partitions 33 | * situation when K <= dataset.size() should be correctly dealt with 34 | */ 35 | virtual real_t cluster(const Dataset &dataset, std::vector ¢roids, int K); 36 | 37 | protected: 38 | real_t oversampling_factor, 39 | size_factor; 40 | 41 | Random random; 42 | }; 43 | 44 | 45 | /** 46 | * vim: syntax=cpp11 foldmethod=marker 47 | */ 48 | 49 | -------------------------------------------------------------------------------- /src/main.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * $File: main.cc 3 | * $Date: Wed Dec 11 19:00:29 2013 +0800 4 | * $Author: Xinyu Zhou 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | #include "gmm.hh" 11 | 12 | #include "datamanip.hh" 13 | #include "common.hh" 14 | 15 | #include "tclap/CmdLine.h" 16 | 17 | using namespace std; 18 | using namespace TCLAP; 19 | 20 | typedef std::vector> DenseDataset; 21 | 22 | vector string_to_double_vector(string line) { 23 | vector x; 24 | int begin = 0, end = 0; 25 | int len = line.size(); 26 | while (true) { 27 | while (end < len && line[end] != ' ' && line[end] != '\n') 28 | end ++; 29 | x.push_back(atof(line.substr(begin, end - begin).c_str())); 30 | if (end == len - 1 || line[end] == '\n' || (end == len - 2 && line[end] == ' ' && line[end] == '\n')) 31 | break; 32 | begin = end + 1; 33 | end = begin; 34 | } 35 | return x; 36 | } 37 | 38 | struct Args { 39 | int init_with_kmeans; 40 | int concurrency; 41 | int K; 42 | int iteration; 43 | real_t min_covar = 1e-3; 44 | 45 | string input_file; 46 | string model_file; 47 | }; 48 | 49 | Args parse_args(int argc, char *argv[]) { 50 | Args args; 51 | try { 52 | CmdLine cmd("Gaussian Mixture Model (GMM)", ' ', "0.0.1"); 53 | 54 | ValueArg arg_init_with_kmeans("f", "kmeans", "init_with_kmeans", false, 1, "NUMBER"); 55 | ValueArg arg_concurrency("w", "concurrency", "number of workers", false, 1, "NUMBER"); 56 | ValueArg arg_K("k", "K", "number of gaussians", true, 10, "NUMBER"); 57 | ValueArg arg_min_covar("c", "mincovar", "minimum covariance to avoid overfitting, default 1e-3.", false, 1e-3, "FLOAT"); 58 | 59 | ValueArg arg_input_file("i", "input", "intput file", true, "", "FILE"); 60 | ValueArg arg_model_file("m", "model", "model file", true, "", "FILE"); 61 | ValueArg arg_iteration("r", "iteration", "number of iterations", 62 | false, 200, "NUMBER"); 63 | 64 | cmd.add(arg_concurrency); 65 | cmd.add(arg_init_with_kmeans); 66 | cmd.add(arg_K); 67 | cmd.add(arg_min_covar); 68 | cmd.add(arg_input_file); 69 | cmd.add(arg_model_file); 70 | cmd.add(arg_iteration); 71 | 72 | 73 | cmd.parse(argc, argv); 74 | 75 | #define GET_VALUE(name) args.name = arg_##name.getValue(); 76 | GET_VALUE(concurrency); 77 | GET_VALUE(init_with_kmeans); 78 | GET_VALUE(K); 79 | GET_VALUE(min_covar); 80 | GET_VALUE(input_file); 81 | GET_VALUE(model_file); 82 | GET_VALUE(iteration); 83 | 84 | } catch (ArgException &e) { 85 | cerr << "error: " << e.error() << " for arg " << e.argId() << endl; 86 | } 87 | return args; 88 | } 89 | 90 | void read_dense_dataset(DenseDataset &X, const char *fname) { 91 | ifstream fin(fname); 92 | string line; 93 | while (getline(fin, line)) { 94 | X.push_back(string_to_double_vector(line)); 95 | } 96 | } 97 | 98 | void write_dense_dataset(DenseDataset &X, const char *fname) { 99 | ofstream fout(fname); 100 | for (auto &x: X) { 101 | for (auto &v: x) 102 | fout << v << ' '; 103 | fout << endl; 104 | } 105 | } 106 | 107 | static vector random_vector(int dim, real_t range, Random &random) { 108 | vector vec(dim); 109 | for (auto &v: vec) v = random.rand_real() * range; 110 | return vec; 111 | } 112 | 113 | void fill_gaussian(DenseDataset &X, Gaussian *gaussian, int nr_point) { 114 | for (int i = 0; i < nr_point; i ++) 115 | X.push_back(gaussian->sample()); 116 | } 117 | 118 | void gen_high_dim_gaussian_mixture(DenseDataset &X, int dim, int nr_gaussian, int nr_point_per_gaussian) { 119 | Random random; 120 | for (int i = 0; i < nr_gaussian; i ++) { 121 | Gaussian g(dim); 122 | g.mean = random_vector(dim, 1, random); 123 | g.sigma = random_vector(dim, 0.05 + random.rand_real() * 0.1, random); 124 | fill_gaussian(X, &g, nr_point_per_gaussian); 125 | } 126 | } 127 | 128 | 129 | void test() { 130 | DenseDataset X; 131 | // read_dense_dataset(X, "test.data"); 132 | gen_high_dim_gaussian_mixture(X, 13, 10, 68000); 133 | write_dense_dataset(X, "test.data"); 134 | printf("start training"); 135 | GMMTrainerBaseline trainer(100, 1e-3, 0.01, 1, 4, 2); 136 | GMM gmm(100, COVTYPE_DIAGONAL, &trainer); 137 | gmm.fit(X); 138 | } 139 | 140 | int main(int argc, char *argv[]) { 141 | srand(42); // Answer to The Ultimate Question of Life, the Universe, and Everything 142 | test(); 143 | return 0; 144 | Args args = parse_args(argc, argv); 145 | 146 | DenseDataset X; 147 | read_dense_dataset(X, args.input_file.c_str()); 148 | 149 | GMMTrainerBaseline trainer(args.iteration, args.min_covar, args.init_with_kmeans, args.concurrency); 150 | GMM gmm(args.K, COVTYPE_DIAGONAL, &trainer); 151 | printf("start training ...\n"); fflush(stdout); 152 | gmm.fit(X); 153 | 154 | ofstream fout(args.model_file); 155 | gmm.dump(fout); 156 | 157 | return 0; 158 | } 159 | 160 | /** 161 | * vim: syntax=cpp11 foldmethod=marker 162 | */ 163 | 164 | -------------------------------------------------------------------------------- /src/pygmm.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * $File: pygmm.cc 3 | * $Date: Wed Dec 11 18:50:31 2013 +0800 4 | * $Author: Xinyu Zhou 5 | */ 6 | 7 | #include "pygmm.hh" 8 | #include "gmm.hh" 9 | 10 | #include 11 | 12 | using namespace std; 13 | 14 | typedef vector> DenseDataset; 15 | 16 | void conv_double_pp_to_vv(double **Xp, DenseDataset &X, int nr_instance, int nr_dim) { 17 | X.resize(nr_instance); 18 | for (auto &x: X) 19 | x.resize(nr_dim); 20 | for (int i = 0; i < nr_instance; i ++) 21 | for (int j = 0; j < nr_dim; j ++) 22 | X[i][j] = Xp[i][j]; 23 | } 24 | 25 | void conv_double_p_to_v(double *x_in, vector &x, int nr_dim) { 26 | x.resize(nr_dim); 27 | for (int i = 0; i < nr_dim; i ++) 28 | x[i] = x_in[i]; 29 | } 30 | 31 | void print_param(Parameter *param) { 32 | printf("nr_instance : %d\n", param->nr_instance); 33 | printf("nr_dim : %d\n", param->nr_dim); 34 | printf("nr_mixture : %d\n", param->nr_mixture); 35 | printf("min_covar : %f\n", param->min_covar); 36 | printf("threshold : %f\n", param->threshold); 37 | printf("nr_iteration : %d\n", param->nr_iteration); 38 | printf("init_with_kmeans: %d\n", param->init_with_kmeans); 39 | printf("concurrency : %d\n", param->concurrency); 40 | printf("verbosity : %d\n", param->verbosity); 41 | } 42 | 43 | void print_X(double **X) { 44 | printf("X: %p\n", X); 45 | printf("X: %p\n", X[0]); 46 | printf("X: %f\n", X[0][0]); 47 | } 48 | 49 | 50 | GMM *new_gmm(int nr_mixture, int covariance_type) { 51 | return new GMM(nr_mixture, covariance_type); 52 | } 53 | 54 | GMM *load(const char *model_file) { 55 | return new GMM(model_file); 56 | } 57 | 58 | void dump(GMM *gmm, const char *model_file) { 59 | ofstream fout(model_file); 60 | gmm->dump(fout); 61 | } 62 | 63 | void train_model(GMM *gmm, double **X_in, Parameter *param) { 64 | print_param(param); 65 | GMMTrainerBaseline trainer(param->nr_iteration, param->min_covar, param->init_with_kmeans, param->concurrency, param->verbosity); 66 | gmm->trainer = &trainer; 67 | DenseDataset X; 68 | conv_double_pp_to_vv(X_in, X, param->nr_instance, param->nr_dim); 69 | gmm->fit(X); 70 | } 71 | 72 | double score_all(GMM *gmm, double **X_in, int nr_instance, int nr_dim, int concurrency) { 73 | DenseDataset X; 74 | conv_double_pp_to_vv(X_in, X, nr_instance, nr_dim); 75 | return gmm->log_probability_of_fast_exp_threaded(X, concurrency); 76 | } 77 | 78 | void score_batch(GMM *gmm, double **X_in, double *prob_out, int nr_instance, int nr_dim, int concurrency) { 79 | DenseDataset X; 80 | conv_double_pp_to_vv(X_in, X, nr_instance, nr_dim); 81 | std::vector prob; 82 | gmm->log_probability_of_fast_exp_threaded(X, prob, concurrency); 83 | for (size_t i = 0; i < prob.size(); i ++) 84 | prob_out[i] = prob[i]; 85 | } 86 | 87 | double score_instance(GMM *gmm, double *x_in, int nr_dim) { 88 | vector x; 89 | conv_double_p_to_v(x_in, x, nr_dim); 90 | return gmm->log_probability_of_fast_exp(x); 91 | } 92 | 93 | /** 94 | * vim: syntax=cpp11 foldmethod=marker 95 | */ 96 | 97 | -------------------------------------------------------------------------------- /src/pygmm.hh: -------------------------------------------------------------------------------- 1 | /* 2 | * $File: pygmm.hh 3 | * $Date: Wed Dec 11 18:50:08 2013 +0800 4 | * $Author: Xinyu Zhou 5 | */ 6 | 7 | #pragma once 8 | 9 | #include "gmm.hh" 10 | 11 | extern "C" { 12 | struct Parameter { 13 | int nr_instance; 14 | int nr_dim; 15 | 16 | int nr_mixture; 17 | 18 | double min_covar; 19 | double threshold; 20 | int nr_iteration; 21 | 22 | int init_with_kmeans; 23 | int concurrency; 24 | 25 | int verbosity; 26 | }; 27 | 28 | GMM *new_gmm(int nr_mixture, int covariance_type); 29 | GMM *load(const char *model_file); 30 | 31 | void dump(GMM *gmm, const char *model_file); 32 | 33 | void train_model(GMM *gmm, double **X_in, Parameter *param); 34 | 35 | double score_all(GMM *gmm, double **X_in, int nr_instance, int nr_dim, int concurrency); 36 | void score_batch(GMM *gmm, double **X_in, double *prob_out, int nr_instance, int nr_dim, int concurrency); 37 | double score_instance(GMM *gmm, double *x_in, int nr_dim); 38 | } 39 | 40 | /** 41 | * vim: syntax=cpp11 foldmethod=marker 42 | */ 43 | 44 | -------------------------------------------------------------------------------- /src/random.hh: -------------------------------------------------------------------------------- 1 | /* 2 | * $File: random.hh 3 | * $Date: Wed Dec 11 17:31:04 2013 +0800 4 | * $Author: Xinyu Zhou 5 | */ 6 | 7 | #pragma once 8 | 9 | #include "type.hh" 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | /** 16 | * Random Number Generator 17 | */ 18 | class Random { 19 | public: 20 | 21 | Random() { 22 | // long long seed = std::chrono::system_clock::now().time_since_epoch().count(); 23 | long long seed = rand(); 24 | generator.seed(seed); 25 | } 26 | 27 | void seed(unsigned long long s) { 28 | generator.seed(s); 29 | } 30 | 31 | /// return a random number in [0.0, 1.0) 32 | inline real_t rand_real() { 33 | return real_distribution(generator); 34 | } 35 | 36 | inline real_t rand_normal() { 37 | return normal_distribution(generator); 38 | } 39 | 40 | inline real_t rand_normal(real_t mean, real_t stddev) { 41 | return std::normal_distribution(mean, stddev)(generator); 42 | } 43 | 44 | void set_normal_distribution_param(real_t mean, real_t stddev) { 45 | normal_distribution = std::normal_distribution(mean, stddev); 46 | } 47 | 48 | /// return a random integer in range [0, max_val) 49 | inline int rand_int(int max_val = std::numeric_limits::max()) { 50 | return rand_real() * max_val; 51 | } 52 | 53 | protected: 54 | std::default_random_engine generator; 55 | std::uniform_real_distribution real_distribution; // [0.0, 1.0) 56 | std::normal_distribution normal_distribution; // N(0, 1) 57 | }; 58 | 59 | /** 60 | * vim: syntax=cpp11 foldmethod=marker 61 | */ 62 | 63 | -------------------------------------------------------------------------------- /src/tclap/ArgException.h: -------------------------------------------------------------------------------- 1 | // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- 2 | 3 | /****************************************************************************** 4 | * 5 | * file: ArgException.h 6 | * 7 | * Copyright (c) 2003, Michael E. Smoot . 8 | * All rights reverved. 9 | * 10 | * See the file COPYING in the top directory of this distribution for 11 | * more information. 12 | * 13 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | * DEALINGS IN THE SOFTWARE. 20 | * 21 | *****************************************************************************/ 22 | 23 | 24 | #ifndef TCLAP_ARG_EXCEPTION_H 25 | #define TCLAP_ARG_EXCEPTION_H 26 | 27 | #include 28 | #include 29 | 30 | namespace TCLAP { 31 | 32 | /** 33 | * A simple class that defines and argument exception. Should be caught 34 | * whenever a CmdLine is created and parsed. 35 | */ 36 | class ArgException : public std::exception 37 | { 38 | public: 39 | 40 | /** 41 | * Constructor. 42 | * \param text - The text of the exception. 43 | * \param id - The text identifying the argument source. 44 | * \param td - Text describing the type of ArgException it is. 45 | * of the exception. 46 | */ 47 | ArgException( const std::string& text = "undefined exception", 48 | const std::string& id = "undefined", 49 | const std::string& td = "Generic ArgException") 50 | : std::exception(), 51 | _errorText(text), 52 | _argId( id ), 53 | _typeDescription(td) 54 | { } 55 | 56 | /** 57 | * Destructor. 58 | */ 59 | virtual ~ArgException() throw() { } 60 | 61 | /** 62 | * Returns the error text. 63 | */ 64 | std::string error() const { return ( _errorText ); } 65 | 66 | /** 67 | * Returns the argument id. 68 | */ 69 | std::string argId() const 70 | { 71 | if ( _argId == "undefined" ) 72 | return " "; 73 | else 74 | return ( "Argument: " + _argId ); 75 | } 76 | 77 | /** 78 | * Returns the arg id and error text. 79 | */ 80 | const char* what() const throw() 81 | { 82 | static std::string ex; 83 | ex = _argId + " -- " + _errorText; 84 | return ex.c_str(); 85 | } 86 | 87 | /** 88 | * Returns the type of the exception. Used to explain and distinguish 89 | * between different child exceptions. 90 | */ 91 | std::string typeDescription() const 92 | { 93 | return _typeDescription; 94 | } 95 | 96 | 97 | private: 98 | 99 | /** 100 | * The text of the exception message. 101 | */ 102 | std::string _errorText; 103 | 104 | /** 105 | * The argument related to this exception. 106 | */ 107 | std::string _argId; 108 | 109 | /** 110 | * Describes the type of the exception. Used to distinguish 111 | * between different child exceptions. 112 | */ 113 | std::string _typeDescription; 114 | 115 | }; 116 | 117 | /** 118 | * Thrown from within the child Arg classes when it fails to properly 119 | * parse the argument it has been passed. 120 | */ 121 | class ArgParseException : public ArgException 122 | { 123 | public: 124 | /** 125 | * Constructor. 126 | * \param text - The text of the exception. 127 | * \param id - The text identifying the argument source 128 | * of the exception. 129 | */ 130 | ArgParseException( const std::string& text = "undefined exception", 131 | const std::string& id = "undefined" ) 132 | : ArgException( text, 133 | id, 134 | std::string( "Exception found while parsing " ) + 135 | std::string( "the value the Arg has been passed." )) 136 | { } 137 | }; 138 | 139 | /** 140 | * Thrown from CmdLine when the arguments on the command line are not 141 | * properly specified, e.g. too many arguments, required argument missing, etc. 142 | */ 143 | class CmdLineParseException : public ArgException 144 | { 145 | public: 146 | /** 147 | * Constructor. 148 | * \param text - The text of the exception. 149 | * \param id - The text identifying the argument source 150 | * of the exception. 151 | */ 152 | CmdLineParseException( const std::string& text = "undefined exception", 153 | const std::string& id = "undefined" ) 154 | : ArgException( text, 155 | id, 156 | std::string( "Exception found when the values ") + 157 | std::string( "on the command line do not meet ") + 158 | std::string( "the requirements of the defined ") + 159 | std::string( "Args." )) 160 | { } 161 | }; 162 | 163 | /** 164 | * Thrown from Arg and CmdLine when an Arg is improperly specified, e.g. 165 | * same flag as another Arg, same name, etc. 166 | */ 167 | class SpecificationException : public ArgException 168 | { 169 | public: 170 | /** 171 | * Constructor. 172 | * \param text - The text of the exception. 173 | * \param id - The text identifying the argument source 174 | * of the exception. 175 | */ 176 | SpecificationException( const std::string& text = "undefined exception", 177 | const std::string& id = "undefined" ) 178 | : ArgException( text, 179 | id, 180 | std::string("Exception found when an Arg object ")+ 181 | std::string("is improperly defined by the ") + 182 | std::string("developer." )) 183 | { } 184 | 185 | }; 186 | 187 | class ExitException { 188 | public: 189 | ExitException(int estat) : _estat(estat) {} 190 | 191 | int getExitStatus() const { return _estat; } 192 | 193 | private: 194 | int _estat; 195 | }; 196 | 197 | } // namespace TCLAP 198 | 199 | #endif 200 | 201 | -------------------------------------------------------------------------------- /src/tclap/ArgTraits.h: -------------------------------------------------------------------------------- 1 | // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- 2 | 3 | /****************************************************************************** 4 | * 5 | * file: ArgTraits.h 6 | * 7 | * Copyright (c) 2007, Daniel Aarno, Michael E. Smoot . 8 | * All rights reverved. 9 | * 10 | * See the file COPYING in the top directory of this distribution for 11 | * more information. 12 | * 13 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | * DEALINGS IN THE SOFTWARE. 20 | * 21 | *****************************************************************************/ 22 | 23 | // This is an internal tclap file, you should probably not have to 24 | // include this directly 25 | 26 | #ifndef TCLAP_ARGTRAITS_H 27 | #define TCLAP_ARGTRAITS_H 28 | 29 | namespace TCLAP { 30 | 31 | // We use two empty structs to get compile type specialization 32 | // function to work 33 | 34 | /** 35 | * A value like argument value type is a value that can be set using 36 | * operator>>. This is the default value type. 37 | */ 38 | struct ValueLike { 39 | typedef ValueLike ValueCategory; 40 | virtual ~ValueLike() {} 41 | }; 42 | 43 | /** 44 | * A string like argument value type is a value that can be set using 45 | * operator=(string). Usefull if the value type contains spaces which 46 | * will be broken up into individual tokens by operator>>. 47 | */ 48 | struct StringLike { 49 | virtual ~StringLike() {} 50 | }; 51 | 52 | /** 53 | * A class can inherit from this object to make it have string like 54 | * traits. This is a compile time thing and does not add any overhead 55 | * to the inherenting class. 56 | */ 57 | struct StringLikeTrait { 58 | typedef StringLike ValueCategory; 59 | virtual ~StringLikeTrait() {} 60 | }; 61 | 62 | /** 63 | * A class can inherit from this object to make it have value like 64 | * traits. This is a compile time thing and does not add any overhead 65 | * to the inherenting class. 66 | */ 67 | struct ValueLikeTrait { 68 | typedef ValueLike ValueCategory; 69 | virtual ~ValueLikeTrait() {} 70 | }; 71 | 72 | /** 73 | * Arg traits are used to get compile type specialization when parsing 74 | * argument values. Using an ArgTraits you can specify the way that 75 | * values gets assigned to any particular type during parsing. The two 76 | * supported types are StringLike and ValueLike. 77 | */ 78 | template 79 | struct ArgTraits { 80 | typedef typename T::ValueCategory ValueCategory; 81 | virtual ~ArgTraits() {} 82 | //typedef ValueLike ValueCategory; 83 | }; 84 | 85 | #endif 86 | 87 | } // namespace 88 | -------------------------------------------------------------------------------- /src/tclap/CmdLineInterface.h: -------------------------------------------------------------------------------- 1 | 2 | /****************************************************************************** 3 | * 4 | * file: CmdLineInterface.h 5 | * 6 | * Copyright (c) 2003, Michael E. Smoot . 7 | * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. 8 | * All rights reverved. 9 | * 10 | * See the file COPYING in the top directory of this distribution for 11 | * more information. 12 | * 13 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | * DEALINGS IN THE SOFTWARE. 20 | * 21 | *****************************************************************************/ 22 | 23 | #ifndef TCLAP_COMMANDLINE_INTERFACE_H 24 | #define TCLAP_COMMANDLINE_INTERFACE_H 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | 33 | namespace TCLAP { 34 | 35 | class Arg; 36 | class CmdLineOutput; 37 | class XorHandler; 38 | 39 | /** 40 | * The base class that manages the command line definition and passes 41 | * along the parsing to the appropriate Arg classes. 42 | */ 43 | class CmdLineInterface 44 | { 45 | public: 46 | 47 | /** 48 | * Destructor 49 | */ 50 | virtual ~CmdLineInterface() {} 51 | 52 | /** 53 | * Adds an argument to the list of arguments to be parsed. 54 | * \param a - Argument to be added. 55 | */ 56 | virtual void add( Arg& a )=0; 57 | 58 | /** 59 | * An alternative add. Functionally identical. 60 | * \param a - Argument to be added. 61 | */ 62 | virtual void add( Arg* a )=0; 63 | 64 | /** 65 | * Add two Args that will be xor'd. 66 | * If this method is used, add does 67 | * not need to be called. 68 | * \param a - Argument to be added and xor'd. 69 | * \param b - Argument to be added and xor'd. 70 | */ 71 | virtual void xorAdd( Arg& a, Arg& b )=0; 72 | 73 | /** 74 | * Add a list of Args that will be xor'd. If this method is used, 75 | * add does not need to be called. 76 | * \param xors - List of Args to be added and xor'd. 77 | */ 78 | virtual void xorAdd( std::vector& xors )=0; 79 | 80 | /** 81 | * Parses the command line. 82 | * \param argc - Number of arguments. 83 | * \param argv - Array of arguments. 84 | */ 85 | virtual void parse(int argc, const char * const * argv)=0; 86 | 87 | /** 88 | * Parses the command line. 89 | * \param args - A vector of strings representing the args. 90 | * args[0] is still the program name. 91 | */ 92 | void parse(std::vector& args); 93 | 94 | /** 95 | * Returns the CmdLineOutput object. 96 | */ 97 | virtual CmdLineOutput* getOutput()=0; 98 | 99 | /** 100 | * \param co - CmdLineOutput object that we want to use instead. 101 | */ 102 | virtual void setOutput(CmdLineOutput* co)=0; 103 | 104 | /** 105 | * Returns the version string. 106 | */ 107 | virtual std::string& getVersion()=0; 108 | 109 | /** 110 | * Returns the program name string. 111 | */ 112 | virtual std::string& getProgramName()=0; 113 | 114 | /** 115 | * Returns the argList. 116 | */ 117 | virtual std::list& getArgList()=0; 118 | 119 | /** 120 | * Returns the XorHandler. 121 | */ 122 | virtual XorHandler& getXorHandler()=0; 123 | 124 | /** 125 | * Returns the delimiter string. 126 | */ 127 | virtual char getDelimiter()=0; 128 | 129 | /** 130 | * Returns the message string. 131 | */ 132 | virtual std::string& getMessage()=0; 133 | 134 | /** 135 | * Indicates whether or not the help and version switches were created 136 | * automatically. 137 | */ 138 | virtual bool hasHelpAndVersion()=0; 139 | 140 | /** 141 | * Resets the instance as if it had just been constructed so that the 142 | * instance can be reused. 143 | */ 144 | virtual void reset()=0; 145 | }; 146 | 147 | } //namespace 148 | 149 | 150 | #endif 151 | -------------------------------------------------------------------------------- /src/tclap/CmdLineOutput.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | /****************************************************************************** 4 | * 5 | * file: CmdLineOutput.h 6 | * 7 | * Copyright (c) 2004, Michael E. Smoot 8 | * All rights reverved. 9 | * 10 | * See the file COPYING in the top directory of this distribution for 11 | * more information. 12 | * 13 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | * DEALINGS IN THE SOFTWARE. 20 | * 21 | *****************************************************************************/ 22 | 23 | #ifndef TCLAP_CMDLINEOUTPUT_H 24 | #define TCLAP_CMDLINEOUTPUT_H 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | namespace TCLAP { 34 | 35 | class CmdLineInterface; 36 | class ArgException; 37 | 38 | /** 39 | * The interface that any output object must implement. 40 | */ 41 | class CmdLineOutput 42 | { 43 | 44 | public: 45 | 46 | /** 47 | * Virtual destructor. 48 | */ 49 | virtual ~CmdLineOutput() {} 50 | 51 | /** 52 | * Generates some sort of output for the USAGE. 53 | * \param c - The CmdLine object the output is generated for. 54 | */ 55 | virtual void usage(CmdLineInterface& c)=0; 56 | 57 | /** 58 | * Generates some sort of output for the version. 59 | * \param c - The CmdLine object the output is generated for. 60 | */ 61 | virtual void version(CmdLineInterface& c)=0; 62 | 63 | /** 64 | * Generates some sort of output for a failure. 65 | * \param c - The CmdLine object the output is generated for. 66 | * \param e - The ArgException that caused the failure. 67 | */ 68 | virtual void failure( CmdLineInterface& c, 69 | ArgException& e )=0; 70 | 71 | }; 72 | 73 | } //namespace TCLAP 74 | #endif 75 | -------------------------------------------------------------------------------- /src/tclap/Constraint.h: -------------------------------------------------------------------------------- 1 | 2 | /****************************************************************************** 3 | * 4 | * file: Constraint.h 5 | * 6 | * Copyright (c) 2005, Michael E. Smoot 7 | * All rights reverved. 8 | * 9 | * See the file COPYING in the top directory of this distribution for 10 | * more information. 11 | * 12 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 13 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 15 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 17 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 18 | * DEALINGS IN THE SOFTWARE. 19 | * 20 | *****************************************************************************/ 21 | 22 | #ifndef TCLAP_CONSTRAINT_H 23 | #define TCLAP_CONSTRAINT_H 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | namespace TCLAP { 33 | 34 | /** 35 | * The interface that defines the interaction between the Arg and Constraint. 36 | */ 37 | template 38 | class Constraint 39 | { 40 | 41 | public: 42 | /** 43 | * Returns a description of the Constraint. 44 | */ 45 | virtual std::string description() const =0; 46 | 47 | /** 48 | * Returns the short ID for the Constraint. 49 | */ 50 | virtual std::string shortID() const =0; 51 | 52 | /** 53 | * The method used to verify that the value parsed from the command 54 | * line meets the constraint. 55 | * \param value - The value that will be checked. 56 | */ 57 | virtual bool check(const T& value) const =0; 58 | 59 | /** 60 | * Destructor. 61 | * Silences warnings about Constraint being a base class with virtual 62 | * functions but without a virtual destructor. 63 | */ 64 | virtual ~Constraint() { ; } 65 | }; 66 | 67 | } //namespace TCLAP 68 | #endif 69 | -------------------------------------------------------------------------------- /src/tclap/DocBookOutput.h: -------------------------------------------------------------------------------- 1 | // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- 2 | 3 | /****************************************************************************** 4 | * 5 | * file: DocBookOutput.h 6 | * 7 | * Copyright (c) 2004, Michael E. Smoot 8 | * All rights reverved. 9 | * 10 | * See the file COPYING in the top directory of this distribution for 11 | * more information. 12 | * 13 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | * DEALINGS IN THE SOFTWARE. 20 | * 21 | *****************************************************************************/ 22 | 23 | #ifndef TCLAP_DOCBOOKOUTPUT_H 24 | #define TCLAP_DOCBOOKOUTPUT_H 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | namespace TCLAP { 38 | 39 | /** 40 | * A class that generates DocBook output for usage() method for the 41 | * given CmdLine and its Args. 42 | */ 43 | class DocBookOutput : public CmdLineOutput 44 | { 45 | 46 | public: 47 | 48 | /** 49 | * Prints the usage to stdout. Can be overridden to 50 | * produce alternative behavior. 51 | * \param c - The CmdLine object the output is generated for. 52 | */ 53 | virtual void usage(CmdLineInterface& c); 54 | 55 | /** 56 | * Prints the version to stdout. Can be overridden 57 | * to produce alternative behavior. 58 | * \param c - The CmdLine object the output is generated for. 59 | */ 60 | virtual void version(CmdLineInterface& c); 61 | 62 | /** 63 | * Prints (to stderr) an error message, short usage 64 | * Can be overridden to produce alternative behavior. 65 | * \param c - The CmdLine object the output is generated for. 66 | * \param e - The ArgException that caused the failure. 67 | */ 68 | virtual void failure(CmdLineInterface& c, 69 | ArgException& e ); 70 | 71 | protected: 72 | 73 | /** 74 | * Substitutes the char r for string x in string s. 75 | * \param s - The string to operate on. 76 | * \param r - The char to replace. 77 | * \param x - What to replace r with. 78 | */ 79 | void substituteSpecialChars( std::string& s, char r, std::string& x ); 80 | void removeChar( std::string& s, char r); 81 | void basename( std::string& s ); 82 | 83 | void printShortArg(Arg* it); 84 | void printLongArg(Arg* it); 85 | 86 | char theDelimiter; 87 | }; 88 | 89 | 90 | inline void DocBookOutput::version(CmdLineInterface& _cmd) 91 | { 92 | std::cout << _cmd.getVersion() << std::endl; 93 | } 94 | 95 | inline void DocBookOutput::usage(CmdLineInterface& _cmd ) 96 | { 97 | std::list argList = _cmd.getArgList(); 98 | std::string progName = _cmd.getProgramName(); 99 | std::string xversion = _cmd.getVersion(); 100 | theDelimiter = _cmd.getDelimiter(); 101 | XorHandler xorHandler = _cmd.getXorHandler(); 102 | std::vector< std::vector > xorList = xorHandler.getXorList(); 103 | basename(progName); 104 | 105 | std::cout << "" << std::endl; 106 | std::cout << "" << std::endl << std::endl; 108 | 109 | std::cout << "" << std::endl; 110 | 111 | std::cout << "" << std::endl; 112 | std::cout << "" << progName << "" << std::endl; 113 | std::cout << "1" << std::endl; 114 | std::cout << "" << std::endl; 115 | 116 | std::cout << "" << std::endl; 117 | std::cout << "" << progName << "" << std::endl; 118 | std::cout << "" << _cmd.getMessage() << "" << std::endl; 119 | std::cout << "" << std::endl; 120 | 121 | std::cout << "" << std::endl; 122 | std::cout << "" << std::endl; 123 | 124 | std::cout << "" << progName << "" << std::endl; 125 | 126 | // xor 127 | for ( int i = 0; (unsigned int)i < xorList.size(); i++ ) 128 | { 129 | std::cout << "" << std::endl; 130 | for ( ArgVectorIterator it = xorList[i].begin(); 131 | it != xorList[i].end(); it++ ) 132 | printShortArg((*it)); 133 | 134 | std::cout << "" << std::endl; 135 | } 136 | 137 | // rest of args 138 | for (ArgListIterator it = argList.begin(); it != argList.end(); it++) 139 | if ( !xorHandler.contains( (*it) ) ) 140 | printShortArg((*it)); 141 | 142 | std::cout << "" << std::endl; 143 | std::cout << "" << std::endl; 144 | 145 | std::cout << "" << std::endl; 146 | std::cout << "Description" << std::endl; 147 | std::cout << "" << std::endl; 148 | std::cout << _cmd.getMessage() << std::endl; 149 | std::cout << "" << std::endl; 150 | std::cout << "" << std::endl; 151 | 152 | std::cout << "" << std::endl; 153 | std::cout << "Options" << std::endl; 154 | 155 | std::cout << "" << std::endl; 156 | 157 | for (ArgListIterator it = argList.begin(); it != argList.end(); it++) 158 | printLongArg((*it)); 159 | 160 | std::cout << "" << std::endl; 161 | std::cout << "" << std::endl; 162 | 163 | std::cout << "" << std::endl; 164 | std::cout << "Version" << std::endl; 165 | std::cout << "" << std::endl; 166 | std::cout << xversion << std::endl; 167 | std::cout << "" << std::endl; 168 | std::cout << "" << std::endl; 169 | 170 | std::cout << "" << std::endl; 171 | 172 | } 173 | 174 | inline void DocBookOutput::failure( CmdLineInterface& _cmd, 175 | ArgException& e ) 176 | { 177 | static_cast(_cmd); // unused 178 | std::cout << e.what() << std::endl; 179 | throw ExitException(1); 180 | } 181 | 182 | inline void DocBookOutput::substituteSpecialChars( std::string& s, 183 | char r, 184 | std::string& x ) 185 | { 186 | size_t p; 187 | while ( (p = s.find_first_of(r)) != std::string::npos ) 188 | { 189 | s.erase(p,1); 190 | s.insert(p,x); 191 | } 192 | } 193 | 194 | inline void DocBookOutput::removeChar( std::string& s, char r) 195 | { 196 | size_t p; 197 | while ( (p = s.find_first_of(r)) != std::string::npos ) 198 | { 199 | s.erase(p,1); 200 | } 201 | } 202 | 203 | inline void DocBookOutput::basename( std::string& s ) 204 | { 205 | size_t p = s.find_last_of('/'); 206 | if ( p != std::string::npos ) 207 | { 208 | s.erase(0, p + 1); 209 | } 210 | } 211 | 212 | inline void DocBookOutput::printShortArg(Arg* a) 213 | { 214 | std::string lt = "<"; 215 | std::string gt = ">"; 216 | 217 | std::string id = a->shortID(); 218 | substituteSpecialChars(id,'<',lt); 219 | substituteSpecialChars(id,'>',gt); 220 | removeChar(id,'['); 221 | removeChar(id,']'); 222 | 223 | std::string choice = "opt"; 224 | if ( a->isRequired() ) 225 | choice = "plain"; 226 | 227 | std::cout << "acceptsMultipleValues() ) 229 | std::cout << " rep='repeat'"; 230 | 231 | 232 | std::cout << '>'; 233 | if ( !a->getFlag().empty() ) 234 | std::cout << a->flagStartChar() << a->getFlag(); 235 | else 236 | std::cout << a->nameStartString() << a->getName(); 237 | if ( a->isValueRequired() ) 238 | { 239 | std::string arg = a->shortID(); 240 | removeChar(arg,'['); 241 | removeChar(arg,']'); 242 | removeChar(arg,'<'); 243 | removeChar(arg,'>'); 244 | arg.erase(0, arg.find_last_of(theDelimiter) + 1); 245 | std::cout << theDelimiter; 246 | std::cout << "" << arg << ""; 247 | } 248 | std::cout << "" << std::endl; 249 | 250 | } 251 | 252 | inline void DocBookOutput::printLongArg(Arg* a) 253 | { 254 | std::string lt = "<"; 255 | std::string gt = ">"; 256 | 257 | std::string desc = a->getDescription(); 258 | substituteSpecialChars(desc,'<',lt); 259 | substituteSpecialChars(desc,'>',gt); 260 | 261 | std::cout << "" << std::endl; 262 | 263 | if ( !a->getFlag().empty() ) 264 | { 265 | std::cout << "" << std::endl; 266 | std::cout << "" << std::endl; 269 | std::cout << "" << std::endl; 270 | } 271 | 272 | std::cout << "" << std::endl; 273 | std::cout << "" << std::endl; 287 | std::cout << "" << std::endl; 288 | 289 | std::cout << "" << std::endl; 290 | std::cout << "" << std::endl; 291 | std::cout << desc << std::endl; 292 | std::cout << "" << std::endl; 293 | std::cout << "" << std::endl; 294 | 295 | std::cout << "" << std::endl; 296 | } 297 | 298 | } //namespace TCLAP 299 | #endif 300 | -------------------------------------------------------------------------------- /src/tclap/HelpVisitor.h: -------------------------------------------------------------------------------- 1 | 2 | /****************************************************************************** 3 | * 4 | * file: HelpVisitor.h 5 | * 6 | * Copyright (c) 2003, Michael E. Smoot . 7 | * All rights reverved. 8 | * 9 | * See the file COPYING in the top directory of this distribution for 10 | * more information. 11 | * 12 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 13 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 15 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 17 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 18 | * DEALINGS IN THE SOFTWARE. 19 | * 20 | *****************************************************************************/ 21 | 22 | #ifndef TCLAP_HELP_VISITOR_H 23 | #define TCLAP_HELP_VISITOR_H 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | namespace TCLAP { 30 | 31 | /** 32 | * A Visitor object that calls the usage method of the given CmdLineOutput 33 | * object for the specified CmdLine object. 34 | */ 35 | class HelpVisitor: public Visitor 36 | { 37 | private: 38 | /** 39 | * Prevent accidental copying. 40 | */ 41 | HelpVisitor(const HelpVisitor& rhs); 42 | HelpVisitor& operator=(const HelpVisitor& rhs); 43 | 44 | protected: 45 | 46 | /** 47 | * The CmdLine the output will be generated for. 48 | */ 49 | CmdLineInterface* _cmd; 50 | 51 | /** 52 | * The output object. 53 | */ 54 | CmdLineOutput** _out; 55 | 56 | public: 57 | 58 | /** 59 | * Constructor. 60 | * \param cmd - The CmdLine the output will be generated for. 61 | * \param out - The type of output. 62 | */ 63 | HelpVisitor(CmdLineInterface* cmd, CmdLineOutput** out) 64 | : Visitor(), _cmd( cmd ), _out( out ) { } 65 | 66 | /** 67 | * Calls the usage method of the CmdLineOutput for the 68 | * specified CmdLine. 69 | */ 70 | void visit() { (*_out)->usage(*_cmd); throw ExitException(0); } 71 | 72 | }; 73 | 74 | } 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /src/tclap/IgnoreRestVisitor.h: -------------------------------------------------------------------------------- 1 | 2 | /****************************************************************************** 3 | * 4 | * file: IgnoreRestVisitor.h 5 | * 6 | * Copyright (c) 2003, Michael E. Smoot . 7 | * All rights reverved. 8 | * 9 | * See the file COPYING in the top directory of this distribution for 10 | * more information. 11 | * 12 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 13 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 15 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 17 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 18 | * DEALINGS IN THE SOFTWARE. 19 | * 20 | *****************************************************************************/ 21 | 22 | 23 | #ifndef TCLAP_IGNORE_REST_VISITOR_H 24 | #define TCLAP_IGNORE_REST_VISITOR_H 25 | 26 | #include 27 | #include 28 | 29 | namespace TCLAP { 30 | 31 | /** 32 | * A Vistor that tells the CmdLine to begin ignoring arguments after 33 | * this one is parsed. 34 | */ 35 | class IgnoreRestVisitor: public Visitor 36 | { 37 | public: 38 | 39 | /** 40 | * Constructor. 41 | */ 42 | IgnoreRestVisitor() : Visitor() {} 43 | 44 | /** 45 | * Sets Arg::_ignoreRest. 46 | */ 47 | void visit() { Arg::beginIgnoring(); } 48 | }; 49 | 50 | } 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /src/tclap/Makefile.am: -------------------------------------------------------------------------------- 1 | 2 | libtclapincludedir = $(includedir)/tclap 3 | 4 | libtclapinclude_HEADERS = \ 5 | CmdLineInterface.h \ 6 | ArgException.h \ 7 | CmdLine.h \ 8 | XorHandler.h \ 9 | MultiArg.h \ 10 | UnlabeledMultiArg.h \ 11 | ValueArg.h \ 12 | UnlabeledValueArg.h \ 13 | Visitor.h Arg.h \ 14 | HelpVisitor.h \ 15 | SwitchArg.h \ 16 | MultiSwitchArg.h \ 17 | VersionVisitor.h \ 18 | IgnoreRestVisitor.h \ 19 | CmdLineOutput.h \ 20 | StdOutput.h \ 21 | DocBookOutput.h \ 22 | ZshCompletionOutput.h \ 23 | OptionalUnlabeledTracker.h \ 24 | Constraint.h \ 25 | ValuesConstraint.h \ 26 | ArgTraits.h \ 27 | StandardTraits.h 28 | 29 | -------------------------------------------------------------------------------- /src/tclap/Makefile.in: -------------------------------------------------------------------------------- 1 | # Makefile.in generated by automake 1.10 from Makefile.am. 2 | # @configure_input@ 3 | 4 | # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 5 | # 2003, 2004, 2005, 2006 Free Software Foundation, Inc. 6 | # This Makefile.in is free software; the Free Software Foundation 7 | # gives unlimited permission to copy and/or distribute it, 8 | # with or without modifications, as long as this notice is preserved. 9 | 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY, to the extent permitted by law; without 12 | # even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | # PARTICULAR PURPOSE. 14 | 15 | @SET_MAKE@ 16 | 17 | VPATH = @srcdir@ 18 | pkgdatadir = $(datadir)/@PACKAGE@ 19 | pkglibdir = $(libdir)/@PACKAGE@ 20 | pkgincludedir = $(includedir)/@PACKAGE@ 21 | am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd 22 | install_sh_DATA = $(install_sh) -c -m 644 23 | install_sh_PROGRAM = $(install_sh) -c 24 | install_sh_SCRIPT = $(install_sh) -c 25 | INSTALL_HEADER = $(INSTALL_DATA) 26 | transform = $(program_transform_name) 27 | NORMAL_INSTALL = : 28 | PRE_INSTALL = : 29 | POST_INSTALL = : 30 | NORMAL_UNINSTALL = : 31 | PRE_UNINSTALL = : 32 | POST_UNINSTALL = : 33 | subdir = include/tclap 34 | DIST_COMMON = $(libtclapinclude_HEADERS) $(srcdir)/Makefile.am \ 35 | $(srcdir)/Makefile.in 36 | ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 37 | am__aclocal_m4_deps = $(top_srcdir)/config/ac_cxx_have_long_long.m4 \ 38 | $(top_srcdir)/config/ac_cxx_have_sstream.m4 \ 39 | $(top_srcdir)/config/ac_cxx_have_strstream.m4 \ 40 | $(top_srcdir)/config/ac_cxx_namespaces.m4 \ 41 | $(top_srcdir)/config/ac_cxx_warn_effective_cxx.m4 \ 42 | $(top_srcdir)/config/bb_enable_doxygen.m4 \ 43 | $(top_srcdir)/configure.in 44 | am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ 45 | $(ACLOCAL_M4) 46 | mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs 47 | CONFIG_HEADER = $(top_builddir)/config/config.h 48 | CONFIG_CLEAN_FILES = 49 | SOURCES = 50 | DIST_SOURCES = 51 | am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; 52 | am__vpath_adj = case $$p in \ 53 | $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ 54 | *) f=$$p;; \ 55 | esac; 56 | am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; 57 | am__installdirs = "$(DESTDIR)$(libtclapincludedir)" 58 | libtclapincludeHEADERS_INSTALL = $(INSTALL_HEADER) 59 | HEADERS = $(libtclapinclude_HEADERS) 60 | ETAGS = etags 61 | CTAGS = ctags 62 | DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) 63 | ACLOCAL = @ACLOCAL@ 64 | AMTAR = @AMTAR@ 65 | AUTOCONF = @AUTOCONF@ 66 | AUTOHEADER = @AUTOHEADER@ 67 | AUTOMAKE = @AUTOMAKE@ 68 | AWK = @AWK@ 69 | CPPFLAGS = @CPPFLAGS@ 70 | CXX = @CXX@ 71 | CXXCPP = @CXXCPP@ 72 | CXXDEPMODE = @CXXDEPMODE@ 73 | CXXFLAGS = @CXXFLAGS@ 74 | CYGPATH_W = @CYGPATH_W@ 75 | DEFS = @DEFS@ 76 | DEPDIR = @DEPDIR@ 77 | DOT = @DOT@ 78 | DOXYGEN = @DOXYGEN@ 79 | ECHO_C = @ECHO_C@ 80 | ECHO_N = @ECHO_N@ 81 | ECHO_T = @ECHO_T@ 82 | EGREP = @EGREP@ 83 | EXEEXT = @EXEEXT@ 84 | GREP = @GREP@ 85 | INSTALL = @INSTALL@ 86 | INSTALL_DATA = @INSTALL_DATA@ 87 | INSTALL_PROGRAM = @INSTALL_PROGRAM@ 88 | INSTALL_SCRIPT = @INSTALL_SCRIPT@ 89 | INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ 90 | LDFLAGS = @LDFLAGS@ 91 | LIBOBJS = @LIBOBJS@ 92 | LIBS = @LIBS@ 93 | LTLIBOBJS = @LTLIBOBJS@ 94 | MAKEINFO = @MAKEINFO@ 95 | MKDIR_P = @MKDIR_P@ 96 | OBJEXT = @OBJEXT@ 97 | PACKAGE = @PACKAGE@ 98 | PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ 99 | PACKAGE_NAME = @PACKAGE_NAME@ 100 | PACKAGE_STRING = @PACKAGE_STRING@ 101 | PACKAGE_TARNAME = @PACKAGE_TARNAME@ 102 | PACKAGE_VERSION = @PACKAGE_VERSION@ 103 | PATH_SEPARATOR = @PATH_SEPARATOR@ 104 | RANLIB = @RANLIB@ 105 | SET_MAKE = @SET_MAKE@ 106 | SHELL = @SHELL@ 107 | STRIP = @STRIP@ 108 | VERSION = @VERSION@ 109 | WARN_EFFECTIVE_CXX = @WARN_EFFECTIVE_CXX@ 110 | WARN_NO_EFFECTIVE_CXX = @WARN_NO_EFFECTIVE_CXX@ 111 | abs_builddir = @abs_builddir@ 112 | abs_srcdir = @abs_srcdir@ 113 | abs_top_builddir = @abs_top_builddir@ 114 | abs_top_srcdir = @abs_top_srcdir@ 115 | ac_ct_CXX = @ac_ct_CXX@ 116 | am__include = @am__include@ 117 | am__leading_dot = @am__leading_dot@ 118 | am__quote = @am__quote@ 119 | am__tar = @am__tar@ 120 | am__untar = @am__untar@ 121 | bindir = @bindir@ 122 | build_alias = @build_alias@ 123 | builddir = @builddir@ 124 | datadir = @datadir@ 125 | datarootdir = @datarootdir@ 126 | docdir = @docdir@ 127 | dvidir = @dvidir@ 128 | exec_prefix = @exec_prefix@ 129 | host_alias = @host_alias@ 130 | htmldir = @htmldir@ 131 | includedir = @includedir@ 132 | infodir = @infodir@ 133 | install_sh = @install_sh@ 134 | libdir = @libdir@ 135 | libexecdir = @libexecdir@ 136 | localedir = @localedir@ 137 | localstatedir = @localstatedir@ 138 | mandir = @mandir@ 139 | mkdir_p = @mkdir_p@ 140 | oldincludedir = @oldincludedir@ 141 | pdfdir = @pdfdir@ 142 | prefix = @prefix@ 143 | program_transform_name = @program_transform_name@ 144 | psdir = @psdir@ 145 | sbindir = @sbindir@ 146 | sharedstatedir = @sharedstatedir@ 147 | srcdir = @srcdir@ 148 | sysconfdir = @sysconfdir@ 149 | target_alias = @target_alias@ 150 | top_builddir = @top_builddir@ 151 | top_srcdir = @top_srcdir@ 152 | libtclapincludedir = $(includedir)/tclap 153 | libtclapinclude_HEADERS = \ 154 | CmdLineInterface.h \ 155 | ArgException.h \ 156 | CmdLine.h \ 157 | XorHandler.h \ 158 | MultiArg.h \ 159 | UnlabeledMultiArg.h \ 160 | ValueArg.h \ 161 | UnlabeledValueArg.h \ 162 | Visitor.h Arg.h \ 163 | HelpVisitor.h \ 164 | SwitchArg.h \ 165 | MultiSwitchArg.h \ 166 | VersionVisitor.h \ 167 | IgnoreRestVisitor.h \ 168 | CmdLineOutput.h \ 169 | StdOutput.h \ 170 | DocBookOutput.h \ 171 | ZshCompletionOutput.h \ 172 | OptionalUnlabeledTracker.h \ 173 | Constraint.h \ 174 | ValuesConstraint.h \ 175 | ArgTraits.h \ 176 | StandardTraits.h 177 | 178 | all: all-am 179 | 180 | .SUFFIXES: 181 | $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) 182 | @for dep in $?; do \ 183 | case '$(am__configure_deps)' in \ 184 | *$$dep*) \ 185 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ 186 | && exit 0; \ 187 | exit 1;; \ 188 | esac; \ 189 | done; \ 190 | echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu include/tclap/Makefile'; \ 191 | cd $(top_srcdir) && \ 192 | $(AUTOMAKE) --gnu include/tclap/Makefile 193 | .PRECIOUS: Makefile 194 | Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status 195 | @case '$?' in \ 196 | *config.status*) \ 197 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ 198 | *) \ 199 | echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ 200 | cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ 201 | esac; 202 | 203 | $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) 204 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh 205 | 206 | $(top_srcdir)/configure: $(am__configure_deps) 207 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh 208 | $(ACLOCAL_M4): $(am__aclocal_m4_deps) 209 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh 210 | install-libtclapincludeHEADERS: $(libtclapinclude_HEADERS) 211 | @$(NORMAL_INSTALL) 212 | test -z "$(libtclapincludedir)" || $(MKDIR_P) "$(DESTDIR)$(libtclapincludedir)" 213 | @list='$(libtclapinclude_HEADERS)'; for p in $$list; do \ 214 | if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ 215 | f=$(am__strip_dir) \ 216 | echo " $(libtclapincludeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(libtclapincludedir)/$$f'"; \ 217 | $(libtclapincludeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(libtclapincludedir)/$$f"; \ 218 | done 219 | 220 | uninstall-libtclapincludeHEADERS: 221 | @$(NORMAL_UNINSTALL) 222 | @list='$(libtclapinclude_HEADERS)'; for p in $$list; do \ 223 | f=$(am__strip_dir) \ 224 | echo " rm -f '$(DESTDIR)$(libtclapincludedir)/$$f'"; \ 225 | rm -f "$(DESTDIR)$(libtclapincludedir)/$$f"; \ 226 | done 227 | 228 | ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) 229 | list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ 230 | unique=`for i in $$list; do \ 231 | if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ 232 | done | \ 233 | $(AWK) ' { files[$$0] = 1; } \ 234 | END { for (i in files) print i; }'`; \ 235 | mkid -fID $$unique 236 | tags: TAGS 237 | 238 | TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ 239 | $(TAGS_FILES) $(LISP) 240 | tags=; \ 241 | here=`pwd`; \ 242 | list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ 243 | unique=`for i in $$list; do \ 244 | if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ 245 | done | \ 246 | $(AWK) ' { files[$$0] = 1; } \ 247 | END { for (i in files) print i; }'`; \ 248 | if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ 249 | test -n "$$unique" || unique=$$empty_fix; \ 250 | $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ 251 | $$tags $$unique; \ 252 | fi 253 | ctags: CTAGS 254 | CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ 255 | $(TAGS_FILES) $(LISP) 256 | tags=; \ 257 | here=`pwd`; \ 258 | list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ 259 | unique=`for i in $$list; do \ 260 | if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ 261 | done | \ 262 | $(AWK) ' { files[$$0] = 1; } \ 263 | END { for (i in files) print i; }'`; \ 264 | test -z "$(CTAGS_ARGS)$$tags$$unique" \ 265 | || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ 266 | $$tags $$unique 267 | 268 | GTAGS: 269 | here=`$(am__cd) $(top_builddir) && pwd` \ 270 | && cd $(top_srcdir) \ 271 | && gtags -i $(GTAGS_ARGS) $$here 272 | 273 | distclean-tags: 274 | -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags 275 | 276 | distdir: $(DISTFILES) 277 | @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ 278 | topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ 279 | list='$(DISTFILES)'; \ 280 | dist_files=`for file in $$list; do echo $$file; done | \ 281 | sed -e "s|^$$srcdirstrip/||;t" \ 282 | -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ 283 | case $$dist_files in \ 284 | */*) $(MKDIR_P) `echo "$$dist_files" | \ 285 | sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ 286 | sort -u` ;; \ 287 | esac; \ 288 | for file in $$dist_files; do \ 289 | if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ 290 | if test -d $$d/$$file; then \ 291 | dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ 292 | if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ 293 | cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ 294 | fi; \ 295 | cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ 296 | else \ 297 | test -f $(distdir)/$$file \ 298 | || cp -p $$d/$$file $(distdir)/$$file \ 299 | || exit 1; \ 300 | fi; \ 301 | done 302 | check-am: all-am 303 | check: check-am 304 | all-am: Makefile $(HEADERS) 305 | installdirs: 306 | for dir in "$(DESTDIR)$(libtclapincludedir)"; do \ 307 | test -z "$$dir" || $(MKDIR_P) "$$dir"; \ 308 | done 309 | install: install-am 310 | install-exec: install-exec-am 311 | install-data: install-data-am 312 | uninstall: uninstall-am 313 | 314 | install-am: all-am 315 | @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am 316 | 317 | installcheck: installcheck-am 318 | install-strip: 319 | $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ 320 | install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ 321 | `test -z '$(STRIP)' || \ 322 | echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install 323 | mostlyclean-generic: 324 | 325 | clean-generic: 326 | 327 | distclean-generic: 328 | -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) 329 | 330 | maintainer-clean-generic: 331 | @echo "This command is intended for maintainers to use" 332 | @echo "it deletes files that may require special tools to rebuild." 333 | clean: clean-am 334 | 335 | clean-am: clean-generic mostlyclean-am 336 | 337 | distclean: distclean-am 338 | -rm -f Makefile 339 | distclean-am: clean-am distclean-generic distclean-tags 340 | 341 | dvi: dvi-am 342 | 343 | dvi-am: 344 | 345 | html: html-am 346 | 347 | info: info-am 348 | 349 | info-am: 350 | 351 | install-data-am: install-libtclapincludeHEADERS 352 | 353 | install-dvi: install-dvi-am 354 | 355 | install-exec-am: 356 | 357 | install-html: install-html-am 358 | 359 | install-info: install-info-am 360 | 361 | install-man: 362 | 363 | install-pdf: install-pdf-am 364 | 365 | install-ps: install-ps-am 366 | 367 | installcheck-am: 368 | 369 | maintainer-clean: maintainer-clean-am 370 | -rm -f Makefile 371 | maintainer-clean-am: distclean-am maintainer-clean-generic 372 | 373 | mostlyclean: mostlyclean-am 374 | 375 | mostlyclean-am: mostlyclean-generic 376 | 377 | pdf: pdf-am 378 | 379 | pdf-am: 380 | 381 | ps: ps-am 382 | 383 | ps-am: 384 | 385 | uninstall-am: uninstall-libtclapincludeHEADERS 386 | 387 | .MAKE: install-am install-strip 388 | 389 | .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ 390 | ctags distclean distclean-generic distclean-tags distdir dvi \ 391 | dvi-am html html-am info info-am install install-am \ 392 | install-data install-data-am install-dvi install-dvi-am \ 393 | install-exec install-exec-am install-html install-html-am \ 394 | install-info install-info-am install-libtclapincludeHEADERS \ 395 | install-man install-pdf install-pdf-am install-ps \ 396 | install-ps-am install-strip installcheck installcheck-am \ 397 | installdirs maintainer-clean maintainer-clean-generic \ 398 | mostlyclean mostlyclean-generic pdf pdf-am ps ps-am tags \ 399 | uninstall uninstall-am uninstall-libtclapincludeHEADERS 400 | 401 | # Tell versions [3.59,3.63) of GNU make to not export all variables. 402 | # Otherwise a system limit (for SysV at least) may be exceeded. 403 | .NOEXPORT: 404 | -------------------------------------------------------------------------------- /src/tclap/MultiSwitchArg.h: -------------------------------------------------------------------------------- 1 | 2 | /****************************************************************************** 3 | * 4 | * file: MultiSwitchArg.h 5 | * 6 | * Copyright (c) 2003, Michael E. Smoot . 7 | * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. 8 | * Copyright (c) 2005, Michael E. Smoot, Daniel Aarno, Erik Zeek. 9 | * All rights reverved. 10 | * 11 | * See the file COPYING in the top directory of this distribution for 12 | * more information. 13 | * 14 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | * 22 | *****************************************************************************/ 23 | 24 | 25 | #ifndef TCLAP_MULTI_SWITCH_ARG_H 26 | #define TCLAP_MULTI_SWITCH_ARG_H 27 | 28 | #include 29 | #include 30 | 31 | #include 32 | 33 | namespace TCLAP { 34 | 35 | /** 36 | * A multiple switch argument. If the switch is set on the command line, then 37 | * the getValue method will return the number of times the switch appears. 38 | */ 39 | class MultiSwitchArg : public SwitchArg 40 | { 41 | protected: 42 | 43 | /** 44 | * The value of the switch. 45 | */ 46 | int _value; 47 | 48 | /** 49 | * Used to support the reset() method so that ValueArg can be 50 | * reset to their constructed value. 51 | */ 52 | int _default; 53 | 54 | public: 55 | 56 | /** 57 | * MultiSwitchArg constructor. 58 | * \param flag - The one character flag that identifies this 59 | * argument on the command line. 60 | * \param name - A one word name for the argument. Can be 61 | * used as a long flag on the command line. 62 | * \param desc - A description of what the argument is for or 63 | * does. 64 | * \param init - Optional. The initial/default value of this Arg. 65 | * Defaults to 0. 66 | * \param v - An optional visitor. You probably should not 67 | * use this unless you have a very good reason. 68 | */ 69 | MultiSwitchArg(const std::string& flag, 70 | const std::string& name, 71 | const std::string& desc, 72 | int init = 0, 73 | Visitor* v = NULL); 74 | 75 | 76 | /** 77 | * MultiSwitchArg constructor. 78 | * \param flag - The one character flag that identifies this 79 | * argument on the command line. 80 | * \param name - A one word name for the argument. Can be 81 | * used as a long flag on the command line. 82 | * \param desc - A description of what the argument is for or 83 | * does. 84 | * \param parser - A CmdLine parser object to add this Arg to 85 | * \param init - Optional. The initial/default value of this Arg. 86 | * Defaults to 0. 87 | * \param v - An optional visitor. You probably should not 88 | * use this unless you have a very good reason. 89 | */ 90 | MultiSwitchArg(const std::string& flag, 91 | const std::string& name, 92 | const std::string& desc, 93 | CmdLineInterface& parser, 94 | int init = 0, 95 | Visitor* v = NULL); 96 | 97 | 98 | /** 99 | * Handles the processing of the argument. 100 | * This re-implements the SwitchArg version of this method to set the 101 | * _value of the argument appropriately. 102 | * \param i - Pointer the the current argument in the list. 103 | * \param args - Mutable list of strings. Passed 104 | * in from main(). 105 | */ 106 | virtual bool processArg(int* i, std::vector& args); 107 | 108 | /** 109 | * Returns int, the number of times the switch has been set. 110 | */ 111 | int getValue(); 112 | 113 | /** 114 | * Returns the shortID for this Arg. 115 | */ 116 | std::string shortID(const std::string& val) const; 117 | 118 | /** 119 | * Returns the longID for this Arg. 120 | */ 121 | std::string longID(const std::string& val) const; 122 | 123 | void reset(); 124 | 125 | }; 126 | 127 | ////////////////////////////////////////////////////////////////////// 128 | //BEGIN MultiSwitchArg.cpp 129 | ////////////////////////////////////////////////////////////////////// 130 | inline MultiSwitchArg::MultiSwitchArg(const std::string& flag, 131 | const std::string& name, 132 | const std::string& desc, 133 | int init, 134 | Visitor* v ) 135 | : SwitchArg(flag, name, desc, false, v), 136 | _value( init ), 137 | _default( init ) 138 | { } 139 | 140 | inline MultiSwitchArg::MultiSwitchArg(const std::string& flag, 141 | const std::string& name, 142 | const std::string& desc, 143 | CmdLineInterface& parser, 144 | int init, 145 | Visitor* v ) 146 | : SwitchArg(flag, name, desc, false, v), 147 | _value( init ), 148 | _default( init ) 149 | { 150 | parser.add( this ); 151 | } 152 | 153 | inline int MultiSwitchArg::getValue() { return _value; } 154 | 155 | inline bool MultiSwitchArg::processArg(int *i, std::vector& args) 156 | { 157 | if ( _ignoreable && Arg::ignoreRest() ) 158 | return false; 159 | 160 | if ( argMatches( args[*i] )) 161 | { 162 | // so the isSet() method will work 163 | _alreadySet = true; 164 | 165 | // Matched argument: increment value. 166 | ++_value; 167 | 168 | _checkWithVisitor(); 169 | 170 | return true; 171 | } 172 | else if ( combinedSwitchesMatch( args[*i] ) ) 173 | { 174 | // so the isSet() method will work 175 | _alreadySet = true; 176 | 177 | // Matched argument: increment value. 178 | ++_value; 179 | 180 | // Check for more in argument and increment value. 181 | while ( combinedSwitchesMatch( args[*i] ) ) 182 | ++_value; 183 | 184 | _checkWithVisitor(); 185 | 186 | return false; 187 | } 188 | else 189 | return false; 190 | } 191 | 192 | inline std::string 193 | MultiSwitchArg::shortID(const std::string& val) const 194 | { 195 | return Arg::shortID(val) + " ... "; 196 | } 197 | 198 | inline std::string 199 | MultiSwitchArg::longID(const std::string& val) const 200 | { 201 | return Arg::longID(val) + " (accepted multiple times)"; 202 | } 203 | 204 | inline void 205 | MultiSwitchArg::reset() 206 | { 207 | MultiSwitchArg::_value = MultiSwitchArg::_default; 208 | } 209 | 210 | ////////////////////////////////////////////////////////////////////// 211 | //END MultiSwitchArg.cpp 212 | ////////////////////////////////////////////////////////////////////// 213 | 214 | } //namespace TCLAP 215 | 216 | #endif 217 | -------------------------------------------------------------------------------- /src/tclap/OptionalUnlabeledTracker.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | /****************************************************************************** 4 | * 5 | * file: OptionalUnlabeledTracker.h 6 | * 7 | * Copyright (c) 2005, Michael E. Smoot . 8 | * All rights reverved. 9 | * 10 | * See the file COPYING in the top directory of this distribution for 11 | * more information. 12 | * 13 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | * DEALINGS IN THE SOFTWARE. 20 | * 21 | *****************************************************************************/ 22 | 23 | 24 | #ifndef TCLAP_OPTIONAL_UNLABELED_TRACKER_H 25 | #define TCLAP_OPTIONAL_UNLABELED_TRACKER_H 26 | 27 | #include 28 | 29 | namespace TCLAP { 30 | 31 | class OptionalUnlabeledTracker 32 | { 33 | 34 | public: 35 | 36 | static void check( bool req, const std::string& argName ); 37 | 38 | static void gotOptional() { alreadyOptionalRef() = true; } 39 | 40 | static bool& alreadyOptional() { return alreadyOptionalRef(); } 41 | 42 | private: 43 | 44 | static bool& alreadyOptionalRef() { static bool ct = false; return ct; } 45 | }; 46 | 47 | 48 | inline void OptionalUnlabeledTracker::check( bool req, const std::string& argName ) 49 | { 50 | if ( OptionalUnlabeledTracker::alreadyOptional() ) 51 | throw( SpecificationException( 52 | "You can't specify ANY Unlabeled Arg following an optional Unlabeled Arg", 53 | argName ) ); 54 | 55 | if ( !req ) 56 | OptionalUnlabeledTracker::gotOptional(); 57 | } 58 | 59 | 60 | } // namespace TCLAP 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /src/tclap/StandardTraits.h: -------------------------------------------------------------------------------- 1 | // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- 2 | 3 | /****************************************************************************** 4 | * 5 | * file: StandardTraits.h 6 | * 7 | * Copyright (c) 2007, Daniel Aarno, Michael E. Smoot . 8 | * All rights reverved. 9 | * 10 | * See the file COPYING in the top directory of this distribution for 11 | * more information. 12 | * 13 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | * DEALINGS IN THE SOFTWARE. 20 | * 21 | *****************************************************************************/ 22 | 23 | // This is an internal tclap file, you should probably not have to 24 | // include this directly 25 | 26 | #ifndef TCLAP_STANDARD_TRAITS_H 27 | #define TCLAP_STANDARD_TRAITS_H 28 | 29 | #ifdef HAVE_CONFIG_H 30 | #include // To check for long long 31 | #endif 32 | 33 | // If Microsoft has already typedef'd wchar_t as an unsigned 34 | // short, then compiles will break because it's as if we're 35 | // creating ArgTraits twice for unsigned short. Thus... 36 | #ifdef _MSC_VER 37 | #ifndef _NATIVE_WCHAR_T_DEFINED 38 | #define TCLAP_DONT_DECLARE_WCHAR_T_ARGTRAITS 39 | #endif 40 | #endif 41 | 42 | namespace TCLAP { 43 | 44 | // ====================================================================== 45 | // Integer types 46 | // ====================================================================== 47 | 48 | /** 49 | * longs have value-like semantics. 50 | */ 51 | template<> 52 | struct ArgTraits { 53 | typedef ValueLike ValueCategory; 54 | }; 55 | 56 | /** 57 | * ints have value-like semantics. 58 | */ 59 | template<> 60 | struct ArgTraits { 61 | typedef ValueLike ValueCategory; 62 | }; 63 | 64 | /** 65 | * shorts have value-like semantics. 66 | */ 67 | template<> 68 | struct ArgTraits { 69 | typedef ValueLike ValueCategory; 70 | }; 71 | 72 | /** 73 | * chars have value-like semantics. 74 | */ 75 | template<> 76 | struct ArgTraits { 77 | typedef ValueLike ValueCategory; 78 | }; 79 | 80 | #ifdef HAVE_LONG_LONG 81 | /** 82 | * long longs have value-like semantics. 83 | */ 84 | template<> 85 | struct ArgTraits { 86 | typedef ValueLike ValueCategory; 87 | }; 88 | #endif 89 | 90 | // ====================================================================== 91 | // Unsigned integer types 92 | // ====================================================================== 93 | 94 | /** 95 | * unsigned longs have value-like semantics. 96 | */ 97 | template<> 98 | struct ArgTraits { 99 | typedef ValueLike ValueCategory; 100 | }; 101 | 102 | /** 103 | * unsigned ints have value-like semantics. 104 | */ 105 | template<> 106 | struct ArgTraits { 107 | typedef ValueLike ValueCategory; 108 | }; 109 | 110 | /** 111 | * unsigned shorts have value-like semantics. 112 | */ 113 | template<> 114 | struct ArgTraits { 115 | typedef ValueLike ValueCategory; 116 | }; 117 | 118 | /** 119 | * unsigned chars have value-like semantics. 120 | */ 121 | template<> 122 | struct ArgTraits { 123 | typedef ValueLike ValueCategory; 124 | }; 125 | 126 | // Microsoft implements size_t awkwardly. 127 | #if defined(_MSC_VER) && defined(_M_X64) 128 | /** 129 | * size_ts have value-like semantics. 130 | */ 131 | template<> 132 | struct ArgTraits { 133 | typedef ValueLike ValueCategory; 134 | }; 135 | #endif 136 | 137 | 138 | #ifdef HAVE_LONG_LONG 139 | /** 140 | * unsigned long longs have value-like semantics. 141 | */ 142 | template<> 143 | struct ArgTraits { 144 | typedef ValueLike ValueCategory; 145 | }; 146 | #endif 147 | 148 | // ====================================================================== 149 | // Float types 150 | // ====================================================================== 151 | 152 | /** 153 | * floats have value-like semantics. 154 | */ 155 | template<> 156 | struct ArgTraits { 157 | typedef ValueLike ValueCategory; 158 | }; 159 | 160 | /** 161 | * doubles have value-like semantics. 162 | */ 163 | template<> 164 | struct ArgTraits { 165 | typedef ValueLike ValueCategory; 166 | }; 167 | 168 | // ====================================================================== 169 | // Other types 170 | // ====================================================================== 171 | 172 | /** 173 | * bools have value-like semantics. 174 | */ 175 | template<> 176 | struct ArgTraits { 177 | typedef ValueLike ValueCategory; 178 | }; 179 | 180 | 181 | /** 182 | * wchar_ts have value-like semantics. 183 | */ 184 | #ifndef TCLAP_DONT_DECLARE_WCHAR_T_ARGTRAITS 185 | template<> 186 | struct ArgTraits { 187 | typedef ValueLike ValueCategory; 188 | }; 189 | #endif 190 | 191 | /** 192 | * Strings have string like argument traits. 193 | */ 194 | template<> 195 | struct ArgTraits { 196 | typedef StringLike ValueCategory; 197 | }; 198 | 199 | template 200 | void SetString(T &dst, const std::string &src) 201 | { 202 | dst = src; 203 | } 204 | 205 | } // namespace 206 | 207 | #endif 208 | 209 | -------------------------------------------------------------------------------- /src/tclap/StdOutput.h: -------------------------------------------------------------------------------- 1 | // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- 2 | 3 | /****************************************************************************** 4 | * 5 | * file: StdOutput.h 6 | * 7 | * Copyright (c) 2004, Michael E. Smoot 8 | * All rights reverved. 9 | * 10 | * See the file COPYING in the top directory of this distribution for 11 | * more information. 12 | * 13 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | * DEALINGS IN THE SOFTWARE. 20 | * 21 | *****************************************************************************/ 22 | 23 | #ifndef TCLAP_STDCMDLINEOUTPUT_H 24 | #define TCLAP_STDCMDLINEOUTPUT_H 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | namespace TCLAP { 38 | 39 | /** 40 | * A class that isolates any output from the CmdLine object so that it 41 | * may be easily modified. 42 | */ 43 | class StdOutput : public CmdLineOutput 44 | { 45 | 46 | public: 47 | 48 | /** 49 | * Prints the usage to stdout. Can be overridden to 50 | * produce alternative behavior. 51 | * \param c - The CmdLine object the output is generated for. 52 | */ 53 | virtual void usage(CmdLineInterface& c); 54 | 55 | /** 56 | * Prints the version to stdout. Can be overridden 57 | * to produce alternative behavior. 58 | * \param c - The CmdLine object the output is generated for. 59 | */ 60 | virtual void version(CmdLineInterface& c); 61 | 62 | /** 63 | * Prints (to stderr) an error message, short usage 64 | * Can be overridden to produce alternative behavior. 65 | * \param c - The CmdLine object the output is generated for. 66 | * \param e - The ArgException that caused the failure. 67 | */ 68 | virtual void failure(CmdLineInterface& c, 69 | ArgException& e ); 70 | 71 | protected: 72 | 73 | /** 74 | * Writes a brief usage message with short args. 75 | * \param c - The CmdLine object the output is generated for. 76 | * \param os - The stream to write the message to. 77 | */ 78 | void _shortUsage( CmdLineInterface& c, std::ostream& os ) const; 79 | 80 | /** 81 | * Writes a longer usage message with long and short args, 82 | * provides descriptions and prints message. 83 | * \param c - The CmdLine object the output is generated for. 84 | * \param os - The stream to write the message to. 85 | */ 86 | void _longUsage( CmdLineInterface& c, std::ostream& os ) const; 87 | 88 | /** 89 | * This function inserts line breaks and indents long strings 90 | * according the params input. It will only break lines at spaces, 91 | * commas and pipes. 92 | * \param os - The stream to be printed to. 93 | * \param s - The string to be printed. 94 | * \param maxWidth - The maxWidth allowed for the output line. 95 | * \param indentSpaces - The number of spaces to indent the first line. 96 | * \param secondLineOffset - The number of spaces to indent the second 97 | * and all subsequent lines in addition to indentSpaces. 98 | */ 99 | void spacePrint( std::ostream& os, 100 | const std::string& s, 101 | int maxWidth, 102 | int indentSpaces, 103 | int secondLineOffset ) const; 104 | 105 | }; 106 | 107 | 108 | inline void StdOutput::version(CmdLineInterface& _cmd) 109 | { 110 | std::string progName = _cmd.getProgramName(); 111 | std::string xversion = _cmd.getVersion(); 112 | 113 | std::cout << std::endl << progName << " version: " 114 | << xversion << std::endl << std::endl; 115 | } 116 | 117 | inline void StdOutput::usage(CmdLineInterface& _cmd ) 118 | { 119 | std::cout << std::endl << "USAGE: " << std::endl << std::endl; 120 | 121 | _shortUsage( _cmd, std::cout ); 122 | 123 | std::cout << std::endl << std::endl << "Where: " << std::endl << std::endl; 124 | 125 | _longUsage( _cmd, std::cout ); 126 | 127 | std::cout << std::endl; 128 | 129 | } 130 | 131 | inline void StdOutput::failure( CmdLineInterface& _cmd, 132 | ArgException& e ) 133 | { 134 | std::string progName = _cmd.getProgramName(); 135 | 136 | std::cerr << "PARSE ERROR: " << e.argId() << std::endl 137 | << " " << e.error() << std::endl << std::endl; 138 | 139 | if ( _cmd.hasHelpAndVersion() ) 140 | { 141 | std::cerr << "Brief USAGE: " << std::endl; 142 | 143 | _shortUsage( _cmd, std::cerr ); 144 | 145 | std::cerr << std::endl << "For complete USAGE and HELP type: " 146 | << std::endl << " " << progName << " --help" 147 | << std::endl << std::endl; 148 | } 149 | else 150 | usage(_cmd); 151 | 152 | throw ExitException(1); 153 | } 154 | 155 | inline void 156 | StdOutput::_shortUsage( CmdLineInterface& _cmd, 157 | std::ostream& os ) const 158 | { 159 | std::list argList = _cmd.getArgList(); 160 | std::string progName = _cmd.getProgramName(); 161 | XorHandler xorHandler = _cmd.getXorHandler(); 162 | std::vector< std::vector > xorList = xorHandler.getXorList(); 163 | 164 | std::string s = progName + " "; 165 | 166 | // first the xor 167 | for ( int i = 0; static_cast(i) < xorList.size(); i++ ) 168 | { 169 | s += " {"; 170 | for ( ArgVectorIterator it = xorList[i].begin(); 171 | it != xorList[i].end(); it++ ) 172 | s += (*it)->shortID() + "|"; 173 | 174 | s[s.length()-1] = '}'; 175 | } 176 | 177 | // then the rest 178 | for (ArgListIterator it = argList.begin(); it != argList.end(); it++) 179 | if ( !xorHandler.contains( (*it) ) ) 180 | s += " " + (*it)->shortID(); 181 | 182 | // if the program name is too long, then adjust the second line offset 183 | int secondLineOffset = static_cast(progName.length()) + 2; 184 | if ( secondLineOffset > 75/2 ) 185 | secondLineOffset = static_cast(75/2); 186 | 187 | spacePrint( os, s, 75, 3, secondLineOffset ); 188 | } 189 | 190 | inline void 191 | StdOutput::_longUsage( CmdLineInterface& _cmd, 192 | std::ostream& os ) const 193 | { 194 | std::list argList = _cmd.getArgList(); 195 | std::string message = _cmd.getMessage(); 196 | XorHandler xorHandler = _cmd.getXorHandler(); 197 | std::vector< std::vector > xorList = xorHandler.getXorList(); 198 | 199 | // first the xor 200 | for ( int i = 0; static_cast(i) < xorList.size(); i++ ) 201 | { 202 | for ( ArgVectorIterator it = xorList[i].begin(); 203 | it != xorList[i].end(); 204 | it++ ) 205 | { 206 | spacePrint( os, (*it)->longID(), 75, 3, 3 ); 207 | spacePrint( os, (*it)->getDescription(), 75, 5, 0 ); 208 | 209 | if ( it+1 != xorList[i].end() ) 210 | spacePrint(os, "-- OR --", 75, 9, 0); 211 | } 212 | os << std::endl << std::endl; 213 | } 214 | 215 | // then the rest 216 | for (ArgListIterator it = argList.begin(); it != argList.end(); it++) 217 | if ( !xorHandler.contains( (*it) ) ) 218 | { 219 | spacePrint( os, (*it)->longID(), 75, 3, 3 ); 220 | spacePrint( os, (*it)->getDescription(), 75, 5, 0 ); 221 | os << std::endl; 222 | } 223 | 224 | os << std::endl; 225 | 226 | spacePrint( os, message, 75, 3, 0 ); 227 | } 228 | 229 | inline void StdOutput::spacePrint( std::ostream& os, 230 | const std::string& s, 231 | int maxWidth, 232 | int indentSpaces, 233 | int secondLineOffset ) const 234 | { 235 | int len = static_cast(s.length()); 236 | 237 | if ( (len + indentSpaces > maxWidth) && maxWidth > 0 ) 238 | { 239 | int allowedLen = maxWidth - indentSpaces; 240 | int start = 0; 241 | while ( start < len ) 242 | { 243 | // find the substring length 244 | // int stringLen = std::min( len - start, allowedLen ); 245 | // doing it this way to support a VisualC++ 2005 bug 246 | using namespace std; 247 | int stringLen = min( len - start, allowedLen ); 248 | 249 | // trim the length so it doesn't end in middle of a word 250 | if ( stringLen == allowedLen ) 251 | while ( stringLen >= 0 && 252 | s[stringLen+start] != ' ' && 253 | s[stringLen+start] != ',' && 254 | s[stringLen+start] != '|' ) 255 | stringLen--; 256 | 257 | // ok, the word is longer than the line, so just split 258 | // wherever the line ends 259 | if ( stringLen <= 0 ) 260 | stringLen = allowedLen; 261 | 262 | // check for newlines 263 | for ( int i = 0; i < stringLen; i++ ) 264 | if ( s[start+i] == '\n' ) 265 | stringLen = i+1; 266 | 267 | // print the indent 268 | for ( int i = 0; i < indentSpaces; i++ ) 269 | os << " "; 270 | 271 | if ( start == 0 ) 272 | { 273 | // handle second line offsets 274 | indentSpaces += secondLineOffset; 275 | 276 | // adjust allowed len 277 | allowedLen -= secondLineOffset; 278 | } 279 | 280 | os << s.substr(start,stringLen) << std::endl; 281 | 282 | // so we don't start a line with a space 283 | while ( s[stringLen+start] == ' ' && start < len ) 284 | start++; 285 | 286 | start += stringLen; 287 | } 288 | } 289 | else 290 | { 291 | for ( int i = 0; i < indentSpaces; i++ ) 292 | os << " "; 293 | os << s << std::endl; 294 | } 295 | } 296 | 297 | } //namespace TCLAP 298 | #endif 299 | -------------------------------------------------------------------------------- /src/tclap/SwitchArg.h: -------------------------------------------------------------------------------- 1 | 2 | /****************************************************************************** 3 | * 4 | * file: SwitchArg.h 5 | * 6 | * Copyright (c) 2003, Michael E. Smoot . 7 | * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. 8 | * All rights reverved. 9 | * 10 | * See the file COPYING in the top directory of this distribution for 11 | * more information. 12 | * 13 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | * DEALINGS IN THE SOFTWARE. 20 | * 21 | *****************************************************************************/ 22 | 23 | 24 | #ifndef TCLAP_SWITCH_ARG_H 25 | #define TCLAP_SWITCH_ARG_H 26 | 27 | #include 28 | #include 29 | 30 | #include 31 | 32 | namespace TCLAP { 33 | 34 | /** 35 | * A simple switch argument. If the switch is set on the command line, then 36 | * the getValue method will return the opposite of the default value for the 37 | * switch. 38 | */ 39 | class SwitchArg : public Arg 40 | { 41 | protected: 42 | 43 | /** 44 | * The value of the switch. 45 | */ 46 | bool _value; 47 | 48 | /** 49 | * Used to support the reset() method so that ValueArg can be 50 | * reset to their constructed value. 51 | */ 52 | bool _default; 53 | 54 | public: 55 | 56 | /** 57 | * SwitchArg constructor. 58 | * \param flag - The one character flag that identifies this 59 | * argument on the command line. 60 | * \param name - A one word name for the argument. Can be 61 | * used as a long flag on the command line. 62 | * \param desc - A description of what the argument is for or 63 | * does. 64 | * \param def - The default value for this Switch. 65 | * \param v - An optional visitor. You probably should not 66 | * use this unless you have a very good reason. 67 | */ 68 | SwitchArg(const std::string& flag, 69 | const std::string& name, 70 | const std::string& desc, 71 | bool def = false, 72 | Visitor* v = NULL); 73 | 74 | 75 | /** 76 | * SwitchArg constructor. 77 | * \param flag - The one character flag that identifies this 78 | * argument on the command line. 79 | * \param name - A one word name for the argument. Can be 80 | * used as a long flag on the command line. 81 | * \param desc - A description of what the argument is for or 82 | * does. 83 | * \param parser - A CmdLine parser object to add this Arg to 84 | * \param def - The default value for this Switch. 85 | * \param v - An optional visitor. You probably should not 86 | * use this unless you have a very good reason. 87 | */ 88 | SwitchArg(const std::string& flag, 89 | const std::string& name, 90 | const std::string& desc, 91 | CmdLineInterface& parser, 92 | bool def = false, 93 | Visitor* v = NULL); 94 | 95 | 96 | /** 97 | * Handles the processing of the argument. 98 | * This re-implements the Arg version of this method to set the 99 | * _value of the argument appropriately. 100 | * \param i - Pointer the the current argument in the list. 101 | * \param args - Mutable list of strings. Passed 102 | * in from main(). 103 | */ 104 | virtual bool processArg(int* i, std::vector& args); 105 | 106 | /** 107 | * Checks a string to see if any of the chars in the string 108 | * match the flag for this Switch. 109 | */ 110 | bool combinedSwitchesMatch(std::string& combined); 111 | 112 | /** 113 | * Returns bool, whether or not the switch has been set. 114 | */ 115 | bool getValue(); 116 | 117 | virtual void reset(); 118 | 119 | private: 120 | /** 121 | * Checks to see if we've found the last match in 122 | * a combined string. 123 | */ 124 | bool lastCombined(std::string& combined); 125 | 126 | /** 127 | * Does the common processing of processArg. 128 | */ 129 | void commonProcessing(); 130 | }; 131 | 132 | ////////////////////////////////////////////////////////////////////// 133 | //BEGIN SwitchArg.cpp 134 | ////////////////////////////////////////////////////////////////////// 135 | inline SwitchArg::SwitchArg(const std::string& flag, 136 | const std::string& name, 137 | const std::string& desc, 138 | bool default_val, 139 | Visitor* v ) 140 | : Arg(flag, name, desc, false, false, v), 141 | _value( default_val ), 142 | _default( default_val ) 143 | { } 144 | 145 | inline SwitchArg::SwitchArg(const std::string& flag, 146 | const std::string& name, 147 | const std::string& desc, 148 | CmdLineInterface& parser, 149 | bool default_val, 150 | Visitor* v ) 151 | : Arg(flag, name, desc, false, false, v), 152 | _value( default_val ), 153 | _default(default_val) 154 | { 155 | parser.add( this ); 156 | } 157 | 158 | inline bool SwitchArg::getValue() { return _value; } 159 | 160 | inline bool SwitchArg::lastCombined(std::string& combinedSwitches ) 161 | { 162 | for ( unsigned int i = 1; i < combinedSwitches.length(); i++ ) 163 | if ( combinedSwitches[i] != Arg::blankChar() ) 164 | return false; 165 | 166 | return true; 167 | } 168 | 169 | inline bool SwitchArg::combinedSwitchesMatch(std::string& combinedSwitches ) 170 | { 171 | // make sure this is actually a combined switch 172 | if ( combinedSwitches.length() > 0 && 173 | combinedSwitches[0] != Arg::flagStartString()[0] ) 174 | return false; 175 | 176 | // make sure it isn't a long name 177 | if ( combinedSwitches.substr( 0, Arg::nameStartString().length() ) == 178 | Arg::nameStartString() ) 179 | return false; 180 | 181 | // make sure the delimiter isn't in the string 182 | if ( combinedSwitches.find_first_of( Arg::delimiter() ) != std::string::npos ) 183 | return false; 184 | 185 | // ok, we're not specifying a ValueArg, so we know that we have 186 | // a combined switch list. 187 | for ( unsigned int i = 1; i < combinedSwitches.length(); i++ ) 188 | if ( _flag.length() > 0 && 189 | combinedSwitches[i] == _flag[0] && 190 | _flag[0] != Arg::flagStartString()[0] ) 191 | { 192 | // update the combined switches so this one is no longer present 193 | // this is necessary so that no unlabeled args are matched 194 | // later in the processing. 195 | //combinedSwitches.erase(i,1); 196 | combinedSwitches[i] = Arg::blankChar(); 197 | return true; 198 | } 199 | 200 | // none of the switches passed in the list match. 201 | return false; 202 | } 203 | 204 | inline void SwitchArg::commonProcessing() 205 | { 206 | if ( _xorSet ) 207 | throw(CmdLineParseException( 208 | "Mutually exclusive argument already set!", toString())); 209 | 210 | if ( _alreadySet ) 211 | throw(CmdLineParseException("Argument already set!", toString())); 212 | 213 | _alreadySet = true; 214 | 215 | if ( _value == true ) 216 | _value = false; 217 | else 218 | _value = true; 219 | 220 | _checkWithVisitor(); 221 | } 222 | 223 | inline bool SwitchArg::processArg(int *i, std::vector& args) 224 | { 225 | if ( _ignoreable && Arg::ignoreRest() ) 226 | return false; 227 | 228 | // if the whole string matches the flag or name string 229 | if ( argMatches( args[*i] ) ) 230 | { 231 | commonProcessing(); 232 | 233 | return true; 234 | } 235 | // if a substring matches the flag as part of a combination 236 | else if ( combinedSwitchesMatch( args[*i] ) ) 237 | { 238 | // check again to ensure we don't misinterpret 239 | // this as a MultiSwitchArg 240 | if ( combinedSwitchesMatch( args[*i] ) ) 241 | throw(CmdLineParseException("Argument already set!", 242 | toString())); 243 | 244 | commonProcessing(); 245 | 246 | // We only want to return true if we've found the last combined 247 | // match in the string, otherwise we return true so that other 248 | // switches in the combination will have a chance to match. 249 | return lastCombined( args[*i] ); 250 | } 251 | else 252 | return false; 253 | } 254 | 255 | inline void SwitchArg::reset() 256 | { 257 | Arg::reset(); 258 | _value = _default; 259 | } 260 | ////////////////////////////////////////////////////////////////////// 261 | //End SwitchArg.cpp 262 | ////////////////////////////////////////////////////////////////////// 263 | 264 | } //namespace TCLAP 265 | 266 | #endif 267 | -------------------------------------------------------------------------------- /src/tclap/UnlabeledMultiArg.h: -------------------------------------------------------------------------------- 1 | 2 | /****************************************************************************** 3 | * 4 | * file: UnlabeledMultiArg.h 5 | * 6 | * Copyright (c) 2003, Michael E. Smoot. 7 | * All rights reverved. 8 | * 9 | * See the file COPYING in the top directory of this distribution for 10 | * more information. 11 | * 12 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 13 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 15 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 17 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 18 | * DEALINGS IN THE SOFTWARE. 19 | * 20 | *****************************************************************************/ 21 | 22 | 23 | #ifndef TCLAP_MULTIPLE_UNLABELED_ARGUMENT_H 24 | #define TCLAP_MULTIPLE_UNLABELED_ARGUMENT_H 25 | 26 | #include 27 | #include 28 | 29 | #include 30 | #include 31 | 32 | namespace TCLAP { 33 | 34 | /** 35 | * Just like a MultiArg, except that the arguments are unlabeled. Basically, 36 | * this Arg will slurp up everything that hasn't been matched to another 37 | * Arg. 38 | */ 39 | template 40 | class UnlabeledMultiArg : public MultiArg 41 | { 42 | 43 | // If compiler has two stage name lookup (as gcc >= 3.4 does) 44 | // this is requried to prevent undef. symbols 45 | using MultiArg::_ignoreable; 46 | using MultiArg::_hasBlanks; 47 | using MultiArg::_extractValue; 48 | using MultiArg::_typeDesc; 49 | using MultiArg::_name; 50 | using MultiArg::_description; 51 | using MultiArg::_alreadySet; 52 | using MultiArg::toString; 53 | 54 | public: 55 | 56 | /** 57 | * Constructor. 58 | * \param name - The name of the Arg. Note that this is used for 59 | * identification, not as a long flag. 60 | * \param desc - A description of what the argument is for or 61 | * does. 62 | * \param req - Whether the argument is required on the command 63 | * line. 64 | * \param typeDesc - A short, human readable description of the 65 | * type that this object expects. This is used in the generation 66 | * of the USAGE statement. The goal is to be helpful to the end user 67 | * of the program. 68 | * \param ignoreable - Whether or not this argument can be ignored 69 | * using the "--" flag. 70 | * \param v - An optional visitor. You probably should not 71 | * use this unless you have a very good reason. 72 | */ 73 | UnlabeledMultiArg( const std::string& name, 74 | const std::string& desc, 75 | bool req, 76 | const std::string& typeDesc, 77 | bool ignoreable = false, 78 | Visitor* v = NULL ); 79 | /** 80 | * Constructor. 81 | * \param name - The name of the Arg. Note that this is used for 82 | * identification, not as a long flag. 83 | * \param desc - A description of what the argument is for or 84 | * does. 85 | * \param req - Whether the argument is required on the command 86 | * line. 87 | * \param typeDesc - A short, human readable description of the 88 | * type that this object expects. This is used in the generation 89 | * of the USAGE statement. The goal is to be helpful to the end user 90 | * of the program. 91 | * \param parser - A CmdLine parser object to add this Arg to 92 | * \param ignoreable - Whether or not this argument can be ignored 93 | * using the "--" flag. 94 | * \param v - An optional visitor. You probably should not 95 | * use this unless you have a very good reason. 96 | */ 97 | UnlabeledMultiArg( const std::string& name, 98 | const std::string& desc, 99 | bool req, 100 | const std::string& typeDesc, 101 | CmdLineInterface& parser, 102 | bool ignoreable = false, 103 | Visitor* v = NULL ); 104 | 105 | /** 106 | * Constructor. 107 | * \param name - The name of the Arg. Note that this is used for 108 | * identification, not as a long flag. 109 | * \param desc - A description of what the argument is for or 110 | * does. 111 | * \param req - Whether the argument is required on the command 112 | * line. 113 | * \param constraint - A pointer to a Constraint object used 114 | * to constrain this Arg. 115 | * \param ignoreable - Whether or not this argument can be ignored 116 | * using the "--" flag. 117 | * \param v - An optional visitor. You probably should not 118 | * use this unless you have a very good reason. 119 | */ 120 | UnlabeledMultiArg( const std::string& name, 121 | const std::string& desc, 122 | bool req, 123 | Constraint* constraint, 124 | bool ignoreable = false, 125 | Visitor* v = NULL ); 126 | 127 | /** 128 | * Constructor. 129 | * \param name - The name of the Arg. Note that this is used for 130 | * identification, not as a long flag. 131 | * \param desc - A description of what the argument is for or 132 | * does. 133 | * \param req - Whether the argument is required on the command 134 | * line. 135 | * \param constraint - A pointer to a Constraint object used 136 | * to constrain this Arg. 137 | * \param parser - A CmdLine parser object to add this Arg to 138 | * \param ignoreable - Whether or not this argument can be ignored 139 | * using the "--" flag. 140 | * \param v - An optional visitor. You probably should not 141 | * use this unless you have a very good reason. 142 | */ 143 | UnlabeledMultiArg( const std::string& name, 144 | const std::string& desc, 145 | bool req, 146 | Constraint* constraint, 147 | CmdLineInterface& parser, 148 | bool ignoreable = false, 149 | Visitor* v = NULL ); 150 | 151 | /** 152 | * Handles the processing of the argument. 153 | * This re-implements the Arg version of this method to set the 154 | * _value of the argument appropriately. It knows the difference 155 | * between labeled and unlabeled. 156 | * \param i - Pointer the the current argument in the list. 157 | * \param args - Mutable list of strings. Passed from main(). 158 | */ 159 | virtual bool processArg(int* i, std::vector& args); 160 | 161 | /** 162 | * Returns the a short id string. Used in the usage. 163 | * \param val - value to be used. 164 | */ 165 | virtual std::string shortID(const std::string& val="val") const; 166 | 167 | /** 168 | * Returns the a long id string. Used in the usage. 169 | * \param val - value to be used. 170 | */ 171 | virtual std::string longID(const std::string& val="val") const; 172 | 173 | /** 174 | * Opertor ==. 175 | * \param a - The Arg to be compared to this. 176 | */ 177 | virtual bool operator==(const Arg& a) const; 178 | 179 | /** 180 | * Pushes this to back of list rather than front. 181 | * \param argList - The list this should be added to. 182 | */ 183 | virtual void addToList( std::list& argList ) const; 184 | }; 185 | 186 | template 187 | UnlabeledMultiArg::UnlabeledMultiArg(const std::string& name, 188 | const std::string& desc, 189 | bool req, 190 | const std::string& typeDesc, 191 | bool ignoreable, 192 | Visitor* v) 193 | : MultiArg("", name, desc, req, typeDesc, v) 194 | { 195 | _ignoreable = ignoreable; 196 | OptionalUnlabeledTracker::check(true, toString()); 197 | } 198 | 199 | template 200 | UnlabeledMultiArg::UnlabeledMultiArg(const std::string& name, 201 | const std::string& desc, 202 | bool req, 203 | const std::string& typeDesc, 204 | CmdLineInterface& parser, 205 | bool ignoreable, 206 | Visitor* v) 207 | : MultiArg("", name, desc, req, typeDesc, v) 208 | { 209 | _ignoreable = ignoreable; 210 | OptionalUnlabeledTracker::check(true, toString()); 211 | parser.add( this ); 212 | } 213 | 214 | 215 | template 216 | UnlabeledMultiArg::UnlabeledMultiArg(const std::string& name, 217 | const std::string& desc, 218 | bool req, 219 | Constraint* constraint, 220 | bool ignoreable, 221 | Visitor* v) 222 | : MultiArg("", name, desc, req, constraint, v) 223 | { 224 | _ignoreable = ignoreable; 225 | OptionalUnlabeledTracker::check(true, toString()); 226 | } 227 | 228 | template 229 | UnlabeledMultiArg::UnlabeledMultiArg(const std::string& name, 230 | const std::string& desc, 231 | bool req, 232 | Constraint* constraint, 233 | CmdLineInterface& parser, 234 | bool ignoreable, 235 | Visitor* v) 236 | : MultiArg("", name, desc, req, constraint, v) 237 | { 238 | _ignoreable = ignoreable; 239 | OptionalUnlabeledTracker::check(true, toString()); 240 | parser.add( this ); 241 | } 242 | 243 | 244 | template 245 | bool UnlabeledMultiArg::processArg(int *i, std::vector& args) 246 | { 247 | 248 | if ( _hasBlanks( args[*i] ) ) 249 | return false; 250 | 251 | // never ignore an unlabeled multi arg 252 | 253 | 254 | // always take the first value, regardless of the start string 255 | _extractValue( args[(*i)] ); 256 | 257 | /* 258 | // continue taking args until we hit the end or a start string 259 | while ( (unsigned int)(*i)+1 < args.size() && 260 | args[(*i)+1].find_first_of( Arg::flagStartString() ) != 0 && 261 | args[(*i)+1].find_first_of( Arg::nameStartString() ) != 0 ) 262 | _extractValue( args[++(*i)] ); 263 | */ 264 | 265 | _alreadySet = true; 266 | 267 | return true; 268 | } 269 | 270 | template 271 | std::string UnlabeledMultiArg::shortID(const std::string& val) const 272 | { 273 | static_cast(val); // Ignore input, don't warn 274 | return std::string("<") + _typeDesc + "> ..."; 275 | } 276 | 277 | template 278 | std::string UnlabeledMultiArg::longID(const std::string& val) const 279 | { 280 | static_cast(val); // Ignore input, don't warn 281 | return std::string("<") + _typeDesc + "> (accepted multiple times)"; 282 | } 283 | 284 | template 285 | bool UnlabeledMultiArg::operator==(const Arg& a) const 286 | { 287 | if ( _name == a.getName() || _description == a.getDescription() ) 288 | return true; 289 | else 290 | return false; 291 | } 292 | 293 | template 294 | void UnlabeledMultiArg::addToList( std::list& argList ) const 295 | { 296 | argList.push_back( const_cast(static_cast(this)) ); 297 | } 298 | 299 | } 300 | 301 | #endif 302 | -------------------------------------------------------------------------------- /src/tclap/UnlabeledValueArg.h: -------------------------------------------------------------------------------- 1 | 2 | /****************************************************************************** 3 | * 4 | * file: UnlabeledValueArg.h 5 | * 6 | * Copyright (c) 2003, Michael E. Smoot . 7 | * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. 8 | * All rights reverved. 9 | * 10 | * See the file COPYING in the top directory of this distribution for 11 | * more information. 12 | * 13 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | * DEALINGS IN THE SOFTWARE. 20 | * 21 | *****************************************************************************/ 22 | 23 | 24 | #ifndef TCLAP_UNLABELED_VALUE_ARGUMENT_H 25 | #define TCLAP_UNLABELED_VALUE_ARGUMENT_H 26 | 27 | #include 28 | #include 29 | 30 | #include 31 | #include 32 | 33 | 34 | namespace TCLAP { 35 | 36 | /** 37 | * The basic unlabeled argument that parses a value. 38 | * This is a template class, which means the type T defines the type 39 | * that a given object will attempt to parse when an UnlabeledValueArg 40 | * is reached in the list of args that the CmdLine iterates over. 41 | */ 42 | template 43 | class UnlabeledValueArg : public ValueArg 44 | { 45 | 46 | // If compiler has two stage name lookup (as gcc >= 3.4 does) 47 | // this is requried to prevent undef. symbols 48 | using ValueArg::_ignoreable; 49 | using ValueArg::_hasBlanks; 50 | using ValueArg::_extractValue; 51 | using ValueArg::_typeDesc; 52 | using ValueArg::_name; 53 | using ValueArg::_description; 54 | using ValueArg::_alreadySet; 55 | using ValueArg::toString; 56 | 57 | public: 58 | 59 | /** 60 | * UnlabeledValueArg constructor. 61 | * \param name - A one word name for the argument. Note that this is used for 62 | * identification, not as a long flag. 63 | * \param desc - A description of what the argument is for or 64 | * does. 65 | * \param req - Whether the argument is required on the command 66 | * line. 67 | * \param value - The default value assigned to this argument if it 68 | * is not present on the command line. 69 | * \param typeDesc - A short, human readable description of the 70 | * type that this object expects. This is used in the generation 71 | * of the USAGE statement. The goal is to be helpful to the end user 72 | * of the program. 73 | * \param ignoreable - Allows you to specify that this argument can be 74 | * ignored if the '--' flag is set. This defaults to false (cannot 75 | * be ignored) and should generally stay that way unless you have 76 | * some special need for certain arguments to be ignored. 77 | * \param v - Optional Vistor. You should leave this blank unless 78 | * you have a very good reason. 79 | */ 80 | UnlabeledValueArg( const std::string& name, 81 | const std::string& desc, 82 | bool req, 83 | T value, 84 | const std::string& typeDesc, 85 | bool ignoreable = false, 86 | Visitor* v = NULL); 87 | 88 | /** 89 | * UnlabeledValueArg constructor. 90 | * \param name - A one word name for the argument. Note that this is used for 91 | * identification, not as a long flag. 92 | * \param desc - A description of what the argument is for or 93 | * does. 94 | * \param req - Whether the argument is required on the command 95 | * line. 96 | * \param value - The default value assigned to this argument if it 97 | * is not present on the command line. 98 | * \param typeDesc - A short, human readable description of the 99 | * type that this object expects. This is used in the generation 100 | * of the USAGE statement. The goal is to be helpful to the end user 101 | * of the program. 102 | * \param parser - A CmdLine parser object to add this Arg to 103 | * \param ignoreable - Allows you to specify that this argument can be 104 | * ignored if the '--' flag is set. This defaults to false (cannot 105 | * be ignored) and should generally stay that way unless you have 106 | * some special need for certain arguments to be ignored. 107 | * \param v - Optional Vistor. You should leave this blank unless 108 | * you have a very good reason. 109 | */ 110 | UnlabeledValueArg( const std::string& name, 111 | const std::string& desc, 112 | bool req, 113 | T value, 114 | const std::string& typeDesc, 115 | CmdLineInterface& parser, 116 | bool ignoreable = false, 117 | Visitor* v = NULL ); 118 | 119 | /** 120 | * UnlabeledValueArg constructor. 121 | * \param name - A one word name for the argument. Note that this is used for 122 | * identification, not as a long flag. 123 | * \param desc - A description of what the argument is for or 124 | * does. 125 | * \param req - Whether the argument is required on the command 126 | * line. 127 | * \param value - The default value assigned to this argument if it 128 | * is not present on the command line. 129 | * \param constraint - A pointer to a Constraint object used 130 | * to constrain this Arg. 131 | * \param ignoreable - Allows you to specify that this argument can be 132 | * ignored if the '--' flag is set. This defaults to false (cannot 133 | * be ignored) and should generally stay that way unless you have 134 | * some special need for certain arguments to be ignored. 135 | * \param v - Optional Vistor. You should leave this blank unless 136 | * you have a very good reason. 137 | */ 138 | UnlabeledValueArg( const std::string& name, 139 | const std::string& desc, 140 | bool req, 141 | T value, 142 | Constraint* constraint, 143 | bool ignoreable = false, 144 | Visitor* v = NULL ); 145 | 146 | 147 | /** 148 | * UnlabeledValueArg constructor. 149 | * \param name - A one word name for the argument. Note that this is used for 150 | * identification, not as a long flag. 151 | * \param desc - A description of what the argument is for or 152 | * does. 153 | * \param req - Whether the argument is required on the command 154 | * line. 155 | * \param value - The default value assigned to this argument if it 156 | * is not present on the command line. 157 | * \param constraint - A pointer to a Constraint object used 158 | * to constrain this Arg. 159 | * \param parser - A CmdLine parser object to add this Arg to 160 | * \param ignoreable - Allows you to specify that this argument can be 161 | * ignored if the '--' flag is set. This defaults to false (cannot 162 | * be ignored) and should generally stay that way unless you have 163 | * some special need for certain arguments to be ignored. 164 | * \param v - Optional Vistor. You should leave this blank unless 165 | * you have a very good reason. 166 | */ 167 | UnlabeledValueArg( const std::string& name, 168 | const std::string& desc, 169 | bool req, 170 | T value, 171 | Constraint* constraint, 172 | CmdLineInterface& parser, 173 | bool ignoreable = false, 174 | Visitor* v = NULL); 175 | 176 | /** 177 | * Handles the processing of the argument. 178 | * This re-implements the Arg version of this method to set the 179 | * _value of the argument appropriately. Handling specific to 180 | * unlabled arguments. 181 | * \param i - Pointer the the current argument in the list. 182 | * \param args - Mutable list of strings. 183 | */ 184 | virtual bool processArg(int* i, std::vector& args); 185 | 186 | /** 187 | * Overrides shortID for specific behavior. 188 | */ 189 | virtual std::string shortID(const std::string& val="val") const; 190 | 191 | /** 192 | * Overrides longID for specific behavior. 193 | */ 194 | virtual std::string longID(const std::string& val="val") const; 195 | 196 | /** 197 | * Overrides operator== for specific behavior. 198 | */ 199 | virtual bool operator==(const Arg& a ) const; 200 | 201 | /** 202 | * Instead of pushing to the front of list, push to the back. 203 | * \param argList - The list to add this to. 204 | */ 205 | virtual void addToList( std::list& argList ) const; 206 | 207 | }; 208 | 209 | /** 210 | * Constructor implemenation. 211 | */ 212 | template 213 | UnlabeledValueArg::UnlabeledValueArg(const std::string& name, 214 | const std::string& desc, 215 | bool req, 216 | T val, 217 | const std::string& typeDesc, 218 | bool ignoreable, 219 | Visitor* v) 220 | : ValueArg("", name, desc, req, val, typeDesc, v) 221 | { 222 | _ignoreable = ignoreable; 223 | 224 | OptionalUnlabeledTracker::check(req, toString()); 225 | 226 | } 227 | 228 | template 229 | UnlabeledValueArg::UnlabeledValueArg(const std::string& name, 230 | const std::string& desc, 231 | bool req, 232 | T val, 233 | const std::string& typeDesc, 234 | CmdLineInterface& parser, 235 | bool ignoreable, 236 | Visitor* v) 237 | : ValueArg("", name, desc, req, val, typeDesc, v) 238 | { 239 | _ignoreable = ignoreable; 240 | OptionalUnlabeledTracker::check(req, toString()); 241 | parser.add( this ); 242 | } 243 | 244 | /** 245 | * Constructor implemenation. 246 | */ 247 | template 248 | UnlabeledValueArg::UnlabeledValueArg(const std::string& name, 249 | const std::string& desc, 250 | bool req, 251 | T val, 252 | Constraint* constraint, 253 | bool ignoreable, 254 | Visitor* v) 255 | : ValueArg("", name, desc, req, val, constraint, v) 256 | { 257 | _ignoreable = ignoreable; 258 | OptionalUnlabeledTracker::check(req, toString()); 259 | } 260 | 261 | template 262 | UnlabeledValueArg::UnlabeledValueArg(const std::string& name, 263 | const std::string& desc, 264 | bool req, 265 | T val, 266 | Constraint* constraint, 267 | CmdLineInterface& parser, 268 | bool ignoreable, 269 | Visitor* v) 270 | : ValueArg("", name, desc, req, val, constraint, v) 271 | { 272 | _ignoreable = ignoreable; 273 | OptionalUnlabeledTracker::check(req, toString()); 274 | parser.add( this ); 275 | } 276 | 277 | /** 278 | * Implementation of processArg(). 279 | */ 280 | template 281 | bool UnlabeledValueArg::processArg(int *i, std::vector& args) 282 | { 283 | 284 | if ( _alreadySet ) 285 | return false; 286 | 287 | if ( _hasBlanks( args[*i] ) ) 288 | return false; 289 | 290 | // never ignore an unlabeled arg 291 | 292 | _extractValue( args[*i] ); 293 | _alreadySet = true; 294 | return true; 295 | } 296 | 297 | /** 298 | * Overriding shortID for specific output. 299 | */ 300 | template 301 | std::string UnlabeledValueArg::shortID(const std::string& val) const 302 | { 303 | static_cast(val); // Ignore input, don't warn 304 | return std::string("<") + _typeDesc + ">"; 305 | } 306 | 307 | /** 308 | * Overriding longID for specific output. 309 | */ 310 | template 311 | std::string UnlabeledValueArg::longID(const std::string& val) const 312 | { 313 | static_cast(val); // Ignore input, don't warn 314 | 315 | // Ideally we would like to be able to use RTTI to return the name 316 | // of the type required for this argument. However, g++ at least, 317 | // doesn't appear to return terribly useful "names" of the types. 318 | return std::string("<") + _typeDesc + ">"; 319 | } 320 | 321 | /** 322 | * Overriding operator== for specific behavior. 323 | */ 324 | template 325 | bool UnlabeledValueArg::operator==(const Arg& a ) const 326 | { 327 | if ( _name == a.getName() || _description == a.getDescription() ) 328 | return true; 329 | else 330 | return false; 331 | } 332 | 333 | template 334 | void UnlabeledValueArg::addToList( std::list& argList ) const 335 | { 336 | argList.push_back( const_cast(static_cast(this)) ); 337 | } 338 | 339 | } 340 | #endif 341 | -------------------------------------------------------------------------------- /src/tclap/ValuesConstraint.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | /****************************************************************************** 4 | * 5 | * file: ValuesConstraint.h 6 | * 7 | * Copyright (c) 2005, Michael E. Smoot 8 | * All rights reverved. 9 | * 10 | * See the file COPYING in the top directory of this distribution for 11 | * more information. 12 | * 13 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | * DEALINGS IN THE SOFTWARE. 20 | * 21 | *****************************************************************************/ 22 | 23 | #ifndef TCLAP_VALUESCONSTRAINT_H 24 | #define TCLAP_VALUESCONSTRAINT_H 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #ifdef HAVE_CONFIG_H 31 | #include 32 | #else 33 | #define HAVE_SSTREAM 34 | #endif 35 | 36 | #if defined(HAVE_SSTREAM) 37 | #include 38 | #elif defined(HAVE_STRSTREAM) 39 | #include 40 | #else 41 | #error "Need a stringstream (sstream or strstream) to compile!" 42 | #endif 43 | 44 | namespace TCLAP { 45 | 46 | /** 47 | * A Constraint that constrains the Arg to only those values specified 48 | * in the constraint. 49 | */ 50 | template 51 | class ValuesConstraint : public Constraint 52 | { 53 | 54 | public: 55 | 56 | /** 57 | * Constructor. 58 | * \param allowed - vector of allowed values. 59 | */ 60 | ValuesConstraint(std::vector& allowed); 61 | 62 | /** 63 | * Virtual destructor. 64 | */ 65 | virtual ~ValuesConstraint() {} 66 | 67 | /** 68 | * Returns a description of the Constraint. 69 | */ 70 | virtual std::string description() const; 71 | 72 | /** 73 | * Returns the short ID for the Constraint. 74 | */ 75 | virtual std::string shortID() const; 76 | 77 | /** 78 | * The method used to verify that the value parsed from the command 79 | * line meets the constraint. 80 | * \param value - The value that will be checked. 81 | */ 82 | virtual bool check(const T& value) const; 83 | 84 | protected: 85 | 86 | /** 87 | * The list of valid values. 88 | */ 89 | std::vector _allowed; 90 | 91 | /** 92 | * The string used to describe the allowed values of this constraint. 93 | */ 94 | std::string _typeDesc; 95 | 96 | }; 97 | 98 | template 99 | ValuesConstraint::ValuesConstraint(std::vector& allowed) 100 | : _allowed(allowed), 101 | _typeDesc("") 102 | { 103 | for ( unsigned int i = 0; i < _allowed.size(); i++ ) 104 | { 105 | 106 | #if defined(HAVE_SSTREAM) 107 | std::ostringstream os; 108 | #elif defined(HAVE_STRSTREAM) 109 | std::ostrstream os; 110 | #else 111 | #error "Need a stringstream (sstream or strstream) to compile!" 112 | #endif 113 | 114 | os << _allowed[i]; 115 | 116 | std::string temp( os.str() ); 117 | 118 | if ( i > 0 ) 119 | _typeDesc += "|"; 120 | _typeDesc += temp; 121 | } 122 | } 123 | 124 | template 125 | bool ValuesConstraint::check( const T& val ) const 126 | { 127 | if ( std::find(_allowed.begin(),_allowed.end(),val) == _allowed.end() ) 128 | return false; 129 | else 130 | return true; 131 | } 132 | 133 | template 134 | std::string ValuesConstraint::shortID() const 135 | { 136 | return _typeDesc; 137 | } 138 | 139 | template 140 | std::string ValuesConstraint::description() const 141 | { 142 | return _typeDesc; 143 | } 144 | 145 | 146 | } //namespace TCLAP 147 | #endif 148 | 149 | -------------------------------------------------------------------------------- /src/tclap/VersionVisitor.h: -------------------------------------------------------------------------------- 1 | // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- 2 | 3 | /****************************************************************************** 4 | * 5 | * file: VersionVisitor.h 6 | * 7 | * Copyright (c) 2003, Michael E. Smoot . 8 | * All rights reverved. 9 | * 10 | * See the file COPYING in the top directory of this distribution for 11 | * more information. 12 | * 13 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | * DEALINGS IN THE SOFTWARE. 20 | * 21 | *****************************************************************************/ 22 | 23 | 24 | #ifndef TCLAP_VERSION_VISITOR_H 25 | #define TCLAP_VERSION_VISITOR_H 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | namespace TCLAP { 32 | 33 | /** 34 | * A Vistor that will call the version method of the given CmdLineOutput 35 | * for the specified CmdLine object and then exit. 36 | */ 37 | class VersionVisitor: public Visitor 38 | { 39 | private: 40 | /** 41 | * Prevent accidental copying 42 | */ 43 | VersionVisitor(const VersionVisitor& rhs); 44 | VersionVisitor& operator=(const VersionVisitor& rhs); 45 | 46 | protected: 47 | 48 | /** 49 | * The CmdLine of interest. 50 | */ 51 | CmdLineInterface* _cmd; 52 | 53 | /** 54 | * The output object. 55 | */ 56 | CmdLineOutput** _out; 57 | 58 | public: 59 | 60 | /** 61 | * Constructor. 62 | * \param cmd - The CmdLine the output is generated for. 63 | * \param out - The type of output. 64 | */ 65 | VersionVisitor( CmdLineInterface* cmd, CmdLineOutput** out ) 66 | : Visitor(), _cmd( cmd ), _out( out ) { } 67 | 68 | /** 69 | * Calls the version method of the output object using the 70 | * specified CmdLine. 71 | */ 72 | void visit() { 73 | (*_out)->version(*_cmd); 74 | throw ExitException(0); 75 | } 76 | 77 | }; 78 | 79 | } 80 | 81 | #endif 82 | -------------------------------------------------------------------------------- /src/tclap/Visitor.h: -------------------------------------------------------------------------------- 1 | 2 | /****************************************************************************** 3 | * 4 | * file: Visitor.h 5 | * 6 | * Copyright (c) 2003, Michael E. Smoot . 7 | * All rights reverved. 8 | * 9 | * See the file COPYING in the top directory of this distribution for 10 | * more information. 11 | * 12 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 13 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 15 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 17 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 18 | * DEALINGS IN THE SOFTWARE. 19 | * 20 | *****************************************************************************/ 21 | 22 | 23 | #ifndef TCLAP_VISITOR_H 24 | #define TCLAP_VISITOR_H 25 | 26 | namespace TCLAP { 27 | 28 | /** 29 | * A base class that defines the interface for visitors. 30 | */ 31 | class Visitor 32 | { 33 | public: 34 | 35 | /** 36 | * Constructor. Does nothing. 37 | */ 38 | Visitor() { } 39 | 40 | /** 41 | * Destructor. Does nothing. 42 | */ 43 | virtual ~Visitor() { } 44 | 45 | /** 46 | * Does nothing. Should be overridden by child. 47 | */ 48 | virtual void visit() { } 49 | }; 50 | 51 | } 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /src/tclap/XorHandler.h: -------------------------------------------------------------------------------- 1 | 2 | /****************************************************************************** 3 | * 4 | * file: XorHandler.h 5 | * 6 | * Copyright (c) 2003, Michael E. Smoot . 7 | * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. 8 | * All rights reverved. 9 | * 10 | * See the file COPYING in the top directory of this distribution for 11 | * more information. 12 | * 13 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | * DEALINGS IN THE SOFTWARE. 20 | * 21 | *****************************************************************************/ 22 | 23 | #ifndef TCLAP_XORHANDLER_H 24 | #define TCLAP_XORHANDLER_H 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | namespace TCLAP { 33 | 34 | /** 35 | * This class handles lists of Arg's that are to be XOR'd on the command 36 | * line. This is used by CmdLine and you shouldn't ever use it. 37 | */ 38 | class XorHandler 39 | { 40 | protected: 41 | 42 | /** 43 | * The list of of lists of Arg's to be or'd together. 44 | */ 45 | std::vector< std::vector > _orList; 46 | 47 | public: 48 | 49 | /** 50 | * Constructor. Does nothing. 51 | */ 52 | XorHandler( ) : _orList(std::vector< std::vector >()) {} 53 | 54 | /** 55 | * Add a list of Arg*'s that will be orred together. 56 | * \param ors - list of Arg* that will be xor'd. 57 | */ 58 | void add( std::vector& ors ); 59 | 60 | /** 61 | * Checks whether the specified Arg is in one of the xor lists and 62 | * if it does match one, returns the size of the xor list that the 63 | * Arg matched. If the Arg matches, then it also sets the rest of 64 | * the Arg's in the list. You shouldn't use this. 65 | * \param a - The Arg to be checked. 66 | */ 67 | int check( const Arg* a ); 68 | 69 | /** 70 | * Returns the XOR specific short usage. 71 | */ 72 | std::string shortUsage(); 73 | 74 | /** 75 | * Prints the XOR specific long usage. 76 | * \param os - Stream to print to. 77 | */ 78 | void printLongUsage(std::ostream& os); 79 | 80 | /** 81 | * Simply checks whether the Arg is contained in one of the arg 82 | * lists. 83 | * \param a - The Arg to be checked. 84 | */ 85 | bool contains( const Arg* a ); 86 | 87 | std::vector< std::vector >& getXorList(); 88 | 89 | }; 90 | 91 | 92 | ////////////////////////////////////////////////////////////////////// 93 | //BEGIN XOR.cpp 94 | ////////////////////////////////////////////////////////////////////// 95 | inline void XorHandler::add( std::vector& ors ) 96 | { 97 | _orList.push_back( ors ); 98 | } 99 | 100 | inline int XorHandler::check( const Arg* a ) 101 | { 102 | // iterate over each XOR list 103 | for ( int i = 0; static_cast(i) < _orList.size(); i++ ) 104 | { 105 | // if the XOR list contains the arg.. 106 | ArgVectorIterator ait = std::find( _orList[i].begin(), 107 | _orList[i].end(), a ); 108 | if ( ait != _orList[i].end() ) 109 | { 110 | // first check to see if a mutually exclusive switch 111 | // has not already been set 112 | for ( ArgVectorIterator it = _orList[i].begin(); 113 | it != _orList[i].end(); 114 | it++ ) 115 | if ( a != (*it) && (*it)->isSet() ) 116 | throw(CmdLineParseException( 117 | "Mutually exclusive argument already set!", 118 | (*it)->toString())); 119 | 120 | // go through and set each arg that is not a 121 | for ( ArgVectorIterator it = _orList[i].begin(); 122 | it != _orList[i].end(); 123 | it++ ) 124 | if ( a != (*it) ) 125 | (*it)->xorSet(); 126 | 127 | // return the number of required args that have now been set 128 | if ( (*ait)->allowMore() ) 129 | return 0; 130 | else 131 | return static_cast(_orList[i].size()); 132 | } 133 | } 134 | 135 | if ( a->isRequired() ) 136 | return 1; 137 | else 138 | return 0; 139 | } 140 | 141 | inline bool XorHandler::contains( const Arg* a ) 142 | { 143 | for ( int i = 0; static_cast(i) < _orList.size(); i++ ) 144 | for ( ArgVectorIterator it = _orList[i].begin(); 145 | it != _orList[i].end(); 146 | it++ ) 147 | if ( a == (*it) ) 148 | return true; 149 | 150 | return false; 151 | } 152 | 153 | inline std::vector< std::vector >& XorHandler::getXorList() 154 | { 155 | return _orList; 156 | } 157 | 158 | 159 | 160 | ////////////////////////////////////////////////////////////////////// 161 | //END XOR.cpp 162 | ////////////////////////////////////////////////////////////////////// 163 | 164 | } //namespace TCLAP 165 | 166 | #endif 167 | -------------------------------------------------------------------------------- /src/tclap/ZshCompletionOutput.h: -------------------------------------------------------------------------------- 1 | // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- 2 | 3 | /****************************************************************************** 4 | * 5 | * file: ZshCompletionOutput.h 6 | * 7 | * Copyright (c) 2006, Oliver Kiddle 8 | * All rights reverved. 9 | * 10 | * See the file COPYING in the top directory of this distribution for 11 | * more information. 12 | * 13 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | * DEALINGS IN THE SOFTWARE. 20 | * 21 | *****************************************************************************/ 22 | 23 | #ifndef TCLAP_ZSHCOMPLETIONOUTPUT_H 24 | #define TCLAP_ZSHCOMPLETIONOUTPUT_H 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | namespace TCLAP { 38 | 39 | /** 40 | * A class that generates a Zsh completion function as output from the usage() 41 | * method for the given CmdLine and its Args. 42 | */ 43 | class ZshCompletionOutput : public CmdLineOutput 44 | { 45 | 46 | public: 47 | 48 | ZshCompletionOutput(); 49 | 50 | /** 51 | * Prints the usage to stdout. Can be overridden to 52 | * produce alternative behavior. 53 | * \param c - The CmdLine object the output is generated for. 54 | */ 55 | virtual void usage(CmdLineInterface& c); 56 | 57 | /** 58 | * Prints the version to stdout. Can be overridden 59 | * to produce alternative behavior. 60 | * \param c - The CmdLine object the output is generated for. 61 | */ 62 | virtual void version(CmdLineInterface& c); 63 | 64 | /** 65 | * Prints (to stderr) an error message, short usage 66 | * Can be overridden to produce alternative behavior. 67 | * \param c - The CmdLine object the output is generated for. 68 | * \param e - The ArgException that caused the failure. 69 | */ 70 | virtual void failure(CmdLineInterface& c, 71 | ArgException& e ); 72 | 73 | protected: 74 | 75 | void basename( std::string& s ); 76 | void quoteSpecialChars( std::string& s ); 77 | 78 | std::string getMutexList( CmdLineInterface& _cmd, Arg* a ); 79 | void printOption( Arg* it, std::string mutex ); 80 | void printArg( Arg* it ); 81 | 82 | std::map common; 83 | char theDelimiter; 84 | }; 85 | 86 | ZshCompletionOutput::ZshCompletionOutput() 87 | : common(std::map()), 88 | theDelimiter('=') 89 | { 90 | common["host"] = "_hosts"; 91 | common["hostname"] = "_hosts"; 92 | common["file"] = "_files"; 93 | common["filename"] = "_files"; 94 | common["user"] = "_users"; 95 | common["username"] = "_users"; 96 | common["directory"] = "_directories"; 97 | common["path"] = "_directories"; 98 | common["url"] = "_urls"; 99 | } 100 | 101 | inline void ZshCompletionOutput::version(CmdLineInterface& _cmd) 102 | { 103 | std::cout << _cmd.getVersion() << std::endl; 104 | } 105 | 106 | inline void ZshCompletionOutput::usage(CmdLineInterface& _cmd ) 107 | { 108 | std::list argList = _cmd.getArgList(); 109 | std::string progName = _cmd.getProgramName(); 110 | std::string xversion = _cmd.getVersion(); 111 | theDelimiter = _cmd.getDelimiter(); 112 | basename(progName); 113 | 114 | std::cout << "#compdef " << progName << std::endl << std::endl << 115 | "# " << progName << " version " << _cmd.getVersion() << std::endl << std::endl << 116 | "_arguments -s -S"; 117 | 118 | for (ArgListIterator it = argList.begin(); it != argList.end(); it++) 119 | { 120 | if ( (*it)->shortID().at(0) == '<' ) 121 | printArg((*it)); 122 | else if ( (*it)->getFlag() != "-" ) 123 | printOption((*it), getMutexList(_cmd, *it)); 124 | } 125 | 126 | std::cout << std::endl; 127 | } 128 | 129 | inline void ZshCompletionOutput::failure( CmdLineInterface& _cmd, 130 | ArgException& e ) 131 | { 132 | static_cast(_cmd); // unused 133 | std::cout << e.what() << std::endl; 134 | } 135 | 136 | inline void ZshCompletionOutput::quoteSpecialChars( std::string& s ) 137 | { 138 | size_t idx = s.find_last_of(':'); 139 | while ( idx != std::string::npos ) 140 | { 141 | s.insert(idx, 1, '\\'); 142 | idx = s.find_last_of(':', idx); 143 | } 144 | idx = s.find_last_of('\''); 145 | while ( idx != std::string::npos ) 146 | { 147 | s.insert(idx, "'\\'"); 148 | if (idx == 0) 149 | idx = std::string::npos; 150 | else 151 | idx = s.find_last_of('\'', --idx); 152 | } 153 | } 154 | 155 | inline void ZshCompletionOutput::basename( std::string& s ) 156 | { 157 | size_t p = s.find_last_of('/'); 158 | if ( p != std::string::npos ) 159 | { 160 | s.erase(0, p + 1); 161 | } 162 | } 163 | 164 | inline void ZshCompletionOutput::printArg(Arg* a) 165 | { 166 | static int count = 1; 167 | 168 | std::cout << " \\" << std::endl << " '"; 169 | if ( a->acceptsMultipleValues() ) 170 | std::cout << '*'; 171 | else 172 | std::cout << count++; 173 | std::cout << ':'; 174 | if ( !a->isRequired() ) 175 | std::cout << ':'; 176 | 177 | std::cout << a->getName() << ':'; 178 | std::map::iterator compArg = common.find(a->getName()); 179 | if ( compArg != common.end() ) 180 | { 181 | std::cout << compArg->second; 182 | } 183 | else 184 | { 185 | std::cout << "_guard \"^-*\" " << a->getName(); 186 | } 187 | std::cout << '\''; 188 | } 189 | 190 | inline void ZshCompletionOutput::printOption(Arg* a, std::string mutex) 191 | { 192 | std::string flag = a->flagStartChar() + a->getFlag(); 193 | std::string name = a->nameStartString() + a->getName(); 194 | std::string desc = a->getDescription(); 195 | 196 | // remove full stop and capitalisation from description as 197 | // this is the convention for zsh function 198 | if (!desc.compare(0, 12, "(required) ")) 199 | { 200 | desc.erase(0, 12); 201 | } 202 | if (!desc.compare(0, 15, "(OR required) ")) 203 | { 204 | desc.erase(0, 15); 205 | } 206 | size_t len = desc.length(); 207 | if (len && desc.at(--len) == '.') 208 | { 209 | desc.erase(len); 210 | } 211 | if (len) 212 | { 213 | desc.replace(0, 1, 1, tolower(desc.at(0))); 214 | } 215 | 216 | std::cout << " \\" << std::endl << " '" << mutex; 217 | 218 | if ( a->getFlag().empty() ) 219 | { 220 | std::cout << name; 221 | } 222 | else 223 | { 224 | std::cout << "'{" << flag << ',' << name << "}'"; 225 | } 226 | if ( theDelimiter == '=' && a->isValueRequired() ) 227 | std::cout << "=-"; 228 | quoteSpecialChars(desc); 229 | std::cout << '[' << desc << ']'; 230 | 231 | if ( a->isValueRequired() ) 232 | { 233 | std::string arg = a->shortID(); 234 | arg.erase(0, arg.find_last_of(theDelimiter) + 1); 235 | if ( arg.at(arg.length()-1) == ']' ) 236 | arg.erase(arg.length()-1); 237 | if ( arg.at(arg.length()-1) == ']' ) 238 | { 239 | arg.erase(arg.length()-1); 240 | } 241 | if ( arg.at(0) == '<' ) 242 | { 243 | arg.erase(arg.length()-1); 244 | arg.erase(0, 1); 245 | } 246 | size_t p = arg.find('|'); 247 | if ( p != std::string::npos ) 248 | { 249 | do 250 | { 251 | arg.replace(p, 1, 1, ' '); 252 | } 253 | while ( (p = arg.find_first_of('|', p)) != std::string::npos ); 254 | quoteSpecialChars(arg); 255 | std::cout << ": :(" << arg << ')'; 256 | } 257 | else 258 | { 259 | std::cout << ':' << arg; 260 | std::map::iterator compArg = common.find(arg); 261 | if ( compArg != common.end() ) 262 | { 263 | std::cout << ':' << compArg->second; 264 | } 265 | } 266 | } 267 | 268 | std::cout << '\''; 269 | } 270 | 271 | inline std::string ZshCompletionOutput::getMutexList( CmdLineInterface& _cmd, Arg* a) 272 | { 273 | XorHandler xorHandler = _cmd.getXorHandler(); 274 | std::vector< std::vector > xorList = xorHandler.getXorList(); 275 | 276 | if (a->getName() == "help" || a->getName() == "version") 277 | { 278 | return "(-)"; 279 | } 280 | 281 | std::ostringstream list; 282 | if ( a->acceptsMultipleValues() ) 283 | { 284 | list << '*'; 285 | } 286 | 287 | for ( int i = 0; static_cast(i) < xorList.size(); i++ ) 288 | { 289 | for ( ArgVectorIterator it = xorList[i].begin(); 290 | it != xorList[i].end(); 291 | it++) 292 | if ( a == (*it) ) 293 | { 294 | list << '('; 295 | for ( ArgVectorIterator iu = xorList[i].begin(); 296 | iu != xorList[i].end(); 297 | iu++ ) 298 | { 299 | bool notCur = (*iu) != a; 300 | bool hasFlag = !(*iu)->getFlag().empty(); 301 | if ( iu != xorList[i].begin() && (notCur || hasFlag) ) 302 | list << ' '; 303 | if (hasFlag) 304 | list << (*iu)->flagStartChar() << (*iu)->getFlag() << ' '; 305 | if ( notCur || hasFlag ) 306 | list << (*iu)->nameStartString() << (*iu)->getName(); 307 | } 308 | list << ')'; 309 | return list.str(); 310 | } 311 | } 312 | 313 | // wasn't found in xor list 314 | if (!a->getFlag().empty()) { 315 | list << "(" << a->flagStartChar() << a->getFlag() << ' ' << 316 | a->nameStartString() << a->getName() << ')'; 317 | } 318 | 319 | return list.str(); 320 | } 321 | 322 | } //namespace TCLAP 323 | #endif 324 | -------------------------------------------------------------------------------- /src/timer.hh: -------------------------------------------------------------------------------- 1 | /* 2 | * $File: timer.hh 3 | * $Date: Tue Dec 10 16:44:35 2013 +0800 4 | * $Author: Xinyu Zhou 5 | */ 6 | 7 | #pragma once 8 | 9 | #include "sys/time.h" 10 | #include 11 | 12 | class Timer { 13 | public: 14 | long long get_time() { 15 | timeval tv; 16 | gettimeofday(&tv, 0); 17 | return tv.tv_sec * 1000ll + tv.tv_usec / 1000; 18 | } 19 | 20 | long long m_start; 21 | long long start() { 22 | return m_start = get_time(); 23 | } 24 | 25 | long long stop() { 26 | return get_time() - m_start; 27 | } 28 | }; 29 | 30 | 31 | class GuardedTimer { 32 | public: 33 | std::string prompt; 34 | Timer timer; 35 | bool enable; 36 | GuardedTimer(const std::string &prompt, bool enable = true) : 37 | prompt(prompt), enable(enable) { 38 | timer.start(); 39 | } 40 | ~GuardedTimer() { 41 | if (enable) { 42 | printf("%s: %.3lfs\n", prompt.c_str(), timer.stop() / 1000.0); 43 | fflush(stdout); 44 | } 45 | } 46 | 47 | }; 48 | 49 | /** 50 | * vim: syntax=cpp11 foldmethod=marker 51 | */ 52 | 53 | -------------------------------------------------------------------------------- /src/type.hh: -------------------------------------------------------------------------------- 1 | /* 2 | * $File: type.hh 3 | * $Date: Mon Aug 19 16:37:57 2013 +0000 4 | * $Author: Xinyu Zhou 5 | */ 6 | 7 | #pragma once 8 | 9 | typedef double real_t; 10 | typedef int label_t; 11 | typedef long long ll; 12 | typedef unsigned long long ull; 13 | 14 | /** 15 | * vim: syntax=cpp11 foldmethod=marker 16 | */ 17 | 18 | --------------------------------------------------------------------------------