General Support Types and Functions¶
The Utils package contains a set of C++ support functions and classes. Due to the library dependency order, these classes have no internal dependencies. In particular, the utils package does not contain classes or functions that are related to image processing.
Table of Contents¶
Basic Types¶
ICL’s basic data types are defined in ICLUtils/BasicTypes.h. Unlike all other classes, types and functions, the basic types are defined directly in the icl -namespace. The type syntax is copied from the Intel IPP library: All types have an icl-prefix, an integer-value that describes the number of bits used, and a suffix
u for unsigned integers
s for signed integers
f for floating point numbers
c for complex floating point numbers
The most common types are
icl8u for 8 bit unsigned integers (commonly known as unsigned char)
icl16s for 16 bit signed integers (commonly known as short)
icl32s for 32 bit signed integers (usually int)
icl32f for floats
icl64f for doubles
ICL’s image classes (provided by the ICLCore module) are implemented for these common types Note: Please ensure not to mix up the basic data types with the alternatives for the enumeration core::depth which are
The core::depth value is used for run-time type-inference
Support Types¶
Defines a rectangle by given x, y, width and height. Serialization: “(x,y)WxH”
Note
in case of Intel IPP Support, Rect is derived from it’s IPP-counter-part IppiRect
Range and SteppingRange
A template class for ranges, described by minVal and maxVal. SteppingRange extends the Range template by a stepping member variable of the same type
Uncopyable and Lockable
Two straight-forward to use interfaces. Uncopyable just declares copy constructor and assignment operators in a private scope to avoid copying instances of classes that are derived from it. The Lockable interfaces contains a Mutex and provides a lock and unlock method. Mutex and Lockable instances can be scope-locked using an instance of Mutex::Locker.
Utility class for describing visualizations in a state-machine manner. With this tool, classes can e.g. provide a visualization of something, that can then be rendered generically
Program Argument Evaluation¶
The program argument evaluation toolkit is used in most ICL-based applications. It provides
a simple and intuitive string-based description of allowed program arguments
an easy to use way to describe program arguments
a efficient parser for program arguments, that provides human-readable error messages
an automatically supported set of common default program arguments, such as -version or -help
a concise method pa that can be use to query whether a specific program argument has been given and what it’s sub arguments where
The usage of the program argument evaluation toolkit is explain in an extra chapter of the tutorial (see Evaluating Program Arguments)
The Configurable interface¶
The Configurable-interface can be used to define a classes parameters/properties that shall be changed at runtime. The Configurable-subclasses can define properties that can be accessed by string identifiers. Each property has a type, a type-dependend description of possible values, a current value and a so called volatileness. Further details and examples are given in the tutorial The Configurable Interface.
Smart-Pointer and Smart-Array¶
ICL provides a very simple, yet powerful reference counting smart-pointer implementation SmartPtr that basically behaves like the boost::shared_ptr. For array-pointers (where the data was created using new []), the SmartArray can be used.
Time and Timer Support¶
Here, the main utility class is Time, which was originally copied from libiceutils. The Time class provides microsecond resolutions internally represented as an icl64s. Time::now() returns the current system time. Time instances can easily be added, subtracted and compared. In contrast to e.g. the boost-libraries, the time class represents absolute times and time intervalls at once.
This class can be used to estimate the average frames-per-second count of a running application:
void runction(){ static icl::utils::FPSEstimator fps(10); // averages over 10 iterations std::cout << fps.getFPSString() << std::endl; }
The limiter inherits the FPSEstimator class. It’s FPSLimiter::wait() method will wait long enough to ensure, the desired FPS-limit is not overshot.
The StackTimer is a very special tool, that can be used for coarse profiling. The header ICLUtils/StackTimer.h provides the magic-macros BENCHMARK_THIS_FUNCTION and BENCHMARK_THIS_SCOPE(STRING):
void foo(){ BENCHMARK_THIS_FUNCTION; // some other stuff }Now, you’ll get an evaluation of the run-time of your function when your program exits normally.
Exceptions Types¶
ICL’s basic exception type is ICLException that inherits std::runtime_error. In addition, there are several other exception types either implemented in the ICLUtils/Exception.h header or within one of the other ICL modules. ICL’s exception hierarchy is rather flat; most of the time either ICLException or a direct child-class instance is thrown.
Multi-Threading Tools¶
Here, the two fundamental classes are Thread and Mutex which are basically simple wrappers of the corresponding PThread-types. Most of the time, threading must not be implemented explicitly. Instead the ICLApplication can be used for multi-threaded (interactive) applications.
XML-based Configuration Files¶
We included the Pugi-XML parsing framework into the ICL source tree. Even though, this can be uses for XML file parsing and creation, ICL provides a much simpler tool for XML-based configuration files, the ConfigFile class. This is documented in an extra chapter of the tutorial (see XML-based Configuration Files)
String Manipulation¶
Since C++’s support for string manipulation is a bit weak, ICL supports a set of support functions for intuitive and easy-to use string manipulation. Most important are the two function templates:
template<class T> std::string str(const T &instance); template<class T> T parse(const std::string &text);where str converts a type instance into a string, and parse converts a string into a type instance. Internally, these functions make use of the in- and output stream-operators (<< and >>). Therefore, str is automatically supported for each type that supports the std::ostream-operator and parse for each type that supports the std::istream-operator. For most of the common ICL-types, this is true.
Any is a utility class that defines a string-serialized object. Any is derived from the std::string, and extends it’s functionality by easy to use serialization and de-serialization functions. An Any instance can be created from every type that is supported by the str-template (see above). And it can be converted to any type that is supported by the parse-template
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 #include <ICLUtils/Any.h> #include <ICLMath/FixedMatrix.h> #include <ICLUtils/Size.h> #include <ICLCore/Types.h> #include <ICLCore/CoreFunctions.h> using namespace icl; int main(){ /// create Any instance from data types (implicitly) utils::Any i = 5; utils::Any d = M_PI; utils::Any s = utils::Size::VGA; utils::Any f = core::formatRGB; utils::Any m = math::FixedMatrix<float,3,2>(1,2,3, 4,5,6); // show std::cout << " int:" << i << " double:" << d << " size:" << s << " format:" << f << std::endl << " matrix:" << m << std::endl; /// create data-type from Any instances (implicitly) int ii = i; double dd = d; utils::Size ss = s; core::format ff = f; math::FixedMatrix<float,3,2> mm = m; // show std::cout << " int:" << ii << " double:" << dd << " size:" << ss << " format:" << ff << std::endl << " matrix:" << mm << std::endl; // explicit cross-type parsing int x = d.as<int>(); utils::Point y = s.as<utils::Point>(); std::cout << "double as int:" << x << std::endl; std::cout << "size as point:" << y << std::endl; }
The two support functions are used for tokenization and concatination of string. tok can tokenize strings an std::vector<string> tokens. It can either use a set of single allowed char-delimiters, or a delimiting std::string. Furthermore, an escape-character can be defined for also being able to use the delimiting characters.
The opposite of tok is cat, which concatenate the elements of an std::vector<std::string>. Optionally a delimiter can be inserted between the elements here.
Is a regular expression matching function. It also supports accessing sub-matches.
The Generic Function Class¶
The Function class and it’s heavily overloaded creator function function, is a simplification of the well known boost::function type. The Function defines a generic interface for
global functions
static functions (in classes, that are basically global)
member functions
functors
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | #include <ICLUtils/Function.h>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace icl::utils;
void global_foo(){
std::cout << "void global_foo()" << std::endl;
}
int global_foo2(){
std::cout << "int global_foo() returning 5" << std::endl;
return 5;
}
int global_add(int a, int b) { return a+b; }
struct Foo{
int add(int a, int b){
std::cout << "Foo.add(" << a << "," << b << ") = " << a+b << std::endl;
return a+b;
}
int operator()(int a, int b){
std::cout << "Foo(" << a << "," << b << ") = " << a+b << std::endl;
return a+b;
}
static void show_int(int i){
std::cout << i << std::endl;
}
};
int main(){
/// simple parameterless global function
Function<void> gfoo(global_foo);
gfoo();
/// global function that returns an int
Function<int> gfoo2(global_foo2);
std::cout << gfoo2() << std::endl;
/// Implicit cast from function with return value to function without return value
Function<int> gfoo3 = function(global_foo2);
gfoo3();
/// Global function with parameters
/// identical to function(global_add)(4,5)
Function<int,int,int> gadd(global_add);
std::cout << "global_add(4,5)=" << gadd(4,5) << std::endl;
/// create an std::vector
std::vector<int> v;
/// void-Member function with one parameter
/// preserve type-correctness (argument is not int, but const int&)
Function<void,const int&> vpush = function(v,&std::vector<int>::push_back);
vpush(1); vpush(2); vpush(3);
/// access elements with this function
Function<int&,size_t> vat = function(v,&std::vector<int>::at);
std::cout << "elem 0: " << vat(0) << std::endl;
std::cout << "elem 1: " << vat(1) << std::endl;
std::cout << "elem 2: " << vat(2) << std::endl;
/// create an instance of the foo class
Foo f;
/// creating a list of functions of same type
std::vector<Function<int,int,int> > list;
list.push_back(function(f,&Foo::add)); // member function
list.push_back(function(f,SelectFunctor<int,int,int>())); // a functor
list.push_back(global_add); // a global function
/// Finally, we are also able to implement the FunctionImpl-interface
/// here, we have to implement the corresponding constructor
/// (which must const!!!)
struct Impl : FunctionImpl<int,int,int>{
virtual int operator()(int a, int b) const{
std::cout << "custom impl:operator()(a,b) = " << a+b << std::endl;
return a+b;
}
};
// list.push_back(function(new Impl));
// would also be possible, but implicit cast is possible
list.push_back(new Impl);
/// clear the vector of ints also by using a Function-instance:
function(v,&std::vector<int>::clear)();
/// create a function that wraps the index operator
Function<int&,size_t> vidxop = function(v,&std::vector<int>::operator[]);
/// push the results of the function in the vector
for(unsigned int i=0;i<list.size();++i){
vpush(list[i](i,i));
}
/// create a function for the vector size
Function<size_t> vsize = function(v,&std::vector<int>::size);
/// show the result of the vector-size function
std::cout << vsize() << std::endl;
for(unsigned int i=0;i<vsize();++i){
std::cout << "v[" << i << "] = " << vidxop(i) << std::endl;
}
/// or use a function and std::for_each to print the results
std::for_each(v.begin(),v.end(),function(Foo::show_int));
}
|
Random Number Generation¶
Even though, creation of random numbers is supported sufficiently in C++, ICL provides some extra functions and classes here. In particular creation of Gaussian distributed random numbers usually requires some extra work. In addition to the normal random number generation functions random(min,max) and gaussRandom(mean,variance), few special classes are provided, that can be created with the random number generation properties, and that will draw a new random number, whenever they are assigned to something.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | #include <ICLUtils/Random.h>
#include <vector>
#include <algorithm>
using namespace icl;
int main(){
// intialize with current system time
utils::randomSeed();
// uniformly distributed random number between 0 and 1
float f = utils::random(0,1);
// Gaussian random number with mean 0 and variance 1
float g = utils::gaussRandom(0,1);
// buffer
std::vector<float> ns(100);
// fill each element with a random number
// here uniformly distributed in [10,20]
std::fill(ns.begin(),ns.end(), utils::URand(10,20));
// or with gaussian random numbers
std::fill(ns.begin(),ns.end(), utils::GRand(0,3));
// create random indices (int values between 0 and given max)
std::vector<int> is(100);
std::fill(is.begin(),is.end(),utils::URandI(99));
}
|
The File class¶
The File class is a simple, yet powerful wrapper of a default C-Style FILE-pointer. In case of zlib-support, it provides built-in abilities for gzipped file I/O. I.e. as soon as a file-ending “.gz” is detected, the file will be written and read using zlib-functions.
In addition to this it supports
buffered reading
decomposition of file names into directory, basename and suffix
several reading and writing functions
File::exists()
OpenCL Support Framework¶
ICL’s OpenCL support framework is intendet to provide an even easier access to OpenCL based acceleration. The framework is even settled on a higher level then OpenCL’s C++ front-end allowing to create and embed OpenCL code with only a few lines of support code. Relevant classes are:
utils::CLProgram, functioning as the main-class and as a factory for instances of the other support classes
utils::CLKernel, referencing a callable OpenCL function usually called kernel. Kernels can be filled with arguments and be called.
utils::CLBuffer, buffers are used to exchange memory with graphics card memory (i.e. uploading and downloading memory blocks from and to the graphics card memory)
An example for a simple 3x3 image convolution can be found in the utils::CLProgram API documentation-
Others¶
Abstract map implementation, that can hold entries of different types
Grants process information at run-time such as the current memory consumption, the application’s thread-count or the average processor usage of the system and the current process.
A generic, but difficult to use utility class for the creation of shallow- copyable classes
C++-based wrapper of the C-functions around sigaction for process signal handling
Support Macros¶
DEBUG_LOG(MESSAGE-STREAM)
Can be used to show standard debug messages, that automatically include the source file, line and function name. Internally a C++-stream is used so that debug messages can easily be composed:
DEBUG_LOG("loop " << i );
WARNING_LOG and ERROR_LOG
Can be used to show warning and critical log messages. They work identically like DEBUG_LOG
ICLASSERT(assertion)
Standard assertion wrapper that shows the code position of the failure. For convenience also ASSERT_RETURN(assertion), ASSERT_THROW(assertion,exception) and ASSERT_RETURN_VAL(assertion,return-value) are provided.
ICL_UNLIKELY(unlikely-test)
Is a wrapper of gcc’s __builtin_expect:
if(ICL_UNLIKELY(error)){ break; }
ICL_DEPRECATED
Can be used to add a deprecated status to functions and classes:
void ICL_DEPRECATED foo(){ .. } class ICL_DEPRECATED Bar { ...};
Is a generic power-of-two template, that is sometimes very useful.
Note
utils::sqr is a function rather than a macro and therefore is lies within the icl::utils-namespace
iclMin and iclMax
Are generic replacements of the sometimes missing std::min and std::max function templates. Usually, iclMin and iclMax are just macros that forward their arguments to the std-functions
ICL_DELETE(pointer)
Deletes only non-null pointers and sets them to 0 after deletion. For arrays, ICL_DELETE_ARRAY(pointer) has to be used.