Merge branch 'master' into PIStringTests
This commit is contained in:
@@ -2,8 +2,8 @@ cmake_minimum_required(VERSION 3.0)
|
||||
cmake_policy(SET CMP0017 NEW) # need include() with .cmake
|
||||
project(pip)
|
||||
set(pip_MAJOR 2)
|
||||
set(pip_MINOR 8)
|
||||
set(pip_REVISION 0)
|
||||
set(pip_MINOR 15)
|
||||
set(pip_REVISION 1)
|
||||
set(pip_SUFFIX )
|
||||
set(pip_COMPANY SHS)
|
||||
set(pip_DOMAIN org.SHS)
|
||||
@@ -121,11 +121,6 @@ macro(pip_find_lib NAME)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
if (DEFINED ENV{QNX_HOST} OR PIP_FREERTOS)
|
||||
set(STATIC_LIB ON)
|
||||
endif()
|
||||
|
||||
|
||||
# Version
|
||||
list(APPEND HDRS "${CMAKE_CURRENT_BINARY_DIR}/pip_version.h")
|
||||
|
||||
@@ -433,6 +428,9 @@ if (NOT CROSSTOOLS)
|
||||
|
||||
# Test program
|
||||
if(PIP_UTILS)
|
||||
#add_library(pip_plugin SHARED "test_plugin.h" "test_plugin.cpp")
|
||||
#target_link_libraries(pip_plugin pip)
|
||||
|
||||
add_executable(pip_test "main.cpp")
|
||||
target_link_libraries(pip_test pip pip_cloud)
|
||||
if (LUA_FOUND)
|
||||
@@ -441,24 +439,9 @@ if (NOT CROSSTOOLS)
|
||||
endif()
|
||||
|
||||
else()
|
||||
|
||||
set(PIP_MSG_crypt "yes")
|
||||
set(PIP_MSG_compress "yes")
|
||||
set(PIP_MODULES pip)
|
||||
add_definitions(-DPIP_CRYPT)
|
||||
add_library(pip_crypt ${pip_LIB_TYPE} ${CPP_LIB_CRYPT})
|
||||
target_link_libraries(pip_crypt pip)
|
||||
list(APPEND PIP_MODULES pip_crypt)
|
||||
set(IO_UTILS_LIBS pip)
|
||||
add_library(pip_io_utils ${pip_LIB_TYPE} ${CPP_LIB_IO_UTILS})
|
||||
list(APPEND IO_UTILS_LIBS pip_crypt)
|
||||
target_link_libraries(pip_io_utils ${IO_UTILS_LIBS})
|
||||
list(APPEND PIP_MODULES pip_io_utils)
|
||||
add_definitions(-DPIP_COMPRESS)
|
||||
add_library(pip_compress ${pip_LIB_TYPE} ${CPP_LIB_COMPRESS})
|
||||
target_link_libraries(pip_compress pip)
|
||||
list(APPEND PIP_MODULES pip_compress)
|
||||
|
||||
pip_module(crypt "" "PIP crypt support" "" "")
|
||||
pip_module(compress "" "PIP compression support" "" "")
|
||||
pip_module(io_utils "pip_crypt" "PIP I/O support" "" " (+crypt)")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
@@ -21,8 +21,13 @@ cmake_policy(SET CMP0011 NEW) # don`t affect includer policies
|
||||
include(SHSTKMacros)
|
||||
|
||||
shstk_set_find_dirs(pip)
|
||||
if(PIP_DIR)
|
||||
list(APPEND pip_LIBDIR "${PIP_DIR}/lib")
|
||||
list(APPEND pip_INCDIR "${PIP_DIR}/include/pip")
|
||||
list(APPEND pip_BINDIR "${PIP_DIR}/bin")
|
||||
endif()
|
||||
|
||||
set(__libs "usb;crypt;console;fftw;compress;io_utils;cloud;lua")
|
||||
set(__libs "usb;crypt;console;fftw;compress;io_utils;opencl;cloud;lua")
|
||||
|
||||
if (BUILDING_pip)
|
||||
#set(_libs "pip;pip_usb;pip_console;pip_crypt;pip_fftw;pip_compress;pip_opencl;pip_io_utils;pip_cloud;pip_lua")
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
#[[
|
||||
|
||||
pip_code_model(<out_var> file0 [file1 ...] [OPTIONS opt0 [opt1 ...] ] [ABSOLUTE])
|
||||
pip_code_model(<out_var> file0 [file1 ...] [OPTIONS opt0 [opt1 ...] ])
|
||||
|
||||
Generate code model files for source files file0 [file1 ...]
|
||||
|
||||
Options you can see by exec "pip_cmg -h"
|
||||
If not ABSOLUTE source files will be prepended by CMAKE_CURRENT_SOURCE_DIR
|
||||
Relative files pathes read from CMAKE_CURRENT_SOURCE_DIR
|
||||
You should add ${<out_var>} to your target
|
||||
|
||||
|
||||
@@ -53,15 +53,13 @@ macro(pip_code_model RESULT)
|
||||
set(CCM_OUT ${CMAKE_CURRENT_BINARY_DIR}/ccm_${PROJECT_NAME}.cpp)
|
||||
set(${RESULT} ${${RESULT}} ${CCM_OUT})
|
||||
set(CCM_FILES)
|
||||
if (ABS)
|
||||
foreach(csrc ${CCM_SRC})
|
||||
foreach(csrc ${CCM_SRC})
|
||||
if (IS_ABSOLUTE "${csrc}")
|
||||
list(APPEND CCM_FILES "${csrc}")
|
||||
endforeach()
|
||||
else()
|
||||
foreach(csrc ${CCM_SRC})
|
||||
else()
|
||||
list(APPEND CCM_FILES "${CMAKE_CURRENT_SOURCE_DIR}/${csrc}")
|
||||
endforeach()
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
#message(STATUS "CCM = ${RESULT}")
|
||||
if(NOT DEFINED PIP_DLL_DIR)
|
||||
set(PIP_DLL_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
@@ -47,3 +47,21 @@ while (!cs2.atEnd()) {
|
||||
}
|
||||
piCout << i << str << f << s.i << s.f << s.s;
|
||||
//! [read]
|
||||
|
||||
//! [write_new]
|
||||
PIByteArray & operator <<(PIByteArray & s, const S & value) {
|
||||
PIChunkStream cs;
|
||||
cs.add(1, value.i).add(2, value.f).add(3, value.s);
|
||||
s << cs.data();
|
||||
return s;
|
||||
}
|
||||
//! [write_new]
|
||||
//! [read_new]
|
||||
PIByteArray & operator >>(PIByteArray & s, S & value) {
|
||||
PIChunkStream cs;
|
||||
if (!cs.extract(s)) return s;
|
||||
cs.readAll();
|
||||
cs.get(1, value.i).get(2, value.f).get(3, value.s);
|
||||
return b;
|
||||
}
|
||||
//! [read_new]
|
||||
|
||||
49
esp-pip/CMakeLists.txt
Normal file
49
esp-pip/CMakeLists.txt
Normal file
@@ -0,0 +1,49 @@
|
||||
set(COMPONENT_SRCS "main.cpp")
|
||||
set(COMPONENT_ADD_INCLUDEDIRS "../libs/main")
|
||||
list(APPEND COMPONENT_ADD_INCLUDEDIRS "../libs/main/cloud")
|
||||
list(APPEND COMPONENT_ADD_INCLUDEDIRS "../libs/main/code")
|
||||
list(APPEND COMPONENT_ADD_INCLUDEDIRS "../libs/main/compress")
|
||||
list(APPEND COMPONENT_ADD_INCLUDEDIRS "../libs/main/console")
|
||||
list(APPEND COMPONENT_ADD_INCLUDEDIRS "../libs/main/containers")
|
||||
list(APPEND COMPONENT_ADD_INCLUDEDIRS "../libs/main/core")
|
||||
list(APPEND COMPONENT_ADD_INCLUDEDIRS "../libs/main/crypt")
|
||||
list(APPEND COMPONENT_ADD_INCLUDEDIRS "../libs/main/geo")
|
||||
list(APPEND COMPONENT_ADD_INCLUDEDIRS "../libs/main/io_devices")
|
||||
list(APPEND COMPONENT_ADD_INCLUDEDIRS "../libs/main/io_utils")
|
||||
list(APPEND COMPONENT_ADD_INCLUDEDIRS "../libs/main/math")
|
||||
list(APPEND COMPONENT_ADD_INCLUDEDIRS "../libs/main/resources")
|
||||
list(APPEND COMPONENT_ADD_INCLUDEDIRS "../libs/main/system")
|
||||
list(APPEND COMPONENT_ADD_INCLUDEDIRS "../libs/main/thread")
|
||||
set(COMPONENT_PRIV_REQUIRES pthread lwip freertos vfs spi_flash libsodium)
|
||||
register_component()
|
||||
set(PIP_FREERTOS ON)
|
||||
set(LIB OFF)
|
||||
set(INCLUDE_DIRS ${IDF_INCLUDE_DIRECTORIES})
|
||||
list(APPEND INCLUDE_DIRS $ENV{IDF_PATH}/components/newlib/platform_include)
|
||||
list(APPEND INCLUDE_DIRS $ENV{IDF_PATH}/components/newlib/include)
|
||||
list(APPEND INCLUDE_DIRS $ENV{IDF_PATH}/components/libsodium/libsodium/src/libsodium/include)
|
||||
list(APPEND INCLUDE_DIRS $ENV{IDF_PATH}/components/libsodium/port_include)
|
||||
list(APPEND INCLUDE_DIRS $ENV{IDF_PATH}/components/heap/include)
|
||||
list(APPEND INCLUDE_DIRS $ENV{IDF_PATH}/components/esp_rom/include/esp32)
|
||||
list(APPEND INCLUDE_DIRS $ENV{IDF_PATH}/components/driver/include)
|
||||
list(APPEND INCLUDE_DIRS $ENV{IDF_PATH}/components/spi_flash/include)
|
||||
list(APPEND INCLUDE_DIRS $ENV{IDF_PATH}/components/spiffs/include)
|
||||
list(APPEND INCLUDE_DIRS $ENV{IDF_PATH}/components/soc/include)
|
||||
list(APPEND INCLUDE_DIRS $ENV{IDF_PATH}/components/soc/esp32/include)
|
||||
list(APPEND INCLUDE_DIRS $ENV{IDF_PATH}/components/freertos/include)
|
||||
list(APPEND INCLUDE_DIRS $ENV{IDF_PATH}/components/lwip/lwip/src/include)
|
||||
list(APPEND INCLUDE_DIRS $ENV{IDF_PATH}/components/lwip/port/esp32/include)
|
||||
list(APPEND INCLUDE_DIRS $ENV{IDF_PATH}/components/vfs/include)
|
||||
include_directories(${INCLUDE_DIRS})
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR}/pip)
|
||||
#message("IDF_COMPILE_DEFINITIONS = ${IDF_COMPILE_DEFINITIONS}")
|
||||
#message("IDF_INCLUDE_DIRECTORIES = ${IDF_INCLUDE_DIRECTORIES}")
|
||||
add_compile_options(${IDF_COMPILE_OPTIONS})
|
||||
add_compile_options(${IDF_CXX_COMPILE_OPTIONS})
|
||||
add_definitions(-DESP_PLATFORM)
|
||||
add_definitions(-DGCC_NOT_5_2_0=0)
|
||||
add_definitions(-DHAVE_CONFIG_H)
|
||||
add_subdirectory(.. pip)
|
||||
find_package(PIP REQUIRED)
|
||||
target_link_libraries(${COMPONENT_TARGET} PIP::Crypt PIP::IOUtils PIP::Compress)
|
||||
target_compile_definitions(${COMPONENT_TARGET} PRIVATE ESP_PLATFORM PIP_FREERTOS)
|
||||
@@ -1,49 +0,0 @@
|
||||
set(COMPONENT_SRCS "main.cpp")
|
||||
set(COMPONENT_ADD_INCLUDEDIRS "pip/lib/main")
|
||||
list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/auxiliary")
|
||||
list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/code")
|
||||
list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/console")
|
||||
list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/containers")
|
||||
list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/core")
|
||||
list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/crypt")
|
||||
list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/geo")
|
||||
list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/io_devices")
|
||||
list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/io_utils")
|
||||
list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/math")
|
||||
list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/opencl")
|
||||
list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/resources")
|
||||
list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/system")
|
||||
list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/thread")
|
||||
list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/introspection")
|
||||
set(COMPONENT_PRIV_REQUIRES pthread lwip freertos vfs spiffs)
|
||||
register_component()
|
||||
set(PIP_FREERTOS ON)
|
||||
set(LIB OFF)
|
||||
set(INCLUDE_DIRS ${IDF_INCLUDE_DIRECTORIES})
|
||||
list(APPEND INCLUDE_DIRS "../newlib/platform_include")
|
||||
list(APPEND INCLUDE_DIRS "../newlib/include")
|
||||
list(APPEND INCLUDE_DIRS "../libsodium/libsodium/src/libsodium/include")
|
||||
list(APPEND INCLUDE_DIRS "../libsodium/port_include")
|
||||
list(APPEND INCLUDE_DIRS "../heap/include")
|
||||
list(APPEND INCLUDE_DIRS "../esp_rom/include/esp32")
|
||||
list(APPEND INCLUDE_DIRS "../driver/include")
|
||||
list(APPEND INCLUDE_DIRS "../spi_flash/include")
|
||||
list(APPEND INCLUDE_DIRS "../spiffs/include")
|
||||
list(APPEND INCLUDE_DIRS "../soc/include")
|
||||
list(APPEND INCLUDE_DIRS "../soc/esp32/include")
|
||||
list(APPEND INCLUDE_DIRS "../freertos/include")
|
||||
list(APPEND INCLUDE_DIRS "../lwip/lwip/src/include")
|
||||
list(APPEND INCLUDE_DIRS "../lwip/port/esp32/include")
|
||||
list(APPEND INCLUDE_DIRS "../vfs/include")
|
||||
include_directories(${INCLUDE_DIRS})
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR}/pip)
|
||||
#message("IDF_COMPILE_DEFINITIONS = ${IDF_COMPILE_DEFINITIONS}")
|
||||
#message("IDF_INCLUDE_DIRECTORIES = ${IDF_INCLUDE_DIRECTORIES}")
|
||||
add_compile_options(${IDF_COMPILE_OPTIONS})
|
||||
add_compile_options(${IDF_CXX_COMPILE_OPTIONS})
|
||||
add_definitions(-DESP_PLATFORM)
|
||||
add_definitions(-DGCC_NOT_5_2_0=0)
|
||||
add_definitions(-DHAVE_CONFIG_H)
|
||||
add_subdirectory(pip)
|
||||
|
||||
target_link_libraries(${COMPONENT_TARGET} pip pip_crypt pip_io_utils pip_compress)
|
||||
@@ -20,7 +20,7 @@
|
||||
#include "picompress.h"
|
||||
#ifdef PIP_COMPRESS
|
||||
# ifdef FREERTOS
|
||||
# include "rom/miniz.h"
|
||||
# include "esp32/rom/miniz.h"
|
||||
# define compress2 mz_compress2
|
||||
# define Z_OK MZ_OK
|
||||
# define uncompress mz_uncompress
|
||||
|
||||
@@ -409,6 +409,8 @@ bool PICrypt::init() {
|
||||
if (inited) return true;
|
||||
//piCout << "[PICrypt]" << "init ...";
|
||||
inited = sodium_init();
|
||||
if (!inited)
|
||||
inited = sodium_init();
|
||||
//piCout << "[PICrypt]" << "init" << inited;
|
||||
return inited;
|
||||
#else
|
||||
|
||||
@@ -174,6 +174,13 @@ inline const char * getMemberType(const char * class_name, const char * member_n
|
||||
|
||||
PIP_EXPORT PIVariant getMemberAsVariant(const void * p, const char * class_name, const char * member_name);
|
||||
|
||||
|
||||
template<typename T, typename std::enable_if< std::is_assignable<T&, const T&>::value, int>::type = 0>
|
||||
void serialize(PIByteArray & ret, const T & v) {ret << v;}
|
||||
|
||||
template<typename T, typename std::enable_if<!std::is_assignable<T&, const T&>::value, int>::type = 0>
|
||||
void serialize(PIByteArray & ret, const T & v) {}
|
||||
|
||||
}
|
||||
|
||||
class PIP_EXPORT __PICodeInfoInitializer__ {
|
||||
|
||||
@@ -252,5 +252,8 @@ inline PIByteArray & operator >>(PIByteArray & s, PIKbdListener::KeyEvent & v) {
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIKbdListener::MouseEvent & v) {int a(0); s >> v.x >> v.y >> a >> v.buttons >> v.modifiers; v.action = (PIKbdListener::MouseAction)a; return s;}
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIKbdListener::WheelEvent & v) {uchar d(0); s >> (*(PIKbdListener::MouseEvent*)&v) >> d; v.direction = d; return s;}
|
||||
|
||||
REGISTER_PIVARIANTSIMPLE(PIKbdListener::KeyEvent)
|
||||
REGISTER_PIVARIANTSIMPLE(PIKbdListener::MouseEvent)
|
||||
REGISTER_PIVARIANTSIMPLE(PIKbdListener::WheelEvent)
|
||||
|
||||
#endif // PIKBDLISTENER_H
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
#include "pip_console_export.h"
|
||||
#include "pivariant.h"
|
||||
#include "pivariantsimple.h"
|
||||
|
||||
class PIScreenTile;
|
||||
|
||||
@@ -140,8 +141,11 @@ namespace PIScreenTypes {
|
||||
|
||||
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIScreenTypes::Cell & v) {s << v.format.raw_format << v.symbol; return s;}
|
||||
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIScreenTypes::Cell & v) {s >> v.format.raw_format >> v.symbol; return s;}
|
||||
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIScreenTypes::TileEvent & v) {s << v.type << v.data; return s;}
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIScreenTypes::TileEvent & v) {s >> v.type >> v.data; return s;}
|
||||
|
||||
REGISTER_PIVARIANTSIMPLE(PIScreenTypes::TileEvent)
|
||||
|
||||
#endif // PISCREENTYPES_H
|
||||
|
||||
@@ -28,15 +28,6 @@
|
||||
|
||||
#include "picout.h"
|
||||
#include "piintrospection_containers.h"
|
||||
#ifdef PIP_DEBUG
|
||||
# ifdef NDEBUG
|
||||
# undef NDEBUG
|
||||
# endif
|
||||
# include <cassert>
|
||||
#endif
|
||||
#ifndef assert
|
||||
# define assert(x)
|
||||
#endif
|
||||
#ifdef MAC_OS
|
||||
# include <stdlib.h>
|
||||
#else
|
||||
|
||||
@@ -209,7 +209,22 @@ public:
|
||||
inline T * data(size_t index = 0) {return &(pid_data[pid_start + index]);}
|
||||
inline const T * data(size_t index = 0) const {return &(pid_data[pid_start + index]);}
|
||||
|
||||
inline PIDeque<T> & clear() {resize(0); return *this;}
|
||||
template<typename T1 = T, typename std::enable_if<
|
||||
!std::is_trivially_copyable<T1>::value
|
||||
, int>::type = 0>
|
||||
inline PIDeque<T> & clear() {
|
||||
resize(0);
|
||||
return *this;
|
||||
}
|
||||
template<typename T1 = T, typename std::enable_if<
|
||||
std::is_trivially_copyable<T1>::value
|
||||
, int>::type = 0>
|
||||
inline PIDeque<T> & clear() {
|
||||
PIINTROSPECTION_CONTAINER_UNUSED(T, pid_size)
|
||||
pid_size = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline PIDeque<T> & fill(const T & f = T()) {
|
||||
deleteT(pid_data + pid_start, pid_size);
|
||||
PIINTROSPECTION_CONTAINER_USED(T, pid_size)
|
||||
@@ -218,10 +233,20 @@ public:
|
||||
return *this;
|
||||
}
|
||||
inline PIDeque<T> & assign(const T & f = T()) {return fill(f);}
|
||||
template<typename T1 = T, typename std::enable_if<
|
||||
!std::is_trivially_copyable<T1>::value
|
||||
, int>::type = 0>
|
||||
inline PIDeque<T> & assign(size_t new_size, const T & f) {
|
||||
resize(new_size);
|
||||
return fill(f);
|
||||
}
|
||||
template<typename T1 = T, typename std::enable_if<
|
||||
std::is_trivially_copyable<T1>::value
|
||||
, int>::type = 0>
|
||||
inline PIDeque<T> & assign(size_t new_size, const T & f) {
|
||||
_resizeRaw(new_size);
|
||||
return fill(f);
|
||||
}
|
||||
|
||||
inline PIDeque<T> & resize(size_t new_size, const T & f = T()) {
|
||||
if (new_size < pid_size) {
|
||||
@@ -236,9 +261,18 @@ public:
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T1 = T, typename std::enable_if<
|
||||
std::is_trivially_copyable<T1>::value
|
||||
, int>::type = 0>
|
||||
inline PIDeque<T> & _resizeRaw(size_t new_size) {
|
||||
piCout << "Error, \"resizeRaw()\" only allowed for simple type declared with __PIDEQUE_SIMPLE_TYPE__ macro!";
|
||||
assert(0);
|
||||
if (new_size > pid_size) {
|
||||
PIINTROSPECTION_CONTAINER_USED(T, (new_size-pid_size));
|
||||
}
|
||||
if (new_size < pid_size) {
|
||||
PIINTROSPECTION_CONTAINER_UNUSED(T, (pid_size-new_size));
|
||||
}
|
||||
alloc(new_size, true);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -437,11 +471,24 @@ private:
|
||||
++t;
|
||||
return (1 << t);
|
||||
}
|
||||
template<typename T1 = T, typename std::enable_if<
|
||||
!std::is_trivially_copyable<T1>::value
|
||||
, int>::type = 0>
|
||||
inline void newT(T * dst, const T * src, size_t s) {
|
||||
PIINTROSPECTION_CONTAINER_USED(T, s)
|
||||
for (size_t i = 0; i < s; ++i)
|
||||
elementNew(dst + i, src[i]);
|
||||
}
|
||||
template<typename T1 = T, typename std::enable_if<
|
||||
std::is_trivially_copyable<T1>::value
|
||||
, int>::type = 0>
|
||||
inline void newT(T * dst, const T * src, size_t s) {
|
||||
PIINTROSPECTION_CONTAINER_USED(T, s)
|
||||
memcpy((void*)(dst), (const void*)(src), s * sizeof(T));
|
||||
}
|
||||
template<typename T1 = T, typename std::enable_if<
|
||||
!std::is_trivially_copyable<T1>::value
|
||||
, int>::type = 0>
|
||||
inline void deleteT(T * d, size_t sz) {
|
||||
PIINTROSPECTION_CONTAINER_UNUSED(T, sz)
|
||||
if ((uchar*)d != 0) {
|
||||
@@ -449,9 +496,36 @@ private:
|
||||
elementDelete(d[i]);
|
||||
}
|
||||
}
|
||||
template<typename T1 = T, typename std::enable_if<
|
||||
std::is_trivially_copyable<T1>::value
|
||||
, int>::type = 0>
|
||||
inline void deleteT(T * d, size_t sz) {
|
||||
PIINTROSPECTION_CONTAINER_UNUSED(T, sz)
|
||||
}
|
||||
template<typename T1 = T, typename std::enable_if<
|
||||
!std::is_trivially_copyable<T1>::value
|
||||
, int>::type = 0>
|
||||
inline void elementNew(T * to, const T & from) {new(to)T(from);}
|
||||
template<typename T1 = T, typename std::enable_if<
|
||||
!std::is_trivially_copyable<T1>::value
|
||||
, int>::type = 0>
|
||||
inline void elementNew(T * to, T && from) {new(to)T(std::move(from));}
|
||||
template<typename T1 = T, typename std::enable_if<
|
||||
std::is_trivially_copyable<T1>::value
|
||||
, int>::type = 0>
|
||||
inline void elementNew(T1 * to, const T & from) {(*to) = from;}
|
||||
template<typename T1 = T, typename std::enable_if<
|
||||
std::is_trivially_copyable<T1>::value
|
||||
, int>::type = 0>
|
||||
inline void elementNew(T * to, T && from) {(*to) = std::move(from);}
|
||||
template<typename T1 = T, typename std::enable_if<
|
||||
!std::is_trivially_copyable<T1>::value
|
||||
, int>::type = 0>
|
||||
inline void elementDelete(T & from) {from.~T();}
|
||||
template<typename T1 = T, typename std::enable_if<
|
||||
std::is_trivially_copyable<T1>::value
|
||||
, int>::type = 0>
|
||||
inline void elementDelete(T & from) {}
|
||||
inline void dealloc() {
|
||||
if ((uchar*)pid_data != 0) free((uchar*)pid_data);
|
||||
pid_data = 0;
|
||||
@@ -520,41 +594,6 @@ private:
|
||||
ssize_t pid_start;
|
||||
};
|
||||
|
||||
#define __PIDEQUE_SIMPLE_TYPE__(T) \
|
||||
template<> inline void PIDeque<T>::newT(T * dst, const T * src, size_t s) {PIINTROSPECTION_CONTAINER_USED(T, s); memcpy((void*)(dst), (const void*)(src), s * sizeof(T));} \
|
||||
template<> inline void PIDeque<T>::deleteT(T *, size_t sz) {PIINTROSPECTION_CONTAINER_UNUSED(T, sz);} \
|
||||
template<> inline void PIDeque<T>::elementNew(T * to, const T & from) {(*to) = from;} \
|
||||
template<> inline void PIDeque<T>::elementNew(T * to, T && from) {(*to) = std::move(from);} \
|
||||
template<> inline void PIDeque<T>::elementDelete(T &) {;} \
|
||||
template<> inline PIDeque<T> & PIDeque<T>::_resizeRaw(size_t new_size) { \
|
||||
if (new_size > pid_size) { \
|
||||
PIINTROSPECTION_CONTAINER_USED(T, (new_size-pid_size)); \
|
||||
} \
|
||||
if (new_size < pid_size) { \
|
||||
PIINTROSPECTION_CONTAINER_UNUSED(T, (pid_size-new_size)); \
|
||||
} \
|
||||
alloc(new_size, true); \
|
||||
return *this; \
|
||||
} \
|
||||
template<> inline PIDeque<T> & PIDeque<T>::clear() {PIINTROSPECTION_CONTAINER_UNUSED(T, pid_size); pid_size = 0; return *this;} \
|
||||
template<> inline PIDeque<T> & PIDeque<T>::assign(size_t new_size, const T & f) {_resizeRaw(new_size); return fill(f);}
|
||||
|
||||
|
||||
__PIDEQUE_SIMPLE_TYPE__(bool)
|
||||
__PIDEQUE_SIMPLE_TYPE__(char)
|
||||
__PIDEQUE_SIMPLE_TYPE__(uchar)
|
||||
__PIDEQUE_SIMPLE_TYPE__(short)
|
||||
__PIDEQUE_SIMPLE_TYPE__(ushort)
|
||||
__PIDEQUE_SIMPLE_TYPE__(int)
|
||||
__PIDEQUE_SIMPLE_TYPE__(uint)
|
||||
__PIDEQUE_SIMPLE_TYPE__(long)
|
||||
__PIDEQUE_SIMPLE_TYPE__(ulong)
|
||||
__PIDEQUE_SIMPLE_TYPE__(llong)
|
||||
__PIDEQUE_SIMPLE_TYPE__(ullong)
|
||||
__PIDEQUE_SIMPLE_TYPE__(float)
|
||||
__PIDEQUE_SIMPLE_TYPE__(double)
|
||||
__PIDEQUE_SIMPLE_TYPE__(ldouble)
|
||||
|
||||
|
||||
#ifdef PIP_STD_IOSTREAM
|
||||
template<typename T>
|
||||
|
||||
@@ -28,9 +28,6 @@
|
||||
#include "pivector.h"
|
||||
#include "pideque.h"
|
||||
#include "pipair.h"
|
||||
# define __PICONTAINERS_SIMPLE_TYPE__(T) \
|
||||
__PIDEQUE_SIMPLE_TYPE__(T)\
|
||||
__PIVECTOR_SIMPLE_TYPE__(T)
|
||||
|
||||
|
||||
template<class T>
|
||||
|
||||
@@ -210,7 +210,22 @@ public:
|
||||
inline T * data(size_t index = 0) {return &(piv_data[index]);}
|
||||
inline const T * data(size_t index = 0) const {return &(piv_data[index]);}
|
||||
|
||||
inline PIVector<T> & clear() {resize(0); return *this;}
|
||||
template<typename T1 = T, typename std::enable_if<
|
||||
!std::is_trivially_copyable<T1>::value
|
||||
, int>::type = 0>
|
||||
inline PIVector<T> & clear() {
|
||||
resize(0);
|
||||
return *this;
|
||||
}
|
||||
template<typename T1 = T, typename std::enable_if<
|
||||
std::is_trivially_copyable<T1>::value
|
||||
, int>::type = 0>
|
||||
inline PIVector<T> & clear() {
|
||||
PIINTROSPECTION_CONTAINER_UNUSED(T, piv_size)
|
||||
piv_size = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline PIVector<T> & fill(const T & f = T()) {
|
||||
deleteT(piv_data, piv_size);
|
||||
PIINTROSPECTION_CONTAINER_USED(T, piv_size)
|
||||
@@ -219,10 +234,20 @@ public:
|
||||
return *this;
|
||||
}
|
||||
inline PIVector<T> & assign(const T & f = T()) {return fill(f);}
|
||||
template<typename T1 = T, typename std::enable_if<
|
||||
!std::is_trivially_copyable<T1>::value
|
||||
, int>::type = 0>
|
||||
inline PIVector<T> & assign(size_t new_size, const T & f) {
|
||||
resize(new_size);
|
||||
return fill(f);
|
||||
}
|
||||
template<typename T1 = T, typename std::enable_if<
|
||||
std::is_trivially_copyable<T1>::value
|
||||
, int>::type = 0>
|
||||
inline PIVector<T> & assign(size_t new_size, const T & f) {
|
||||
_resizeRaw(new_size);
|
||||
return fill(f);
|
||||
}
|
||||
|
||||
inline PIVector<T> & resize(size_t new_size, const T & f = T()) {
|
||||
if (new_size < piv_size) {
|
||||
@@ -239,9 +264,17 @@ public:
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
template<typename T1 = T, typename std::enable_if<
|
||||
std::is_trivially_copyable<T1>::value
|
||||
, int>::type = 0>
|
||||
inline PIVector<T> & _resizeRaw(size_t new_size) {
|
||||
piCout << "Error, \"resizeRaw()\" only allowed for simple type declared with __PIVECTOR_SIMPLE_TYPE__ macro!";
|
||||
assert(0);
|
||||
if (new_size > piv_size) {
|
||||
PIINTROSPECTION_CONTAINER_USED(T, (new_size-piv_size));
|
||||
}
|
||||
if (new_size < piv_size) {
|
||||
PIINTROSPECTION_CONTAINER_UNUSED(T, (piv_size-new_size));
|
||||
}
|
||||
alloc(new_size);
|
||||
return *this;
|
||||
}
|
||||
inline void _copyRaw(T * dst, const T * src, size_t size) {
|
||||
@@ -425,11 +458,24 @@ private:
|
||||
while (s_ >> t) ++t;
|
||||
return (1 << t);
|
||||
}
|
||||
template<typename T1 = T, typename std::enable_if<
|
||||
!std::is_trivially_copyable<T1>::value
|
||||
, int>::type = 0>
|
||||
inline void newT(T * dst, const T * src, size_t s) {
|
||||
PIINTROSPECTION_CONTAINER_USED(T, s)
|
||||
for (size_t i = 0; i < s; ++i)
|
||||
elementNew(dst + i, src[i]);
|
||||
}
|
||||
template<typename T1 = T, typename std::enable_if<
|
||||
std::is_trivially_copyable<T1>::value
|
||||
, int>::type = 0>
|
||||
inline void newT(T * dst, const T * src, size_t s) {
|
||||
PIINTROSPECTION_CONTAINER_USED(T, s)
|
||||
memcpy((void*)(dst), (const void*)(src), s * sizeof(T));
|
||||
}
|
||||
template<typename T1 = T, typename std::enable_if<
|
||||
!std::is_trivially_copyable<T1>::value
|
||||
, int>::type = 0>
|
||||
inline void deleteT(T * d, size_t sz) {
|
||||
PIINTROSPECTION_CONTAINER_UNUSED(T, sz)
|
||||
if ((uchar*)d != 0) {
|
||||
@@ -437,9 +483,36 @@ private:
|
||||
elementDelete(d[i]);
|
||||
}
|
||||
}
|
||||
template<typename T1 = T, typename std::enable_if<
|
||||
std::is_trivially_copyable<T1>::value
|
||||
, int>::type = 0>
|
||||
inline void deleteT(T * d, size_t sz) {
|
||||
PIINTROSPECTION_CONTAINER_UNUSED(T, sz)
|
||||
}
|
||||
template<typename T1 = T, typename std::enable_if<
|
||||
!std::is_trivially_copyable<T1>::value
|
||||
, int>::type = 0>
|
||||
inline void elementNew(T * to, const T & from) {new(to)T(from);}
|
||||
template<typename T1 = T, typename std::enable_if<
|
||||
!std::is_trivially_copyable<T1>::value
|
||||
, int>::type = 0>
|
||||
inline void elementNew(T * to, T && from) {new(to)T(std::move(from));}
|
||||
template<typename T1 = T, typename std::enable_if<
|
||||
std::is_trivially_copyable<T1>::value
|
||||
, int>::type = 0>
|
||||
inline void elementNew(T1 * to, const T & from) {(*to) = from;}
|
||||
template<typename T1 = T, typename std::enable_if<
|
||||
std::is_trivially_copyable<T1>::value
|
||||
, int>::type = 0>
|
||||
inline void elementNew(T * to, T && from) {(*to) = std::move(from);}
|
||||
template<typename T1 = T, typename std::enable_if<
|
||||
!std::is_trivially_copyable<T1>::value
|
||||
, int>::type = 0>
|
||||
inline void elementDelete(T & from) {from.~T();}
|
||||
template<typename T1 = T, typename std::enable_if<
|
||||
std::is_trivially_copyable<T1>::value
|
||||
, int>::type = 0>
|
||||
inline void elementDelete(T & from) {}
|
||||
inline void dealloc() {
|
||||
if ((uchar*)piv_data != 0) free((uchar*)piv_data);
|
||||
piv_data = 0;
|
||||
@@ -464,41 +537,6 @@ private:
|
||||
};
|
||||
|
||||
|
||||
#define __PIVECTOR_SIMPLE_TYPE__(T) \
|
||||
template<> inline void PIVector<T>::newT(T * dst, const T * src, size_t s) {PIINTROSPECTION_CONTAINER_USED(T, s); memcpy((void*)(dst), (const void*)(src), s * sizeof(T));} \
|
||||
template<> inline void PIVector<T>::deleteT(T *, size_t sz) {PIINTROSPECTION_CONTAINER_UNUSED(T, sz);} \
|
||||
template<> inline void PIVector<T>::elementNew(T * to, const T & from) {(*to) = from;} \
|
||||
template<> inline void PIVector<T>::elementNew(T * to, T && from) {(*to) = std::move(from);} \
|
||||
template<> inline void PIVector<T>::elementDelete(T &) {;} \
|
||||
template<> inline PIVector<T> & PIVector<T>::_resizeRaw(size_t new_size) { \
|
||||
if (new_size > piv_size) { \
|
||||
PIINTROSPECTION_CONTAINER_USED(T, (new_size-piv_size)); \
|
||||
} \
|
||||
if (new_size < piv_size) { \
|
||||
PIINTROSPECTION_CONTAINER_UNUSED(T, (piv_size-new_size)); \
|
||||
} \
|
||||
alloc(new_size); \
|
||||
return *this; \
|
||||
} \
|
||||
template<> inline PIVector<T> & PIVector<T>::clear() {PIINTROSPECTION_CONTAINER_UNUSED(T, piv_size); piv_size = 0; return *this;} \
|
||||
template<> inline PIVector<T> & PIVector<T>::assign(size_t new_size, const T & f) {_resizeRaw(new_size); return fill(f);}
|
||||
|
||||
|
||||
__PIVECTOR_SIMPLE_TYPE__(bool)
|
||||
__PIVECTOR_SIMPLE_TYPE__(char)
|
||||
__PIVECTOR_SIMPLE_TYPE__(uchar)
|
||||
__PIVECTOR_SIMPLE_TYPE__(short)
|
||||
__PIVECTOR_SIMPLE_TYPE__(ushort)
|
||||
__PIVECTOR_SIMPLE_TYPE__(int)
|
||||
__PIVECTOR_SIMPLE_TYPE__(uint)
|
||||
__PIVECTOR_SIMPLE_TYPE__(long)
|
||||
__PIVECTOR_SIMPLE_TYPE__(ulong)
|
||||
__PIVECTOR_SIMPLE_TYPE__(llong)
|
||||
__PIVECTOR_SIMPLE_TYPE__(ullong)
|
||||
__PIVECTOR_SIMPLE_TYPE__(float)
|
||||
__PIVECTOR_SIMPLE_TYPE__(double)
|
||||
__PIVECTOR_SIMPLE_TYPE__(ldouble)
|
||||
|
||||
|
||||
#ifdef PIP_STD_IOSTREAM
|
||||
template<typename T>
|
||||
|
||||
@@ -160,6 +160,7 @@ public:
|
||||
|
||||
inline T & element(size_t row, size_t col) {return mat[row * cols_ + col];}
|
||||
inline const T & element(size_t row, size_t col) const {return mat[row * cols_ + col];}
|
||||
inline const T & at(size_t row, size_t col) const {return mat[row * cols_ + col];}
|
||||
inline Row operator[](size_t index) {return Row(this, index);}
|
||||
inline RowConst operator[](size_t index) const {return RowConst(this, index);}
|
||||
inline T * data(size_t index = 0) {return mat.data(index);}
|
||||
@@ -218,7 +219,7 @@ public:
|
||||
int cs = (cols - cols_);
|
||||
if (cs < 0) {
|
||||
for (size_t r=0; r<rows; ++r) {
|
||||
mat.remove(r*cols_ + cols_, -cs);
|
||||
mat.remove(r*cols + cols, -cs);
|
||||
}
|
||||
}
|
||||
mat.resize(rows*cols, f);
|
||||
@@ -234,6 +235,13 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline bool operator ==(const PIVector2D<T> & t) const {
|
||||
if (cols_ != t.cols_ || rows_ != t.rows_)
|
||||
return false;
|
||||
return mat == t.mat;
|
||||
}
|
||||
inline bool operator !=(const PIVector2D<T> & t) const {return !(*this == t);}
|
||||
|
||||
PIVector<PIVector<T> > toVectors() const {
|
||||
PIVector<PIVector<T> > ret;
|
||||
ret.reserve(rows_);
|
||||
@@ -251,9 +259,13 @@ public:
|
||||
piSwap<size_t>(cols_, other.cols_);
|
||||
}
|
||||
|
||||
template<typename T1 = T, typename std::enable_if<
|
||||
std::is_trivially_copyable<T1>::value
|
||||
, int>::type = 0>
|
||||
inline PIVector2D<T> & _resizeRaw(size_t r, size_t c) {
|
||||
piCout << "Error, \"resizeRaw()\" only allowed for simple type declared with __PIVECTOR_SIMPLE_TYPE__ macro!";
|
||||
assert(0);
|
||||
rows_ = r;
|
||||
cols_ = c;
|
||||
mat._resizeRaw(r*c);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -287,22 +299,5 @@ inline PICout operator <<(PICout s, const PIVector2D<T> & v) {
|
||||
return s;
|
||||
}
|
||||
|
||||
#define __PIVECTOR2D_SIMPLE_TYPE__(T) \
|
||||
template<> inline PIVector2D<T> & PIVector2D<T>::_resizeRaw(size_t r, size_t c) {rows_ = r; cols_ = c; mat._resizeRaw(r*c); return *this;}
|
||||
|
||||
__PIVECTOR2D_SIMPLE_TYPE__(bool)
|
||||
__PIVECTOR2D_SIMPLE_TYPE__(char)
|
||||
__PIVECTOR2D_SIMPLE_TYPE__(uchar)
|
||||
__PIVECTOR2D_SIMPLE_TYPE__(short)
|
||||
__PIVECTOR2D_SIMPLE_TYPE__(ushort)
|
||||
__PIVECTOR2D_SIMPLE_TYPE__(int)
|
||||
__PIVECTOR2D_SIMPLE_TYPE__(uint)
|
||||
__PIVECTOR2D_SIMPLE_TYPE__(long)
|
||||
__PIVECTOR2D_SIMPLE_TYPE__(ulong)
|
||||
__PIVECTOR2D_SIMPLE_TYPE__(llong)
|
||||
__PIVECTOR2D_SIMPLE_TYPE__(ullong)
|
||||
__PIVECTOR2D_SIMPLE_TYPE__(float)
|
||||
__PIVECTOR2D_SIMPLE_TYPE__(double)
|
||||
__PIVECTOR2D_SIMPLE_TYPE__(ldouble)
|
||||
|
||||
#endif // PIVECTOR2D_H
|
||||
|
||||
@@ -155,6 +155,16 @@
|
||||
extern char ** environ;
|
||||
#endif
|
||||
|
||||
#ifdef NDEBUG
|
||||
# undef NDEBUG
|
||||
#endif
|
||||
#include <cassert>
|
||||
#ifndef assert
|
||||
# define assert(x)
|
||||
# define assertm(exp, msg)
|
||||
#else
|
||||
# define assertm(exp, msg) assert(((void)msg, exp))
|
||||
#endif
|
||||
|
||||
#ifdef CC_GCC
|
||||
# undef DEPRECATED
|
||||
@@ -348,7 +358,7 @@ inline bool piCompareBinary(const void * f, const void * s, size_t size) {
|
||||
*
|
||||
* Example:
|
||||
* \snippet piincludes.cpp round */
|
||||
template<typename T> inline int piRound(const T & v) {return int(v >= T(0.) ? v + T(0.5) : v - T(0.5));}
|
||||
template<typename T> inline constexpr int piRound(const T & v) {return int(v >= T(0.) ? v + T(0.5) : v - T(0.5));}
|
||||
|
||||
/*! \brief Templated function return floor of float falue
|
||||
* \details Floor is the largest integer that is not greater than value \n
|
||||
@@ -358,7 +368,7 @@ template<typename T> inline int piRound(const T & v) {return int(v >= T(0.) ? v
|
||||
*
|
||||
* Example:
|
||||
* \snippet piincludes.cpp floor */
|
||||
template<typename T> inline int piFloor(const T & v) {return v < T(0) ? int(v) - 1 : int(v);}
|
||||
template<typename T> inline constexpr int piFloor(const T & v) {return v < T(0) ? int(v) - 1 : int(v);}
|
||||
|
||||
/*! \brief Templated function return ceil of float falue
|
||||
* \details Ceil is the smallest integer that is not less than value \n
|
||||
@@ -368,7 +378,7 @@ template<typename T> inline int piFloor(const T & v) {return v < T(0) ? int(v) -
|
||||
*
|
||||
* Example:
|
||||
* \snippet piincludes.cpp ceil */
|
||||
template<typename T> inline int piCeil(const T & v) {return v < T(0) ? int(v) : int(v) + 1;}
|
||||
template<typename T> inline constexpr int piCeil(const T & v) {return v < T(0) ? int(v) : int(v) + 1;}
|
||||
|
||||
/*! \brief Templated function return absolute of numeric falue
|
||||
* \details Absolute is the positive or equal 0 value \n
|
||||
@@ -382,7 +392,7 @@ template<typename T> inline int piCeil(const T & v) {return v < T(0) ? int(v) :
|
||||
*
|
||||
* Example:
|
||||
* \snippet piincludes.cpp abs */
|
||||
template<typename T> inline T piAbs(const T & v) {return (v >= T(0) ? v : -v);}
|
||||
template<typename T> inline constexpr T piAbs(const T & v) {return (v >= T(0) ? v : -v);}
|
||||
|
||||
/*! \brief Templated function return minimum of two values
|
||||
* \details There are some macros:
|
||||
@@ -395,7 +405,7 @@ template<typename T> inline T piAbs(const T & v) {return (v >= T(0) ? v : -v);}
|
||||
*
|
||||
* Example:
|
||||
* \snippet piincludes.cpp min2 */
|
||||
template<typename T> inline T piMin(const T & f, const T & s) {return ((f > s) ? s : f);}
|
||||
template<typename T> inline constexpr T piMin(const T & f, const T & s) {return ((f > s) ? s : f);}
|
||||
|
||||
/*! \brief Templated function return minimum of tree values
|
||||
* \details There are some macros:
|
||||
@@ -408,7 +418,7 @@ template<typename T> inline T piMin(const T & f, const T & s) {return ((f > s) ?
|
||||
*
|
||||
* Example:
|
||||
* \snippet piincludes.cpp min3 */
|
||||
template<typename T> inline T piMin(const T & f, const T & s, const T & t) {return ((f < s && f < t) ? f : ((s < t) ? s : t));}
|
||||
template<typename T> inline constexpr T piMin(const T & f, const T & s, const T & t) {return ((f < s && f < t) ? f : ((s < t) ? s : t));}
|
||||
|
||||
/*! \brief Templated function return maximum of two values
|
||||
* \details There are some macros:
|
||||
@@ -421,7 +431,7 @@ template<typename T> inline T piMin(const T & f, const T & s, const T & t) {retu
|
||||
*
|
||||
* Example:
|
||||
* \snippet piincludes.cpp max2 */
|
||||
template<typename T> inline T piMax(const T & f, const T & s) {return ((f < s) ? s : f);}
|
||||
template<typename T> inline constexpr T piMax(const T & f, const T & s) {return ((f < s) ? s : f);}
|
||||
|
||||
/*! \brief Templated function return maximum of tree values
|
||||
* \details There are some macros:
|
||||
@@ -434,7 +444,7 @@ template<typename T> inline T piMax(const T & f, const T & s) {return ((f < s) ?
|
||||
*
|
||||
* Example:
|
||||
* \snippet piincludes.cpp max3 */
|
||||
template<typename T> inline T piMax(const T & f, const T & s, const T & t) {return ((f > s && f > t) ? f : ((s > t) ? s : t));}
|
||||
template<typename T> inline constexpr T piMax(const T & f, const T & s, const T & t) {return ((f > s && f > t) ? f : ((s > t) ? s : t));}
|
||||
|
||||
/*! \brief Templated function return clamped value
|
||||
* \details Clamped is the not greater than "max" and not lesser than "min" value \n
|
||||
@@ -448,7 +458,7 @@ template<typename T> inline T piMax(const T & f, const T & s, const T & t) {retu
|
||||
*
|
||||
* Example:
|
||||
* \snippet piincludes.cpp clamp */
|
||||
template<typename T> inline T piClamp(const T & v, const T & min, const T & max) {return (v > max ? max : (v < min ? min : v));}
|
||||
template<typename T> inline constexpr T piClamp(const T & v, const T & min, const T & max) {return (v > max ? max : (v < min ? min : v));}
|
||||
|
||||
/// Function inverse byte order in memory block
|
||||
inline void piLetobe(void * data, int size) {
|
||||
|
||||
@@ -401,3 +401,14 @@ PIByteArray & operator >>(PIByteArray & s, PIByteArray & v) {
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
PIByteArray & operator <<(PIByteArray & s, const PIByteArray & v) {
|
||||
s << int(v.size_s());
|
||||
int os = s.size_s();
|
||||
if (v.size_s() > 0) {
|
||||
s.enlarge(v.size_s());
|
||||
memcpy(s.data(os), v.data(), v.size());
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -28,23 +28,6 @@
|
||||
#include "pimap.h"
|
||||
#include "pivector2d.h"
|
||||
|
||||
__PICONTAINERS_SIMPLE_TYPE__(PIChar)
|
||||
|
||||
#define __PIBYTEARRAY_SIMPLE_TYPE__(T) \
|
||||
template<> \
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIVector<T> & v) {s << int(v.size_s()); int os = s.size_s(); s.enlarge(v.size_s()*sizeof(T)); memcpy(s.data(os), v.data(), v.size_s()*sizeof(T)); return s;} \
|
||||
template<> \
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIVector<T> & v) {assert(s.size_s() >= 4); int sz; s >> sz; v._resizeRaw(sz); if (sz > 0) memcpy(v.data(), s.data(), sz*sizeof(T)); s.remove(0, sz*sizeof(T)); return s;} \
|
||||
template<> \
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIDeque<T> & v) {s << int(v.size_s()); int os = s.size_s(); s.enlarge(v.size_s()*sizeof(T)); memcpy(s.data(os), v.data(), v.size_s()*sizeof(T)); return s;} \
|
||||
template<> \
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIDeque<T> & v) {assert(s.size_s() >= 4); int sz; s >> sz; v._resizeRaw(sz); if (sz > 0) memcpy(v.data(), s.data(), sz*sizeof(T)); s.remove(0, sz*sizeof(T)); return s;} \
|
||||
template<> \
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIVector2D<T> & v) {s << int(v.rows()) << int(v.cols()); int os = s.size_s(); s.enlarge(v.size_s()*sizeof(T)); memcpy(s.data(os), v.data(), v.size_s()*sizeof(T)); return s;} \
|
||||
template<> \
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIVector2D<T> & v) {assert(s.size_s() >= 8); int r, c; s >> r >> c; v._resizeRaw(r, c); int sz = r*c; if (sz > 0) memcpy(v.data(), s.data(), sz*sizeof(T)); s.remove(0, sz*sizeof(T)); return s;}
|
||||
|
||||
|
||||
class PIString;
|
||||
class PIByteArray;
|
||||
|
||||
@@ -136,9 +119,48 @@ public:
|
||||
static PIByteArray fromHex(PIString str);
|
||||
static PIByteArray fromBase64(const PIByteArray & base64);
|
||||
static PIByteArray fromBase64(const PIString & base64);
|
||||
|
||||
|
||||
class StreamRef {
|
||||
public:
|
||||
StreamRef(PIByteArray & s): ba(s) {}
|
||||
operator PIByteArray&() {return ba;}
|
||||
private:
|
||||
PIByteArray & ba;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
inline bool operator <(const PIByteArray & v0, const PIByteArray & v1) {if (v0.size() == v1.size()) {for (uint i = 0; i < v0.size(); ++i) if (v0[i] != v1[i]) return v0[i] < v1[i]; return false;} return v0.size() < v1.size();}
|
||||
//! \relatesalso PIByteArray \brief Byte arrays compare operator
|
||||
inline bool operator <(const PIByteArray & v0, const PIByteArray & v1) {
|
||||
if (v0.size() == v1.size()) {
|
||||
for (uint i = 0; i < v0.size(); ++i)
|
||||
if (v0[i] != v1[i])
|
||||
return v0[i] < v1[i];
|
||||
return false;
|
||||
}
|
||||
return v0.size() < v1.size();
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray \brief Byte arrays compare operator
|
||||
inline bool operator ==(PIByteArray & f, PIByteArray & s) {
|
||||
if (f.size_s() != s.size_s())
|
||||
return false;
|
||||
for (int i = 0; i < f.size_s(); ++i)
|
||||
if (f[i] != s[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray \brief Byte arrays compare operator
|
||||
inline bool operator !=(PIByteArray & f, PIByteArray & s) {
|
||||
if (f.size_s() != s.size_s())
|
||||
return true;
|
||||
for (int i = 0; i < f.size_s(); ++i)
|
||||
if (f[i] != s[i])
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef PIP_STD_IOSTREAM
|
||||
//! \relatesalso PIByteArray \brief Output to std::ostream operator
|
||||
@@ -148,114 +170,308 @@ inline std::ostream & operator <<(std::ostream & s, const PIByteArray & ba);
|
||||
//! \relatesalso PIByteArray \brief Output to PICout operator
|
||||
PIP_EXPORT PICout operator <<(PICout s, const PIByteArray & ba);
|
||||
|
||||
#define PBA_OPERATOR_TO int os = s.size_s(); s.enlarge(sizeof(v)); memcpy(s.data(os), &v, sizeof(v));
|
||||
|
||||
|
||||
|
||||
// store operators for basic types
|
||||
|
||||
|
||||
//! \relatesalso PIByteArray \brief Store operator
|
||||
inline PIByteArray & operator <<(PIByteArray & s, bool v) {s.push_back(v); return s;}
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const bool v) {s.push_back(v); return s;}
|
||||
|
||||
//! \relatesalso PIByteArray \brief Store operator
|
||||
inline PIByteArray & operator <<(PIByteArray & s, char v) {s.push_back(v); return s;}
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const char v) {s.push_back(v); return s;}
|
||||
|
||||
//! \relatesalso PIByteArray \brief Store operator
|
||||
inline PIByteArray & operator <<(PIByteArray & s, uchar v) {s.push_back(v); return s;}
|
||||
//! \relatesalso PIByteArray \brief Store operator
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const short v) {PBA_OPERATOR_TO return s;}
|
||||
//! \relatesalso PIByteArray \brief Store operator
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const int v) {PBA_OPERATOR_TO return s;}
|
||||
//! \relatesalso PIByteArray \brief Store operator
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const long & v) {PBA_OPERATOR_TO return s;}
|
||||
//! \relatesalso PIByteArray \brief Store operator
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const llong & v) {PBA_OPERATOR_TO return s;}
|
||||
//! \relatesalso PIByteArray \brief Store operator
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const ushort v) {PBA_OPERATOR_TO return s;}
|
||||
//! \relatesalso PIByteArray \brief Store operator
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const uint v) {PBA_OPERATOR_TO return s;}
|
||||
//! \relatesalso PIByteArray \brief Store operator
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const ulong & v) {PBA_OPERATOR_TO return s;}
|
||||
//! \relatesalso PIByteArray \brief Store operator
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const ullong & v) {PBA_OPERATOR_TO return s;}
|
||||
//! \relatesalso PIByteArray \brief Store operator
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const float v) {PBA_OPERATOR_TO return s;}
|
||||
//! \relatesalso PIByteArray \brief Store operator
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const double & v) {PBA_OPERATOR_TO return s;}
|
||||
//! \relatesalso PIByteArray \brief Store operator
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const ldouble & v) {PBA_OPERATOR_TO return s;}
|
||||
//! \relatesalso PIByteArray \brief Store operator
|
||||
template<typename T> inline PIByteArray & operator <<(PIByteArray & s, const PIFlags<T> & v) {PBA_OPERATOR_TO return s;}
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const uchar v) {s.push_back(v); return s;}
|
||||
|
||||
//! \relatesalso PIByteArray \brief Store operator for any trivial copyable type
|
||||
template<typename T, typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0>
|
||||
inline PIByteArray::StreamRef operator <<(PIByteArray & s, const T & v) {
|
||||
int os = s.size_s();
|
||||
s.enlarge(sizeof(v));
|
||||
memcpy(s.data(os), &v, sizeof(v));
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray \brief Store operator, see \ref PIByteArray_sec1 for details
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIByteArray & v) {s << int(v.size_s()); int os = s.size_s(); s.enlarge(v.size_s()); if (v.size_s() > 0) memcpy(s.data(os), v.data(), v.size()); return s;}
|
||||
PIP_EXPORT PIByteArray & operator <<(PIByteArray & s, const PIByteArray & v);
|
||||
|
||||
//! \relatesalso PIByteArray \brief Store operator, see \ref PIByteArray_sec1 for details
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIByteArray::RawData & v) {int os = s.size_s(); s.enlarge(v.s); if (v.s > 0) memcpy(s.data(os), v.d, v.s); return s;}
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIByteArray::RawData & v) {
|
||||
int os = s.size_s();
|
||||
if (v.s > 0) {
|
||||
s.enlarge(v.s);
|
||||
memcpy(s.data(os), v.d, v.s);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
#undef PBA_OPERATOR_TO
|
||||
#define PBA_OPERATOR_FROM memcpy((void*)(&v), s.data(), sizeof(v)); s.remove(0, sizeof(v));
|
||||
//! \relatesalso PIByteArray \brief Store operator for PIVector of any trivial copyable type
|
||||
template<typename T,
|
||||
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||
typename std::enable_if< std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIVector<T> & v) {
|
||||
s << int(v.size_s());
|
||||
int os = s.size_s();
|
||||
if (v.size_s() > 0) {
|
||||
s.enlarge(v.size_s()*sizeof(T));
|
||||
memcpy(s.data(os), v.data(), v.size_s()*sizeof(T));
|
||||
}
|
||||
return s;
|
||||
}
|
||||
template<typename T,
|
||||
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||
typename std::enable_if<!std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIVector<T> & v) {
|
||||
s << int(v.size_s());
|
||||
for (uint i = 0; i < v.size(); ++i) s << v[i];
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray \brief Restore operator
|
||||
inline PIByteArray & operator >>(PIByteArray & s, bool & v) {assert(s.size() >= 1u); v = s.take_front(); return s;}
|
||||
//! \relatesalso PIByteArray \brief Restore operator
|
||||
inline PIByteArray & operator >>(PIByteArray & s, char & v) {assert(s.size() >= 1u); v = s.take_front(); return s;}
|
||||
//! \relatesalso PIByteArray \brief Restore operator
|
||||
inline PIByteArray & operator >>(PIByteArray & s, uchar & v) {assert(s.size() >= 1u); v = s.take_front(); return s;}
|
||||
//! \relatesalso PIByteArray \brief Restore operator
|
||||
inline PIByteArray & operator >>(PIByteArray & s, short & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
|
||||
//! \relatesalso PIByteArray \brief Restore operator
|
||||
inline PIByteArray & operator >>(PIByteArray & s, int & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
|
||||
//! \relatesalso PIByteArray \brief Restore operator
|
||||
inline PIByteArray & operator >>(PIByteArray & s, long & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
|
||||
//! \relatesalso PIByteArray \brief Restore operator
|
||||
inline PIByteArray & operator >>(PIByteArray & s, llong & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
|
||||
//! \relatesalso PIByteArray \brief Restore operator
|
||||
inline PIByteArray & operator >>(PIByteArray & s, ushort & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
|
||||
//! \relatesalso PIByteArray \brief Restore operator
|
||||
inline PIByteArray & operator >>(PIByteArray & s, uint & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
|
||||
//! \relatesalso PIByteArray \brief Restore operator
|
||||
inline PIByteArray & operator >>(PIByteArray & s, ulong & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
|
||||
//! \relatesalso PIByteArray \brief Restore operator
|
||||
inline PIByteArray & operator >>(PIByteArray & s, ullong & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
|
||||
//! \relatesalso PIByteArray \brief Restore operator
|
||||
inline PIByteArray & operator >>(PIByteArray & s, float & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
|
||||
//! \relatesalso PIByteArray \brief Restore operator
|
||||
inline PIByteArray & operator >>(PIByteArray & s, double & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
|
||||
//! \relatesalso PIByteArray \brief Restore operator
|
||||
inline PIByteArray & operator >>(PIByteArray & s, ldouble & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
|
||||
//! \relatesalso PIByteArray \brief Restore operator
|
||||
template<typename T> inline PIByteArray & operator >>(PIByteArray & s, PIFlags<T> & v) {PBA_OPERATOR_FROM return s;}
|
||||
//! \relatesalso PIByteArray \brief Restore operator, see \ref PIByteArray_sec1 for details
|
||||
PIP_EXPORT PIByteArray & operator >>(PIByteArray & s, PIByteArray & v);
|
||||
//! \relatesalso PIByteArray \brief Restore operator, see \ref PIByteArray_sec1 for details
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIByteArray::RawData v) {assert(s.size_s() >= v.s); if (v.s > 0) memcpy((void*)(v.d), s.data(), v.s); s.remove(0, v.s); return s;}
|
||||
|
||||
#undef PBA_OPERATOR_FROM
|
||||
|
||||
template<typename Type0, typename Type1> inline PIByteArray & operator <<(PIByteArray & s, const PIPair<Type0, Type1> & v);
|
||||
//! \relatesalso PIByteArray \brief Store operator
|
||||
template<typename T> inline PIByteArray & operator <<(PIByteArray & s, const PIVector<T> & v);
|
||||
//! \relatesalso PIByteArray \brief Store operator
|
||||
template<typename T> inline PIByteArray & operator <<(PIByteArray & s, const PIDeque<T> & v);
|
||||
//! \relatesalso PIByteArray \brief Store operator
|
||||
template <typename Key, typename T> inline PIByteArray & operator <<(PIByteArray & s, const PIMap<Key, T> & v);
|
||||
//! Write operator to \c PIByteArray
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIChar & v) {s << v.ch; return s;}
|
||||
|
||||
//! \relatesalso PIByteArray \brief Restore operator
|
||||
template<typename Type0, typename Type1> inline PIByteArray & operator >>(PIByteArray & s, PIPair<Type0, Type1> & v);
|
||||
//! \relatesalso PIByteArray \brief Restore operator
|
||||
template<typename T> inline PIByteArray & operator >>(PIByteArray & s, PIVector<T> & v);
|
||||
//! \relatesalso PIByteArray \brief Restore operator
|
||||
template<typename T> inline PIByteArray & operator >>(PIByteArray & s, PIDeque<T> & v);
|
||||
//! \relatesalso PIByteArray \brief Restore operator
|
||||
template <typename Key, typename T> inline PIByteArray & operator >>(PIByteArray & s, PIMap<Key, T> & v);
|
||||
//! Read operator from \c PIByteArray
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIChar & v) {s >> v.ch; return s;}
|
||||
//! \relatesalso PIByteArray \brief Store operator for PIDeque of any trivial copyable type
|
||||
template<typename T,
|
||||
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||
typename std::enable_if< std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIDeque<T> & v) {
|
||||
s << int(v.size_s());
|
||||
int os = s.size_s();
|
||||
if (v.size_s() > 0) {
|
||||
s.enlarge(v.size_s()*sizeof(T));
|
||||
memcpy(s.data(os), v.data(), v.size_s()*sizeof(T));
|
||||
}
|
||||
return s;
|
||||
}
|
||||
template<typename T,
|
||||
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||
typename std::enable_if<!std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIDeque<T> & v) {
|
||||
s << int(v.size_s());
|
||||
for (uint i = 0; i < v.size(); ++i) s << v[i];
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray \brief Store operator for PIVector2D of any trivial copyable type
|
||||
template<typename T,
|
||||
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||
typename std::enable_if< std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIVector2D<T> & v) {
|
||||
s << int(v.rows()) << int(v.cols());
|
||||
int os = s.size_s();
|
||||
if (v.size_s() > 0) {
|
||||
s.enlarge(v.size_s()*sizeof(T));
|
||||
memcpy(s.data(os), v.data(), v.size_s()*sizeof(T));
|
||||
}
|
||||
return s;
|
||||
}
|
||||
template<typename T,
|
||||
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||
typename std::enable_if<!std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIVector2D<T> & v) {
|
||||
s << int(v.rows()) << int(v.cols()) << v.toPlainVector();
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray \brief Store operator
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIBitArray & v) {s << v.size_ << v.data_; return s;}
|
||||
|
||||
//! \relatesalso PIPair \brief Store operator
|
||||
template<typename Type0, typename Type1>
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIPair<Type0, Type1> & v) {s << v.first << v.second; return s;}
|
||||
template<typename T>
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIVector<T> & v) {s << int(v.size_s()); for (uint i = 0; i < v.size(); ++i) s << v[i]; return s;}
|
||||
template<typename T>
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIDeque<T> & v) {s << int(v.size_s()); for (uint i = 0; i < v.size(); ++i) s << v[i]; return s;}
|
||||
|
||||
|
||||
|
||||
|
||||
// restore operators for basic types
|
||||
|
||||
|
||||
//! \relatesalso PIByteArray \brief Restore operator
|
||||
inline PIByteArray & operator >>(PIByteArray & s, bool & v) {assert(s.size() >= 1u); v = s.take_front(); return s;}
|
||||
|
||||
//! \relatesalso PIByteArray \brief Restore operator
|
||||
inline PIByteArray & operator >>(PIByteArray & s, char & v) {assert(s.size() >= 1u); v = s.take_front(); return s;}
|
||||
|
||||
//! \relatesalso PIByteArray \brief Restore operator
|
||||
inline PIByteArray & operator >>(PIByteArray & s, uchar & v) {assert(s.size() >= 1u); v = s.take_front(); return s;}
|
||||
|
||||
//! \relatesalso PIByteArray \brief Restore operator for any trivial copyable type
|
||||
template<typename T, typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0>
|
||||
inline PIByteArray::StreamRef operator >>(PIByteArray & s, T & v) {
|
||||
assert(s.size() >= sizeof(v));
|
||||
memcpy((void*)(&v), s.data(), sizeof(v));
|
||||
s.remove(0, sizeof(v));
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray \brief Restore operator, see \ref PIByteArray_sec1 for details
|
||||
PIP_EXPORT PIByteArray & operator >>(PIByteArray & s, PIByteArray & v);
|
||||
|
||||
//! \relatesalso PIByteArray \brief Restore operator, see \ref PIByteArray_sec1 for details
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIByteArray::RawData v) {
|
||||
assert(s.size_s() >= v.s);
|
||||
if (v.s > 0) {
|
||||
memcpy((void*)(v.d), s.data(), v.s);
|
||||
s.remove(0, v.s);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray \brief Restore operator for PIVector of any trivial copyable type
|
||||
template<typename T,
|
||||
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||
typename std::enable_if< std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIVector<T> & v) {
|
||||
assert(s.size_s() >= 4);
|
||||
int sz; s >> sz;
|
||||
v._resizeRaw(sz);
|
||||
if (sz > 0) {
|
||||
memcpy(v.data(), s.data(), sz*sizeof(T));
|
||||
s.remove(0, sz*sizeof(T));
|
||||
}
|
||||
return s;
|
||||
}
|
||||
template<typename T,
|
||||
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||
typename std::enable_if<!std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIVector<T> & v) {
|
||||
assert(s.size_s() >= 4);
|
||||
int sz; s >> sz;
|
||||
v.resize(sz);
|
||||
for (int i = 0; i < sz; ++i) s >> v[i];
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray \brief Restore operator for PIDeque of any trivial copyable type
|
||||
template<typename T,
|
||||
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||
typename std::enable_if< std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIDeque<T> & v) {
|
||||
assert(s.size_s() >= 4);
|
||||
int sz; s >> sz;
|
||||
v._resizeRaw(sz);
|
||||
if (sz > 0) {
|
||||
memcpy(v.data(), s.data(), sz*sizeof(T));
|
||||
s.remove(0, sz*sizeof(T));
|
||||
}
|
||||
return s;
|
||||
}
|
||||
template<typename T,
|
||||
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||
typename std::enable_if<!std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIDeque<T> & v) {
|
||||
assert(s.size_s() >= 4);
|
||||
int sz; s >> sz;
|
||||
v.resize(sz);
|
||||
for (int i = 0; i < sz; ++i) s >> v[i];
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray \brief Restore operator for PIVector2D of any trivial copyable type
|
||||
template<typename T,
|
||||
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||
typename std::enable_if< std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIVector2D<T> & v) {
|
||||
assert(s.size_s() >= 8);
|
||||
int r, c; s >> r >> c;
|
||||
v._resizeRaw(r, c);
|
||||
int sz = r*c;
|
||||
if (sz > 0) {
|
||||
memcpy(v.data(), s.data(), sz*sizeof(T));
|
||||
s.remove(0, sz*sizeof(T));
|
||||
}
|
||||
return s;
|
||||
}
|
||||
template<typename T,
|
||||
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||
typename std::enable_if<!std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIVector2D<T> & v) {
|
||||
assert(s.size_s() >= 8);
|
||||
int r,c;
|
||||
PIVector<T> tmp;
|
||||
s >> r >> c >> tmp;
|
||||
v = PIVector2D<T>(r, c, tmp);
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray \brief Restore operator
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIBitArray & v) {assert(s.size_s() >= 8); s >> v.size_ >> v.data_; return s;}
|
||||
|
||||
//! \relatesalso PIPair \brief Restore operator
|
||||
template<typename Type0, typename Type1>
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIPair<Type0, Type1> & v) {s >> v.first >> v.second; return s;}
|
||||
|
||||
|
||||
|
||||
|
||||
// store operators for complex types
|
||||
|
||||
|
||||
//! \relatesalso PIByteArray \brief Store operator for PIVector of any compound type
|
||||
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIVector<T> & v) {
|
||||
s << int(v.size_s());
|
||||
for (uint i = 0; i < v.size(); ++i) s << v[i];
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray \brief Store operator for PIDeque of any compound type
|
||||
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIDeque<T> & v) {
|
||||
s << int(v.size_s());
|
||||
for (uint i = 0; i < v.size(); ++i) s << v[i];
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray \brief Store operator for PIVector2D of any compound type
|
||||
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIVector2D<T> & v) {
|
||||
s << int(v.rows()) << int(v.cols()) << v.toPlainVector();
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// restore operators for complex types
|
||||
|
||||
|
||||
//! \relatesalso PIByteArray \brief Restore operator for PIVector of any compound type
|
||||
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIVector<T> & v) {
|
||||
assert(s.size_s() >= 4);
|
||||
int sz; s >> sz;
|
||||
v.resize(sz);
|
||||
for (int i = 0; i < sz; ++i) s >> v[i];
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray \brief Restore operator for PIDeque of any compound type
|
||||
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIDeque<T> & v) {
|
||||
assert(s.size_s() >= 4);
|
||||
int sz; s >> sz;
|
||||
v.resize(sz);
|
||||
for (int i = 0; i < sz; ++i) s >> v[i];
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray \brief Restore operator for PIVector2D of any compound type
|
||||
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIVector2D<T> & v) {
|
||||
assert(s.size_s() >= 8);
|
||||
int r,c;
|
||||
PIVector<T> tmp;
|
||||
s >> r >> c >> tmp;
|
||||
v = PIVector2D<T>(r, c, tmp);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// other types
|
||||
|
||||
|
||||
template <typename Key, typename T>
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIMap<Key, T> & v) {
|
||||
s << int(v.pim_index.size_s());
|
||||
@@ -264,18 +480,8 @@ inline PIByteArray & operator <<(PIByteArray & s, const PIMap<Key, T> & v) {
|
||||
s << v.pim_content;
|
||||
return s;
|
||||
}
|
||||
template<typename T>
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIVector2D<T> & v) {s << int(v.rows()) << int(v.cols()) << v.toPlainVector(); return s;}
|
||||
|
||||
|
||||
//! \relatesalso PIByteArray \brief Restore operator
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIBitArray & v) {assert(s.size_s() >= 8); s >> v.size_ >> v.data_; return s;}
|
||||
template<typename Type0, typename Type1>
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIPair<Type0, Type1> & v) {s >> v.first >> v.second; return s;}
|
||||
template<typename T>
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIVector<T> & v) {assert(s.size_s() >= 4); int sz; s >> sz; v.resize(sz); for (int i = 0; i < sz; ++i) s >> v[i]; return s;}
|
||||
template<typename T>
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIDeque<T> & v) {assert(s.size_s() >= 4); int sz; s >> sz; v.resize(sz); for (int i = 0; i < sz; ++i) s >> v[i]; return s;}
|
||||
template <typename Key, typename T>
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIMap<Key, T> & v) {
|
||||
assert(s.size_s() >= 4);
|
||||
@@ -292,36 +498,20 @@ inline PIByteArray & operator >>(PIByteArray & s, PIMap<Key, T> & v) {
|
||||
}
|
||||
return s;
|
||||
}
|
||||
template<typename T>
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIVector2D<T> & v) {assert(s.size_s() >= 8); int r,c; PIVector<T> tmp; s >> r >> c >> tmp; v = PIVector2D<T>(r, c, tmp); return s;}
|
||||
|
||||
|
||||
template<typename T>
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const T & ) {piCout << "[PIByteArray] Warning: using undeclared operator <<!"; return s;}
|
||||
template<typename T>
|
||||
inline PIByteArray & operator >>(PIByteArray & s, T & ) {piCout << "[PIByteArray] Warning: using undeclared operator >>!"; return s;}
|
||||
|
||||
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const T & ) {
|
||||
static_assert(std::is_trivially_copyable<T>::value, "[PIByteArray] Error: using undeclared operator << for complex type!");
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray \brief Byte arrays compare operator
|
||||
inline bool operator ==(PIByteArray & f, PIByteArray & s) {if (f.size_s() != s.size_s()) return false; for (int i = 0; i < f.size_s(); ++i) if (f[i] != s[i]) return false; return true;}
|
||||
//! \relatesalso PIByteArray \brief Byte arrays compare operator
|
||||
inline bool operator !=(PIByteArray & f, PIByteArray & s) {if (f.size_s() != s.size_s()) return true; for (int i = 0; i < f.size_s(); ++i) if (f[i] != s[i]) return true; return false;}
|
||||
|
||||
__PIBYTEARRAY_SIMPLE_TYPE__(bool)
|
||||
__PIBYTEARRAY_SIMPLE_TYPE__(char)
|
||||
__PIBYTEARRAY_SIMPLE_TYPE__(short)
|
||||
__PIBYTEARRAY_SIMPLE_TYPE__(ushort)
|
||||
__PIBYTEARRAY_SIMPLE_TYPE__(int)
|
||||
__PIBYTEARRAY_SIMPLE_TYPE__(uint)
|
||||
__PIBYTEARRAY_SIMPLE_TYPE__(long)
|
||||
__PIBYTEARRAY_SIMPLE_TYPE__(ulong)
|
||||
__PIBYTEARRAY_SIMPLE_TYPE__(llong)
|
||||
__PIBYTEARRAY_SIMPLE_TYPE__(ullong)
|
||||
__PIBYTEARRAY_SIMPLE_TYPE__(float)
|
||||
__PIBYTEARRAY_SIMPLE_TYPE__(double)
|
||||
__PIBYTEARRAY_SIMPLE_TYPE__(ldouble)
|
||||
__PIBYTEARRAY_SIMPLE_TYPE__(PIChar)
|
||||
|
||||
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
|
||||
inline PIByteArray & operator >>(PIByteArray & s, T & ) {
|
||||
static_assert(std::is_trivially_copyable<T>::value, "[PIByteArray] Error: using undeclared operator >> for complex type!");
|
||||
return s;
|
||||
}
|
||||
|
||||
template<> inline uint piHash(const PIByteArray & ba) {return ba.hash();}
|
||||
template<> inline void piSwap(PIByteArray & f, PIByteArray & s) {f.swap(s);}
|
||||
|
||||
@@ -32,9 +32,7 @@ extern PIP_EXPORT char * __utf8name__;
|
||||
class PIP_EXPORT PIChar
|
||||
{
|
||||
friend class PIString;
|
||||
friend PIByteArray & operator <<(PIByteArray & s, const PIChar & v);
|
||||
friend PIByteArray & operator >>(PIByteArray & s, PIChar & v);
|
||||
friend PICout operator <<(PICout s, const PIChar & v);
|
||||
friend PICout PIP_EXPORT operator <<(PICout s, const PIChar & v);
|
||||
public:
|
||||
//! Contructs ascii symbol
|
||||
PIChar(const char c) {ch = c; ch &= 0xFF;}
|
||||
@@ -135,7 +133,7 @@ private:
|
||||
};
|
||||
|
||||
//! Output operator to \a PICout
|
||||
PICout operator <<(PICout s, const PIChar & v);
|
||||
PICout PIP_EXPORT operator <<(PICout s, const PIChar & v);
|
||||
|
||||
//! Compare operator
|
||||
inline bool operator ==(const char v, const PIChar & c) {return (PIChar(v) == c);}
|
||||
|
||||
@@ -41,13 +41,22 @@
|
||||
* but you should definitely know type of this value. You can read from byte array
|
||||
* while \a atEnd() if false.
|
||||
*
|
||||
* \section PIChunkStream_ex0 Example
|
||||
* Prepare your structs to work with %PIChunkStream
|
||||
* \section PIChunkStream_sec2 Examples
|
||||
*
|
||||
* Using simple operator and cascade serialization:
|
||||
*
|
||||
* Prepare your structs to work with %PIChunkStream:
|
||||
* \snippet pichunkstream.cpp struct
|
||||
* Writing to %PIChunkStream
|
||||
* Old-style writing to %PIChunkStream:
|
||||
* \snippet pichunkstream.cpp write
|
||||
* Reading from %PIChunkStream
|
||||
* Fastest reading from %PIChunkStream:
|
||||
* \snippet pichunkstream.cpp read
|
||||
*
|
||||
* And next code show how to serialize your struct with %PIChunkStream:
|
||||
* \snippet pichunkstream.cpp write_new
|
||||
*
|
||||
* ... and deserialize:
|
||||
* \snippet pichunkstream.cpp read_new
|
||||
*/
|
||||
|
||||
|
||||
@@ -115,7 +124,18 @@ void PIChunkStream::readAll() {
|
||||
|
||||
|
||||
PIChunkStream::~PIChunkStream() {
|
||||
}
|
||||
|
||||
|
||||
bool PIChunkStream::extract(PIByteArray & data, bool read_all) {
|
||||
if (data.size_s() < 4) return false;
|
||||
data >> tmp_data;
|
||||
if (tmp_data.size_s() < 4) return false;
|
||||
data_ = &tmp_data;
|
||||
_init();
|
||||
if (read_all)
|
||||
readAll();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -67,6 +67,11 @@ public:
|
||||
//! Add data to this chunk strean with ID "id" and value "data"
|
||||
template <typename T> PIChunkStream & add(int id, const T & data) {*this << ChunkConst<T>(id, data); return *this;}
|
||||
|
||||
//! Extract %PIByteArray from "data" and set it current stream.
|
||||
//! If "read_all" then call \a readAll() after extract.
|
||||
//! Returns if has data to read.
|
||||
bool extract(PIByteArray & data, bool read_all = false);
|
||||
|
||||
void setSource(const PIByteArray & data);
|
||||
void setSource(PIByteArray * data);
|
||||
|
||||
|
||||
@@ -38,8 +38,6 @@ public:
|
||||
PIFlags(): flags(0) {;}
|
||||
//! Constructor with flags = Enum "e"
|
||||
PIFlags(Enum e): flags(e) {;}
|
||||
//! Constructor with flags = PIFlags "f"
|
||||
PIFlags(const PIFlags & f): flags(f.flags) {;}
|
||||
//! Constructor with flags = int "i"
|
||||
PIFlags(const int i): flags(i) {;}
|
||||
//! Set flags "f" to value "on"
|
||||
@@ -49,8 +47,6 @@ public:
|
||||
//! Set flag "i" to value "on"
|
||||
PIFlags & setFlag(const int & i, bool on = true) {if (on) flags |= i; else flags &= ~i; return *this;}
|
||||
//! copy operator
|
||||
void operator =(const PIFlags & f) {flags = f.flags;}
|
||||
//! copy operator
|
||||
void operator =(const Enum & e) {flags = e;}
|
||||
//! copy operator
|
||||
void operator =(const int & i) {flags = i;}
|
||||
|
||||
@@ -79,6 +79,22 @@ PIString PIPVersion() {
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void piqsort(void * base, size_t num, size_t size, int (*compar)(const void *, const void *)) {
|
||||
qsort(base, num, size, compar);
|
||||
}
|
||||
|
||||
|
||||
void randomize() {
|
||||
srand(PISystemTime::current(true).nanoseconds);
|
||||
}
|
||||
|
||||
|
||||
int randomi() {
|
||||
return rand();
|
||||
}
|
||||
|
||||
|
||||
/*! \class PICout
|
||||
* \brief Class for formatted output similar std::cout
|
||||
*
|
||||
@@ -131,6 +147,9 @@ PIString PIPVersion() {
|
||||
* * packets extractor (\a PIPacketExtractor)
|
||||
* * binary log (\a PIBinaryLog)
|
||||
* * complex I/O point (\a PIConnection)
|
||||
* * Run-time libraries
|
||||
* * abstract (\a PILibrary)
|
||||
* * plugin (\a PIPluginLoader)
|
||||
* * connection quality diagnotic (\a PIDiagnostics)
|
||||
* * command-line arguments parser (\a PICLI)
|
||||
* * math evaluator (\a PIEvaluator)
|
||||
@@ -247,19 +266,3 @@ int main(int argc, char * argv[]) {
|
||||
/*! \page using_advanced Advanced using
|
||||
* Sorry, creativity crysis xD
|
||||
*/
|
||||
|
||||
|
||||
void piqsort(void * base, size_t num, size_t size, int (*compar)(const void *, const void *)) {
|
||||
qsort(base, num, size, compar);
|
||||
}
|
||||
|
||||
|
||||
void randomize() {
|
||||
srand(PISystemTime::current(true).nanoseconds);
|
||||
}
|
||||
|
||||
|
||||
int randomi() {
|
||||
return rand();
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#endif
|
||||
#include <atomic>
|
||||
|
||||
|
||||
class PIMutex;
|
||||
class PIMutexLocker;
|
||||
class PIObject;
|
||||
|
||||
@@ -282,7 +282,7 @@ PIInit::PIInit() {
|
||||
|
||||
|
||||
PIInit::~PIInit() {
|
||||
if (file_charset) delete file_charset;
|
||||
if (file_charset) delete[] file_charset;
|
||||
file_charset = 0;
|
||||
PIResourcesStorage::instance()->clear();
|
||||
#ifdef WINDOWS
|
||||
|
||||
@@ -105,7 +105,7 @@ PIMap<PIString, PIVariant> PIObject::properties() const {
|
||||
|
||||
|
||||
|
||||
bool PIObject::execute(const PIString & method, const PIVector<PIVariant> & vl) {
|
||||
bool PIObject::execute(const PIString & method, const PIVector<PIVariantSimple> & vl) {
|
||||
if (method.isEmpty()) return false;
|
||||
if (!isPIObject()) {
|
||||
piCout << "Error: \"execute(" << method << ")\":" << (void*)this << "is not PIObject!";
|
||||
@@ -121,7 +121,7 @@ bool PIObject::execute(const PIString & method, const PIVector<PIVariant> & vl)
|
||||
}
|
||||
|
||||
|
||||
bool PIObject::executeQueued(PIObject * performer, const PIString & method, const PIVector<PIVariant> & vl) {
|
||||
bool PIObject::executeQueued(PIObject * performer, const PIString & method, const PIVector<PIVariantSimple> & vl) {
|
||||
if (!isPIObject()) {
|
||||
piCout << "Error: \"executeQueued(" << method << ")\": this(" << (void*)this << ") is not PIObject!";
|
||||
return false;
|
||||
@@ -535,14 +535,14 @@ PIMutex & PIObject::mutexObjects() {
|
||||
}
|
||||
|
||||
|
||||
void PIObject::callAddrV(void * slot, void * obj, int args, const PIVector<PIVariant> & vl) {
|
||||
void PIObject::callAddrV(void * slot, void * obj, int args, const PIVector<PIVariantSimple> & vl) {
|
||||
args = piMini(args, vl.size_s());
|
||||
switch (args) {
|
||||
case 0: ((void(*)(void *))slot)(obj); break;
|
||||
case 1: ((void(*)(void * , const PIVariant & ))slot)(obj, vl[0]); break;
|
||||
case 2: ((void(*)(void * , const PIVariant & , const PIVariant & ))slot)(obj, vl[0], vl[1]); break;
|
||||
case 3: ((void(*)(void * , const PIVariant & , const PIVariant & , const PIVariant & ))slot)(obj, vl[0], vl[1], vl[2]); break;
|
||||
case 4: ((void(*)(void * , const PIVariant & , const PIVariant & , const PIVariant & , const PIVariant & ))slot)(obj, vl[0], vl[1], vl[2], vl[3]); break;
|
||||
case 1: ((void(*)(void * , const PIVariantSimple & ))slot)(obj, vl[0]); break;
|
||||
case 2: ((void(*)(void * , const PIVariantSimple & , const PIVariantSimple & ))slot)(obj, vl[0], vl[1]); break;
|
||||
case 3: ((void(*)(void * , const PIVariantSimple & , const PIVariantSimple & , const PIVariantSimple & ))slot)(obj, vl[0], vl[1], vl[2]); break;
|
||||
case 4: ((void(*)(void * , const PIVariantSimple & , const PIVariantSimple & , const PIVariantSimple & , const PIVariantSimple & ))slot)(obj, vl[0], vl[1], vl[2], vl[3]); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*! \file piobject.h
|
||||
* \brief Base object
|
||||
*
|
||||
* This file declare PIObject class and associated macros
|
||||
* This file declare PIObject class
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
#include "piinit.h"
|
||||
#include "pivariant.h"
|
||||
#include "pivariantsimple.h"
|
||||
#include "pimutex.h"
|
||||
#include "piset.h"
|
||||
#include "piqueue.h"
|
||||
@@ -101,33 +102,33 @@ public:
|
||||
void setThreadSafe(bool yes) {thread_safe_ = yes;}
|
||||
bool isThreadSafe() const {return thread_safe_;}
|
||||
|
||||
bool execute(const PIString & method, const PIVector<PIVariant> & vl);
|
||||
bool execute(const PIString & method) {return execute(method, PIVector<PIVariant>());}
|
||||
bool execute(const PIString & method, const PIVariant & v0) {return execute(method, PIVector<PIVariant>() << v0);}
|
||||
bool execute(const PIString & method, const PIVariant & v0, const PIVariant & v1) {return execute(method, PIVector<PIVariant>() << v0 << v1);}
|
||||
bool execute(const PIString & method, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2) {return execute(method, PIVector<PIVariant>() << v0 << v1 << v2);}
|
||||
bool execute(const PIString & method, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2, const PIVariant & v3) {return execute(method, PIVector<PIVariant>() << v0 << v1 << v2 << v3);}
|
||||
bool execute(const PIString & method, const PIVector<PIVariantSimple> & vl);
|
||||
bool execute(const PIString & method) {return execute(method, PIVector<PIVariantSimple>());}
|
||||
bool execute(const PIString & method, const PIVariantSimple & v0) {return execute(method, PIVector<PIVariantSimple>() << v0);}
|
||||
bool execute(const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1) {return execute(method, PIVector<PIVariantSimple>() << v0 << v1);}
|
||||
bool execute(const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2) {return execute(method, PIVector<PIVariantSimple>() << v0 << v1 << v2);}
|
||||
bool execute(const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2, const PIVariantSimple & v3) {return execute(method, PIVector<PIVariantSimple>() << v0 << v1 << v2 << v3);}
|
||||
|
||||
bool executeQueued(PIObject * performer, const PIString & method, const PIVector<PIVariant> & vl);
|
||||
bool executeQueued(PIObject * performer, const PIString & method) {return executeQueued(performer, method, PIVector<PIVariant>());}
|
||||
bool executeQueued(PIObject * performer, const PIString & method, const PIVariant & v0) {return executeQueued(performer, method, PIVector<PIVariant>() << v0);}
|
||||
bool executeQueued(PIObject * performer, const PIString & method, const PIVariant & v0, const PIVariant & v1) {return executeQueued(performer, method, PIVector<PIVariant>() << v0 << v1);}
|
||||
bool executeQueued(PIObject * performer, const PIString & method, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2) {return executeQueued(performer, method, PIVector<PIVariant>() << v0 << v1 << v2);}
|
||||
bool executeQueued(PIObject * performer, const PIString & method, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2, const PIVariant & v3) {return executeQueued(performer, method, PIVector<PIVariant>() << v0 << v1 << v2 << v3);}
|
||||
bool executeQueued(PIObject * performer, const PIString & method, const PIVector<PIVariantSimple> & vl);
|
||||
bool executeQueued(PIObject * performer, const PIString & method) {return executeQueued(performer, method, PIVector<PIVariantSimple>());}
|
||||
bool executeQueued(PIObject * performer, const PIString & method, const PIVariantSimple & v0) {return executeQueued(performer, method, PIVector<PIVariantSimple>() << v0);}
|
||||
bool executeQueued(PIObject * performer, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1) {return executeQueued(performer, method, PIVector<PIVariantSimple>() << v0 << v1);}
|
||||
bool executeQueued(PIObject * performer, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2) {return executeQueued(performer, method, PIVector<PIVariantSimple>() << v0 << v1 << v2);}
|
||||
bool executeQueued(PIObject * performer, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2, const PIVariantSimple & v3) {return executeQueued(performer, method, PIVector<PIVariantSimple>() << v0 << v1 << v2 << v3);}
|
||||
|
||||
static bool execute(PIObject * o, const PIString & method, const PIVector<PIVariant> & vl) {return o->execute(method, vl);}
|
||||
static bool execute(PIObject * o, const PIString & method) {return execute(o, method, PIVector<PIVariant>());}
|
||||
static bool execute(PIObject * o, const PIString & method, const PIVariant & v0) {return execute(o, method, PIVector<PIVariant>() << v0);}
|
||||
static bool execute(PIObject * o, const PIString & method, const PIVariant & v0, const PIVariant & v1) {return execute(o, method, PIVector<PIVariant>() << v0 << v1);}
|
||||
static bool execute(PIObject * o, const PIString & method, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2) {return execute(o, method, PIVector<PIVariant>() << v0 << v1 << v2);}
|
||||
static bool execute(PIObject * o, const PIString & method, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2, const PIVariant & v3) {return execute(o, method, PIVector<PIVariant>() << v0 << v1 << v2 << v3);}
|
||||
static bool execute(PIObject * o, const PIString & method, const PIVector<PIVariantSimple> & vl) {return o->execute(method, vl);}
|
||||
static bool execute(PIObject * o, const PIString & method) {return execute(o, method, PIVector<PIVariantSimple>());}
|
||||
static bool execute(PIObject * o, const PIString & method, const PIVariantSimple & v0) {return execute(o, method, PIVector<PIVariantSimple>() << v0);}
|
||||
static bool execute(PIObject * o, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1) {return execute(o, method, PIVector<PIVariantSimple>() << v0 << v1);}
|
||||
static bool execute(PIObject * o, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2) {return execute(o, method, PIVector<PIVariantSimple>() << v0 << v1 << v2);}
|
||||
static bool execute(PIObject * o, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2, const PIVariantSimple & v3) {return execute(o, method, PIVector<PIVariantSimple>() << v0 << v1 << v2 << v3);}
|
||||
|
||||
static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVector<PIVariant> & vl) {return o->executeQueued(performer, method, vl);}
|
||||
static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method) {return executeQueued(o, performer, method, PIVector<PIVariant>());}
|
||||
static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVariant & v0) {return executeQueued(o, performer, method, PIVector<PIVariant>() << v0);}
|
||||
static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVariant & v0, const PIVariant & v1) {return executeQueued(o, performer, method, PIVector<PIVariant>() << v0 << v1);}
|
||||
static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2) {return executeQueued(o, performer, method, PIVector<PIVariant>() << v0 << v1 << v2);}
|
||||
static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2, const PIVariant & v3) {return executeQueued(o, performer, method, PIVector<PIVariant>() << v0 << v1 << v2 << v3);}
|
||||
static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVector<PIVariantSimple> & vl) {return o->executeQueued(performer, method, vl);}
|
||||
static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method) {return executeQueued(o, performer, method, PIVector<PIVariantSimple>());}
|
||||
static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVariantSimple & v0) {return executeQueued(o, performer, method, PIVector<PIVariantSimple>() << v0);}
|
||||
static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1) {return executeQueued(o, performer, method, PIVector<PIVariantSimple>() << v0 << v1);}
|
||||
static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2) {return executeQueued(o, performer, method, PIVector<PIVariantSimple>() << v0 << v1 << v2);}
|
||||
static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2, const PIVariantSimple & v3) {return executeQueued(o, performer, method, PIVector<PIVariantSimple>() << v0 << v1 << v2 << v3);}
|
||||
|
||||
void dump(const PIString & line_prefix = PIString()) const;
|
||||
|
||||
@@ -201,8 +202,8 @@ public:
|
||||
(*((std::function<void(T0)>*)i.functor))(v0);
|
||||
} else {
|
||||
if (i.performer) {
|
||||
PIVector<PIVariant> vl;
|
||||
if (i.args_count > 0) vl << PIVariant::fromValue(v0);
|
||||
PIVector<PIVariantSimple> vl;
|
||||
if (i.args_count > 0) vl << PIVariantSimple::fromValue(v0);
|
||||
i.performer->postQueuedEvent(__QueuedEvent(i.slot, i.dest, i.dest_o, sender, vl));
|
||||
} else {
|
||||
bool ts = sender->thread_safe_;
|
||||
@@ -232,9 +233,9 @@ public:
|
||||
(*((std::function<void(T0, T1)>*)i.functor))(v0, v1);
|
||||
} else {
|
||||
if (i.performer) {
|
||||
PIVector<PIVariant> vl;
|
||||
if (i.args_count > 0) vl << PIVariant::fromValue(v0);
|
||||
if (i.args_count > 1) vl << PIVariant::fromValue(v1);
|
||||
PIVector<PIVariantSimple> vl;
|
||||
if (i.args_count > 0) vl << PIVariantSimple::fromValue(v0);
|
||||
if (i.args_count > 1) vl << PIVariantSimple::fromValue(v1);
|
||||
i.performer->postQueuedEvent(__QueuedEvent(i.slot, i.dest, i.dest_o, sender, vl));
|
||||
} else {
|
||||
bool ts = sender->thread_safe_;
|
||||
@@ -267,10 +268,10 @@ public:
|
||||
(*((std::function<void(T0, T1, T2)>*)i.functor))(v0, v1, v2);
|
||||
} else {
|
||||
if (i.performer) {
|
||||
PIVector<PIVariant> vl;
|
||||
if (i.args_count > 0) vl << PIVariant::fromValue(v0);
|
||||
if (i.args_count > 1) vl << PIVariant::fromValue(v1);
|
||||
if (i.args_count > 2) vl << PIVariant::fromValue(v2);
|
||||
PIVector<PIVariantSimple> vl;
|
||||
if (i.args_count > 0) vl << PIVariantSimple::fromValue(v0);
|
||||
if (i.args_count > 1) vl << PIVariantSimple::fromValue(v1);
|
||||
if (i.args_count > 2) vl << PIVariantSimple::fromValue(v2);
|
||||
i.performer->postQueuedEvent(__QueuedEvent(i.slot, i.dest, i.dest_o, sender, vl));
|
||||
} else {
|
||||
bool ts = sender->thread_safe_;
|
||||
@@ -304,11 +305,11 @@ public:
|
||||
(*((std::function<void(T0, T1, T2, T3)>*)i.functor))(v0, v1, v2, v3);
|
||||
} else {
|
||||
if (i.performer) {
|
||||
PIVector<PIVariant> vl;
|
||||
if (i.args_count > 0) vl << PIVariant::fromValue(v0);
|
||||
if (i.args_count > 1) vl << PIVariant::fromValue(v1);
|
||||
if (i.args_count > 2) vl << PIVariant::fromValue(v2);
|
||||
if (i.args_count > 3) vl << PIVariant::fromValue(v3);
|
||||
PIVector<PIVariantSimple> vl;
|
||||
if (i.args_count > 0) vl << PIVariantSimple::fromValue(v0);
|
||||
if (i.args_count > 1) vl << PIVariantSimple::fromValue(v1);
|
||||
if (i.args_count > 2) vl << PIVariantSimple::fromValue(v2);
|
||||
if (i.args_count > 3) vl << PIVariantSimple::fromValue(v3);
|
||||
i.performer->postQueuedEvent(__QueuedEvent(i.slot, i.dest, i.dest_o, sender, vl));
|
||||
} else {
|
||||
bool ts = sender->thread_safe_;
|
||||
@@ -452,7 +453,7 @@ private:
|
||||
};
|
||||
|
||||
struct __QueuedEvent {
|
||||
__QueuedEvent(void * sl = 0, void * d = 0, PIObject * d_o = 0, PIObject * s = 0, const PIVector<PIVariant> & v = PIVector<PIVariant>()) {
|
||||
__QueuedEvent(void * sl = 0, void * d = 0, PIObject * d_o = 0, PIObject * s = 0, const PIVector<PIVariantSimple> & v = PIVector<PIVariantSimple>()) {
|
||||
slot = sl;
|
||||
dest = d;
|
||||
dest_o = d_o;
|
||||
@@ -463,7 +464,7 @@ private:
|
||||
void * dest;
|
||||
PIObject * dest_o;
|
||||
PIObject * src;
|
||||
PIVector<PIVariant> values;
|
||||
PIVector<PIVariantSimple> values;
|
||||
};
|
||||
|
||||
class Deleter {
|
||||
@@ -496,7 +497,7 @@ private:
|
||||
|
||||
static PIVector<PIObject * > & objects();
|
||||
static PIMutex & mutexObjects();
|
||||
static void callAddrV(void * slot, void * obj, int args, const PIVector<PIVariant> & vl);
|
||||
static void callAddrV(void * slot, void * obj, int args, const PIVector<PIVariantSimple> & vl);
|
||||
|
||||
|
||||
PIVector<__Connection> connections;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*! \file piobject.h
|
||||
/*! \file piobject_macros.h
|
||||
* \brief Base object
|
||||
*
|
||||
* This file declare PIObject class and associated macros
|
||||
* This file declare macros for PIObject
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
@@ -25,8 +25,6 @@
|
||||
#ifndef PIOBJECT_MACROS_H
|
||||
#define PIOBJECT_MACROS_H
|
||||
|
||||
//#include "piobject_macros.h"
|
||||
|
||||
|
||||
#ifdef DOXYGEN
|
||||
|
||||
@@ -269,7 +267,7 @@
|
||||
PIMutexLocker ml(__meta_mutex()); \
|
||||
__MetaData & eh(__meta_data()[__classNameIDS()]); \
|
||||
void * fp = (void*)(ret(*)(void*, a0))__stat_eh_##name##__; \
|
||||
void * fpV = (void*)(ret(*)(void*, const PIVariant &))__stat_eh_v_##name##__; \
|
||||
void * fpV = (void*)(ret(*)(void*, const PIVariantSimple &))__stat_eh_v_##name##__; \
|
||||
if (eh.eh_set[fp]) return; \
|
||||
eh.eh_set << fp; \
|
||||
__MetaFunc & f(eh.eh_func[fp]); \
|
||||
@@ -287,7 +285,7 @@
|
||||
PIMutexLocker ml(__meta_mutex()); \
|
||||
__MetaData & eh(__meta_data()[__classNameIDS()]); \
|
||||
void * fp = (void*)(ret(*)(void*, a0, a1))__stat_eh_##name##__; \
|
||||
void * fpV = (void*)(ret(*)(void*, const PIVariant &, const PIVariant &))__stat_eh_v_##name##__; \
|
||||
void * fpV = (void*)(ret(*)(void*, const PIVariantSimple &, const PIVariantSimple &))__stat_eh_v_##name##__; \
|
||||
if (eh.eh_set[fp]) return; \
|
||||
eh.eh_set << fp; \
|
||||
__MetaFunc & f(eh.eh_func[fp]); \
|
||||
@@ -305,7 +303,7 @@
|
||||
PIMutexLocker ml(__meta_mutex()); \
|
||||
__MetaData & eh(__meta_data()[__classNameIDS()]); \
|
||||
void * fp = (void*)(ret(*)(void*, a0, a1, a2))__stat_eh_##name##__; \
|
||||
void * fpV = (void*)(ret(*)(void*, const PIVariant &, const PIVariant &, const PIVariant &))__stat_eh_v_##name##__; \
|
||||
void * fpV = (void*)(ret(*)(void*, const PIVariantSimple &, const PIVariantSimple &, const PIVariantSimple &))__stat_eh_v_##name##__; \
|
||||
if (eh.eh_set[fp]) return; \
|
||||
eh.eh_set << fp; \
|
||||
__MetaFunc & f(eh.eh_func[fp]); \
|
||||
@@ -323,7 +321,7 @@
|
||||
PIMutexLocker ml(__meta_mutex()); \
|
||||
__MetaData & eh(__meta_data()[__classNameIDS()]); \
|
||||
void * fp = (void*)(ret(*)(void*, a0, a1, a2, a3))__stat_eh_##name##__; \
|
||||
void * fpV = (void*)(ret(*)(void*, const PIVariant &, const PIVariant &, const PIVariant &, const PIVariant &))__stat_eh_v_##name##__; \
|
||||
void * fpV = (void*)(ret(*)(void*, const PIVariantSimple &, const PIVariantSimple &, const PIVariantSimple &, const PIVariantSimple &))__stat_eh_v_##name##__; \
|
||||
if (eh.eh_set[fp]) return; \
|
||||
eh.eh_set << fp; \
|
||||
__MetaFunc & f(eh.eh_func[fp]); \
|
||||
@@ -345,7 +343,7 @@
|
||||
#define EVENT_HANDLER1(ret, name, a0, n0) \
|
||||
EH_INIT1(ret, name, a0, n0) \
|
||||
static ret __stat_eh_##name##__(void * __o__, a0 n0) {return ((__PIObject__*)__o__)->name(n0);} \
|
||||
static ret __stat_eh_v_##name##__(void * __o__, const PIVariant & v0) { \
|
||||
static ret __stat_eh_v_##name##__(void * __o__, const PIVariantSimple & v0) { \
|
||||
__PTYPE(a0) tv0 = __VVALUE(a0, v0); \
|
||||
return ((__PIObject__*)__o__)->name(tv0);} \
|
||||
ret name(a0 n0)
|
||||
@@ -353,7 +351,7 @@
|
||||
#define EVENT_HANDLER2(ret, name, a0, n0, a1, n1) \
|
||||
EH_INIT2(ret, name, a0, n0, a1, n1) \
|
||||
static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1) {return ((__PIObject__*)__o__)->name(n0, n1);} \
|
||||
static ret __stat_eh_v_##name##__(void * __o__, const PIVariant & v0, const PIVariant & v1) { \
|
||||
static ret __stat_eh_v_##name##__(void * __o__, const PIVariantSimple & v0, const PIVariantSimple & v1) { \
|
||||
__PTYPE(a0) tv0 = __VVALUE(a0, v0); \
|
||||
__PTYPE(a1) tv1 = __VVALUE(a1, v1); \
|
||||
return ((__PIObject__*)__o__)->name(tv0, tv1);} \
|
||||
@@ -362,7 +360,7 @@
|
||||
#define EVENT_HANDLER3(ret, name, a0, n0, a1, n1, a2, n2) \
|
||||
EH_INIT3(ret, name, a0, n0, a1, n1, a2, n2) \
|
||||
static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1, a2 n2) {return ((__PIObject__*)__o__)->name(n0, n1, n2);} \
|
||||
static ret __stat_eh_v_##name##__(void * __o__, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2) { \
|
||||
static ret __stat_eh_v_##name##__(void * __o__, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2) { \
|
||||
__PTYPE(a0) tv0 = __VVALUE(a0, v0); \
|
||||
__PTYPE(a1) tv1 = __VVALUE(a1, v1); \
|
||||
__PTYPE(a2) tv2 = __VVALUE(a2, v2); \
|
||||
@@ -372,7 +370,7 @@
|
||||
#define EVENT_HANDLER4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3) \
|
||||
EH_INIT4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3) \
|
||||
static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1, a2 n2, a3 n3) {return ((__PIObject__*)__o__)->name(n0, n1, n2, n3);} \
|
||||
static ret __stat_eh_v_##name##__(void * __o__, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2, const PIVariant & v3) { \
|
||||
static ret __stat_eh_v_##name##__(void * __o__, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2, const PIVariantSimple & v3) { \
|
||||
__PTYPE(a0) tv0 = __VVALUE(a0, v0); \
|
||||
__PTYPE(a1) tv1 = __VVALUE(a1, v1); \
|
||||
__PTYPE(a2) tv2 = __VVALUE(a2, v2); \
|
||||
@@ -385,43 +383,63 @@
|
||||
|
||||
#define EVENT_VHANDLER0(ret, name) \
|
||||
EH_INIT0(ret, name) \
|
||||
static ret __stat_eh_##name##__(void * __o__) {return ((__PIObject__*)__o__)->name();} \
|
||||
static ret __stat_eh_##name##__(void * __o__) { \
|
||||
return ((__PIObject__*)__o__)->name();} \
|
||||
virtual ret name()
|
||||
|
||||
#define EVENT_VHANDLER1(ret, name, a0, n0) \
|
||||
EH_INIT1(ret, name, a0, n0) \
|
||||
static ret __stat_eh_##name##__(void * __o__, a0 n0) {return ((__PIObject__*)__o__)->name(n0);} \
|
||||
static ret __stat_eh_v_##name##__(void * __o__, const PIVariant & v0) {return ((__PIObject__*)__o__)->name(__VVALUE(a0, v0));} \
|
||||
static ret __stat_eh_##name##__(void * __o__, a0 n0) { \
|
||||
return ((__PIObject__*)__o__)->name(n0);} \
|
||||
static ret __stat_eh_v_##name##__(void * __o__, const PIVariantSimple & v0) { \
|
||||
return ((__PIObject__*)__o__)->name(__VVALUE(a0, v0));} \
|
||||
virtual ret name(a0 n0)
|
||||
|
||||
#define EVENT_VHANDLER2(ret, name, a0, n0, a1, n1) \
|
||||
EH_INIT2(ret, name, a0, n0, a1, n1) \
|
||||
static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1) {return ((__PIObject__*)__o__)->name(n0, n1);} \
|
||||
static ret __stat_eh_v_##name##__(void * __o__, const PIVariant & v0, const PIVariant & v1) {return ((__PIObject__*)__o__)->name(__VVALUE(a0, v0), __VVALUE(a1, v1));} \
|
||||
static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1) { \
|
||||
return ((__PIObject__*)__o__)->name(n0, n1);} \
|
||||
static ret __stat_eh_v_##name##__(void * __o__, const PIVariantSimple & v0, const PIVariantSimple & v1) { \
|
||||
return ((__PIObject__*)__o__)->name(__VVALUE(a0, v0), __VVALUE(a1, v1));} \
|
||||
virtual ret name(a0 n0, a1 n1)
|
||||
|
||||
#define EVENT_VHANDLER3(ret, name, a0, n0, a1, n1, a2, n2) \
|
||||
EH_INIT3(ret, name, a0, n0, a1, n1, a2, n2) \
|
||||
static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1, a2 n2) {return ((__PIObject__*)__o__)->name(n0, n1, n2);} \
|
||||
static ret __stat_eh_v_##name##__(void * __o__, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2) {return ((__PIObject__*)__o__)->name(__VVALUE(a0, v0), __VVALUE(a1, v1), __VVALUE(a2, v2));} \
|
||||
static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1, a2 n2) { \
|
||||
return ((__PIObject__*)__o__)->name(n0, n1, n2);} \
|
||||
static ret __stat_eh_v_##name##__(void * __o__, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2) { \
|
||||
return ((__PIObject__*)__o__)->name(__VVALUE(a0, v0), __VVALUE(a1, v1), __VVALUE(a2, v2));} \
|
||||
virtual ret name(a0 n0, a1 n1, a2 n2)
|
||||
|
||||
#define EVENT_VHANDLER4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3) \
|
||||
EH_INIT4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3) \
|
||||
static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1, a2 n2, a3 n3) {return ((__PIObject__*)__o__)->name(n0, n1, n2, n3);} \
|
||||
static ret __stat_eh_v_##name##__(void * __o__, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2, const PIVariant & v3) {return ((__PIObject__*)__o__)->name(__VVALUE(a0, v0), __VVALUE(a1, v1), __VVALUE(a2, v2), __VVALUE(a3, v3));} \
|
||||
static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1, a2 n2, a3 n3) { \
|
||||
return ((__PIObject__*)__o__)->name(n0, n1, n2, n3);} \
|
||||
static ret __stat_eh_v_##name##__(void * __o__, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2, const PIVariantSimple & v3) { \
|
||||
return ((__PIObject__*)__o__)->name(__VVALUE(a0, v0), __VVALUE(a1, v1), __VVALUE(a2, v2), __VVALUE(a3, v3));} \
|
||||
virtual ret name(a0 n0, a1 n1, a2 n2, a3 n3)
|
||||
|
||||
#define EVENT_VHANDLER EVENT_VHANDLER0
|
||||
|
||||
|
||||
#define EVENT0(name) EVENT_HANDLER0(void, name) {static uint eid = PIStringAscii(#name).hash(); PIObject::raiseEvent(this, eid);}
|
||||
#define EVENT1(name, a0, n0) EVENT_HANDLER1(void, name, a0, n0) {static uint eid = PIStringAscii(#name).hash(); PIObject::raiseEvent(this, eid, n0);}
|
||||
#define EVENT2(name, a0, n0, a1, n1) EVENT_HANDLER2(void, name, a0, n0, a1, n1) {static uint eid = PIStringAscii(#name).hash(); PIObject::raiseEvent(this, eid, n0, n1);}
|
||||
#define EVENT3(name, a0, n0, a1, n1, a2, n2) EVENT_HANDLER3(void, name, a0, n0, a1, n1, a2, n2) {static uint eid = PIStringAscii(#name).hash(); PIObject::raiseEvent(this, eid, n0, n1, n2);}
|
||||
#define EVENT4(name, a0, n0, a1, n1, a2, n2, a3, n3) EVENT_HANDLER4(void, name, a0, n0, a1, n1, a2, n2, a3, n3) {static uint eid = PIStringAscii(#name).hash(); PIObject::raiseEvent(this, eid, n0, n1, n2, n3);}
|
||||
#define EVENT0(name) EVENT_HANDLER0(void, name) { \
|
||||
static uint eid = PIStringAscii(#name).hash(); PIObject::raiseEvent(this, eid);}
|
||||
|
||||
#define EVENT1(name, a0, n0) EVENT_HANDLER1(void, name, a0, n0) { \
|
||||
static uint eid = PIStringAscii(#name).hash(); PIObject::raiseEvent(this, eid, n0);}
|
||||
|
||||
#define EVENT2(name, a0, n0, a1, n1) EVENT_HANDLER2(void, name, a0, n0, a1, n1) { \
|
||||
static uint eid = PIStringAscii(#name).hash(); PIObject::raiseEvent(this, eid, n0, n1);}
|
||||
|
||||
#define EVENT3(name, a0, n0, a1, n1, a2, n2) EVENT_HANDLER3(void, name, a0, n0, a1, n1, a2, n2) { \
|
||||
static uint eid = PIStringAscii(#name).hash(); PIObject::raiseEvent(this, eid, n0, n1, n2);}
|
||||
|
||||
#define EVENT4(name, a0, n0, a1, n1, a2, n2, a3, n3) EVENT_HANDLER4(void, name, a0, n0, a1, n1, a2, n2, a3, n3) { \
|
||||
static uint eid = PIStringAscii(#name).hash(); PIObject::raiseEvent(this, eid, n0, n1, n2, n3);}
|
||||
|
||||
#define EVENT EVENT0
|
||||
|
||||
|
||||
#define RAISE_EVENT0(src, event) (src)->event();
|
||||
#define RAISE_EVENT1(src, event, v0) (src)->event(v0);
|
||||
#define RAISE_EVENT2(src, event, v0, v1) (src)->event(v0, v1);
|
||||
@@ -429,35 +447,81 @@
|
||||
#define RAISE_EVENT4(src, event, v0, v1, v2, v3) (src)->event(v0, v1, v2, v3);
|
||||
#define RAISE_EVENT RAISE_EVENT0
|
||||
|
||||
#define CONNECTU(src, event, dest, handler) PIObject::piConnectU(src, PIStringAscii(#event), dest, dest, PIStringAscii(#handler), LOCATION);
|
||||
#define CONNECTU_QUEUED(src, event, dest, handler, performer) PIObject::piConnectU(src, PIStringAscii(#event), dest, dest, PIStringAscii(#handler), LOCATION, performer);
|
||||
#define CONNECTL(src, event, functor) PIObject::piConnectLS(src, PIStringAscii(#event), PIObject::__newFunctor(&(src)->__stat_eh_##event##__, functor), LOCATION);
|
||||
|
||||
#define CONNECT0(ret, src, event, dest, handler) PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*))(&(dest)->__stat_eh_##handler##__), (void*)(void(*)(void*))(&(src)->__stat_eh_##event##__), 0, LOCATION);
|
||||
#define CONNECT1(ret, a0, src, event, dest, handler) PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0))(&(dest)->__stat_eh_##handler##__), (void*)(void(*)(void*, a0))(&(src)->__stat_eh_##event##__), 1, LOCATION);
|
||||
#define CONNECT2(ret, a0, a1, src, event, dest, handler) PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0, a1))(&(dest)->__stat_eh_##handler##__), (void*)(void(*)(void*, a0, a1))(&(src)->__stat_eh_##event##__), 2, LOCATION);
|
||||
#define CONNECT3(ret, a0, a1, a2, src, event, dest, handler) PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0, a1, a2))(&(dest)->__stat_eh_##handler##__), (void*)(void(*)(void*, a0, a1, a2))(&(src)->__stat_eh_##event##__), 3, LOCATION);
|
||||
#define CONNECT4(ret, a0, a1, a2, a3, src, event, dest, handler) PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0, a1, a2, a3))(&(dest)->__stat_eh_##handler##__), (void*)(void(*)(void*, a0, a1, a2, a3))(&(src)->__stat_eh_##event##__), 4, LOCATION);
|
||||
#define CONNECTU(src, event, dest, handler) \
|
||||
PIObject::piConnectU(src, PIStringAscii(#event), dest, dest, PIStringAscii(#handler), LOCATION);
|
||||
|
||||
#define CONNECTU_QUEUED(src, event, dest, handler, performer) \
|
||||
PIObject::piConnectU(src, PIStringAscii(#event), dest, dest, PIStringAscii(#handler), LOCATION, performer);
|
||||
|
||||
#define CONNECTL(src, event, functor) \
|
||||
PIObject::piConnectLS(src, PIStringAscii(#event), PIObject::__newFunctor(&(src)->__stat_eh_##event##__, functor), LOCATION);
|
||||
|
||||
|
||||
#define CONNECT0(ret, src, event, dest, handler) \
|
||||
PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*))(&(dest)->__stat_eh_##handler##__), \
|
||||
(void*)(void(*)(void*))(&(src)->__stat_eh_##event##__), 0, LOCATION);
|
||||
|
||||
#define CONNECT1(ret, a0, src, event, dest, handler) \
|
||||
PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0))(&(dest)->__stat_eh_##handler##__), \
|
||||
(void*)(void(*)(void*, a0))(&(src)->__stat_eh_##event##__), 1, LOCATION);
|
||||
|
||||
#define CONNECT2(ret, a0, a1, src, event, dest, handler) \
|
||||
PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0, a1))(&(dest)->__stat_eh_##handler##__), \
|
||||
(void*)(void(*)(void*, a0, a1))(&(src)->__stat_eh_##event##__), 2, LOCATION);
|
||||
|
||||
#define CONNECT3(ret, a0, a1, a2, src, event, dest, handler) \
|
||||
PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0, a1, a2))(&(dest)->__stat_eh_##handler##__), \
|
||||
(void*)(void(*)(void*, a0, a1, a2))(&(src)->__stat_eh_##event##__), 3, LOCATION);
|
||||
|
||||
#define CONNECT4(ret, a0, a1, a2, a3, src, event, dest, handler) \
|
||||
PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0, a1, a2, a3))(&(dest)->__stat_eh_##handler##__), \
|
||||
(void*)(void(*)(void*, a0, a1, a2, a3))(&(src)->__stat_eh_##event##__), 4, LOCATION);
|
||||
|
||||
#define CONNECT CONNECT0
|
||||
|
||||
#define WEAK_CONNECT0(ret, src, event, dest, handler) PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*))(&(dest)->__stat_eh_##handler##__), 0, 0, LOCATION);
|
||||
#define WEAK_CONNECT1(ret, a0, src, event, dest, handler) PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0))(&(dest)->__stat_eh_##handler##__), 0, 1, LOCATION);
|
||||
#define WEAK_CONNECT2(ret, a0, a1, src, event, dest, handler) PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0, a1))(&(dest)->__stat_eh_##handler##__), 0, 2, LOCATION);
|
||||
#define WEAK_CONNECT3(ret, a0, a1, a2, src, event, dest, handler) PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0, a1, a2))(&(dest)->__stat_eh_##handler##__), 0, 3, LOCATION);
|
||||
#define WEAK_CONNECT4(ret, a0, a1, a2, a3, src, event, dest, handler) PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0, a1, a2, a3))(&(dest)->__stat_eh_##handler##__), 0, 4, LOCATION);
|
||||
|
||||
#define WEAK_CONNECT0(ret, src, event, dest, handler) \
|
||||
PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*))(&(dest)->__stat_eh_##handler##__), 0, 0, LOCATION);
|
||||
|
||||
#define WEAK_CONNECT1(ret, a0, src, event, dest, handler) \
|
||||
PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0))(&(dest)->__stat_eh_##handler##__), 0, 1, LOCATION);
|
||||
|
||||
#define WEAK_CONNECT2(ret, a0, a1, src, event, dest, handler) \
|
||||
PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0, a1))(&(dest)->__stat_eh_##handler##__), 0, 2, LOCATION);
|
||||
|
||||
#define WEAK_CONNECT3(ret, a0, a1, a2, src, event, dest, handler) \
|
||||
PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0, a1, a2))(&(dest)->__stat_eh_##handler##__), 0, 3, LOCATION);
|
||||
|
||||
#define WEAK_CONNECT4(ret, a0, a1, a2, a3, src, event, dest, handler) \
|
||||
PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0, a1, a2, a3))(&(dest)->__stat_eh_##handler##__), 0, 4, LOCATION);
|
||||
|
||||
#define WEAK_CONNECT WEAK_CONNECT0
|
||||
|
||||
#define DISCONNECT0(ret, src, event, dest, handler) PIObject::piDisconnect(src, PIStringAscii(#event), dest, (void*)(ret(*)(void*))(&(dest)->__stat_eh_##handler##__));
|
||||
#define DISCONNECT1(ret, a0, src, event, dest, handler) PIObject::piDisconnect(src, PIStringAscii(#event), dest, (void*)(ret(*)(void*, a0))(&(dest)->__stat_eh_##handler##__));
|
||||
#define DISCONNECT2(ret, a0, a1, src, event, dest, handler) PIObject::piDisconnect(src, PIStringAscii(#event), dest, (void*)(ret(*)(void*, a0, a1))(&(dest)->__stat_eh_##handler##__));
|
||||
#define DISCONNECT3(ret, a0, a1, a2, src, event, dest, handler) PIObject::piDisconnect(src, PIStringAscii(#event), dest, (void*)(ret(*)(void*, a0, a1, a2))(&(dest)->__stat_eh_##handler##__));
|
||||
#define DISCONNECT4(ret, a0, a1, a2, a3, src, event, dest, handler) PIObject::piDisconnect(src, PIStringAscii(#event), dest, (void*)(ret(*)(void*, a0, a1, a2, a3))(&(dest)->__stat_eh_##handler##__));
|
||||
|
||||
#define DISCONNECT0(ret, src, event, dest, handler) \
|
||||
PIObject::piDisconnect(src, PIStringAscii(#event), dest, (void*)(ret(*)(void*))(&(dest)->__stat_eh_##handler##__));
|
||||
|
||||
#define DISCONNECT1(ret, a0, src, event, dest, handler) \
|
||||
PIObject::piDisconnect(src, PIStringAscii(#event), dest, (void*)(ret(*)(void*, a0))(&(dest)->__stat_eh_##handler##__));
|
||||
|
||||
#define DISCONNECT2(ret, a0, a1, src, event, dest, handler) \
|
||||
PIObject::piDisconnect(src, PIStringAscii(#event), dest, (void*)(ret(*)(void*, a0, a1))(&(dest)->__stat_eh_##handler##__));
|
||||
|
||||
#define DISCONNECT3(ret, a0, a1, a2, src, event, dest, handler) \
|
||||
PIObject::piDisconnect(src, PIStringAscii(#event), dest, (void*)(ret(*)(void*, a0, a1, a2))(&(dest)->__stat_eh_##handler##__));
|
||||
|
||||
#define DISCONNECT4(ret, a0, a1, a2, a3, src, event, dest, handler) \
|
||||
PIObject::piDisconnect(src, PIStringAscii(#event), dest, (void*)(ret(*)(void*, a0, a1, a2, a3))(&(dest)->__stat_eh_##handler##__));
|
||||
|
||||
#define DISCONNECT DISCONNECT0
|
||||
|
||||
|
||||
#define HANDLER(handler) __stat_eh_##handler##__
|
||||
|
||||
#define __PIOBJECT_SIGNATURE__ 0xabcdbadc
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -28,41 +28,54 @@ bool PIPropertyStorage::isPropertyExists(const PIString & _name) const {
|
||||
}
|
||||
|
||||
|
||||
void PIPropertyStorage::addProperty(const PIPropertyStorage::Property & p) {
|
||||
bool PIPropertyStorage::addProperty(const PIPropertyStorage::Property & p) {
|
||||
for (uint i = 0; i < props.size(); ++i)
|
||||
if (props[i].name == p.name) {
|
||||
props[i] = p;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
props << p;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void PIPropertyStorage::addProperty(PIPropertyStorage::Property && p) {
|
||||
bool PIPropertyStorage::addProperty(PIPropertyStorage::Property && p) {
|
||||
for (uint i = 0; i < props.size(); ++i)
|
||||
if (props[i].name == p.name) {
|
||||
props[i] = std::move(p);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
props << std::move(p);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void PIPropertyStorage::removeProperty(const PIString & _name) {
|
||||
for (uint i = 0; i < props.size(); ++i)
|
||||
bool PIPropertyStorage::addProperty(const PIString & _name, const PIVariant & _def_value, const PIString & _comment, int _flags) {
|
||||
return addProperty(Property(_name, _comment, _def_value, _flags));
|
||||
}
|
||||
|
||||
|
||||
bool PIPropertyStorage::removeProperty(const PIString & _name) {
|
||||
for (uint i = 0; i < props.size(); ++i) {
|
||||
if (props[i].name == _name) {
|
||||
props.remove(i);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void PIPropertyStorage::removePropertiesByFlag(int flag) {
|
||||
for (int i = 0; i < props.size_s(); ++i)
|
||||
int PIPropertyStorage::removePropertiesByFlag(int flag) {
|
||||
int ret = 0;
|
||||
for (int i = 0; i < props.size_s(); ++i) {
|
||||
if ((props[i].flags & flag) == flag) {
|
||||
props.remove(i);
|
||||
--i;
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -99,30 +112,36 @@ PIVariant PIPropertyStorage::propertyValueByName(const PIString & name) const {
|
||||
}
|
||||
|
||||
|
||||
void PIPropertyStorage::setPropertyValue(const PIString & name, const PIVariant & value) {
|
||||
for (uint i = 0; i < props.size(); ++i)
|
||||
bool PIPropertyStorage::setPropertyValue(const PIString & name, const PIVariant & value) {
|
||||
for (uint i = 0; i < props.size(); ++i) {
|
||||
if (props[i].name == name) {
|
||||
props[i].value = value;
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void PIPropertyStorage::setPropertyComment(const PIString & name, const PIString & comment) {
|
||||
for (uint i = 0; i < props.size(); ++i)
|
||||
bool PIPropertyStorage::setPropertyComment(const PIString & name, const PIString & comment) {
|
||||
for (uint i = 0; i < props.size(); ++i) {
|
||||
if (props[i].name == name) {
|
||||
props[i].comment = comment;
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void PIPropertyStorage::setPropertyFlags(const PIString & name, int flags) {
|
||||
for (uint i = 0; i < props.size(); ++i)
|
||||
bool PIPropertyStorage::setPropertyFlags(const PIString & name, int flags) {
|
||||
for (uint i = 0; i < props.size(); ++i) {
|
||||
if (props[i].name == name) {
|
||||
props[i].flags = flags;
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -110,24 +110,49 @@ public:
|
||||
PIVector<Property> & properties() {return props;}
|
||||
const PIVector<Property> & properties() const {return props;}
|
||||
const PIPropertyStorage & propertyStorage() const {return *this;}
|
||||
|
||||
/**
|
||||
* @brief Check if property with \a name exists
|
||||
* @return "true" if property exists
|
||||
*/
|
||||
bool isPropertyExists(const PIString & _name) const;
|
||||
|
||||
/**
|
||||
* @brief Remove all properties
|
||||
*/
|
||||
void clearProperties() {props.clear();}
|
||||
|
||||
/**
|
||||
* @brief Add property if name isn't present in storage, otherwrise update existing property with same name.
|
||||
*
|
||||
* @return "true" if new property added, else if update existing property return "false"
|
||||
* @param p to copy in storage
|
||||
*/
|
||||
void addProperty(const Property & p);
|
||||
void addProperty(Property && p);
|
||||
bool addProperty(const Property & p);
|
||||
bool addProperty(Property && p);
|
||||
|
||||
/**
|
||||
* @brief First of all construct Property with method params. After then add property if name isn't present
|
||||
* in storage, otherwrise update existing property with same name.
|
||||
* @return "true" if new property added, else if update existing property return "false"
|
||||
*/
|
||||
bool addProperty(const PIString & _name, const PIVariant & _def_value, const PIString & _comment = PIString(), int _flags = 0);
|
||||
|
||||
/**
|
||||
* @brief Remove property with \a name
|
||||
* @return "true" if property exists and removed
|
||||
*/
|
||||
bool removeProperty(const PIString & _name);
|
||||
|
||||
/**
|
||||
* @brief Remove properties wich has \a flag set
|
||||
* @return removed properties count
|
||||
*/
|
||||
int removePropertiesByFlag(int flag);
|
||||
|
||||
/**
|
||||
* @brief Merge other \a properties_ into this
|
||||
* @param flag_ignore - properties wich has this flag set will be ignored in merge
|
||||
*/
|
||||
void addProperty(const PIString & _name, const PIVariant & _def_value, const PIString & _comment = PIString(), int _flags = 0) {addProperty(Property(_name, _comment, _def_value, _flags));}
|
||||
void removeProperty(const PIString & _name);
|
||||
void removePropertiesByFlag(int flag);
|
||||
void updateProperties(const PIVector<Property> & properties_, int flag_ignore = 0);
|
||||
|
||||
/**
|
||||
@@ -151,24 +176,27 @@ public:
|
||||
*
|
||||
* @param name of property to set value
|
||||
* @param value to set
|
||||
* @return "true" if property exists and updated
|
||||
*/
|
||||
void setPropertyValue(const PIString & name, const PIVariant & value);
|
||||
bool setPropertyValue(const PIString & name, const PIVariant & value);
|
||||
|
||||
/**
|
||||
* @brief Set comment of property with specific name if name is present in storage.
|
||||
*
|
||||
* @param name of property to set comment
|
||||
* @param comment to set
|
||||
* @return "true" if property exists and updated
|
||||
*/
|
||||
void setPropertyComment(const PIString & name, const PIString & comment);
|
||||
bool setPropertyComment(const PIString & name, const PIString & comment);
|
||||
|
||||
/**
|
||||
* @brief Set flags of property with specific name if name is present in storage.
|
||||
*
|
||||
* @param name of property to set flags
|
||||
* @param flags to set
|
||||
*/
|
||||
void setPropertyFlags(const PIString & name, int flags);
|
||||
/**
|
||||
* @brief Set flags of property with specific name if name is present in storage.
|
||||
*
|
||||
* @param name of property to set flags
|
||||
* @param flags to set
|
||||
* @return "true" if property exists and updated
|
||||
*/
|
||||
bool setPropertyFlags(const PIString & name, int flags);
|
||||
|
||||
PIPropertyStorage & operator <<(const PIPropertyStorage::Property & p) {props << p; return *this;}
|
||||
PIPropertyStorage & operator <<(const PIVector<Property> & p) {props << p; return *this;}
|
||||
|
||||
@@ -333,11 +333,14 @@ PIString PIString::fromAscii(const char * s) {
|
||||
ret.push_back(PIChar(s[l]));
|
||||
++l;
|
||||
}
|
||||
/*while (s[l] != '\0') ++l;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
PIString PIString::fromAscii(const char * s, int len) {
|
||||
PIString ret;
|
||||
ret.resize(l);
|
||||
for (int i = 0; i < l; ++i)
|
||||
ret[i] = s[i];*/
|
||||
for (int l = 0; l < len; ++l)
|
||||
ret.push_back(PIChar(s[l]));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -722,6 +722,9 @@ public:
|
||||
//! \brief Return string constructed from ASCII
|
||||
static PIString fromAscii(const char * s);
|
||||
|
||||
//! \brief Return string constructed from "len" chars ASCII
|
||||
static PIString fromAscii(const char * s, int len);
|
||||
|
||||
//! \brief Return string constructed from "c" codepage
|
||||
static PIString fromCodepage(const char * s, const char * c);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*! \file pistring.h
|
||||
* \brief String
|
||||
/*! \file pistring_std.h
|
||||
* \brief STD for PIString
|
||||
*
|
||||
* This file declare std operators and string conversions
|
||||
*/
|
||||
@@ -23,11 +23,12 @@
|
||||
*/
|
||||
#ifndef PISTRING_STD_H
|
||||
#define PISTRING_STD_H
|
||||
|
||||
|
||||
#include <string>
|
||||
#ifdef QNX
|
||||
typedef std::basic_string<wchar_t> wstring;
|
||||
#endif
|
||||
|
||||
#include "pistringlist.h"
|
||||
|
||||
|
||||
@@ -97,4 +98,5 @@ inline std::ostream & operator <<(std::ostream & s, const PIStringList & v) {
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
#endif // PISTRING_STD_H
|
||||
|
||||
@@ -212,6 +212,13 @@ PIDateTime PIDateTime::current() {
|
||||
}
|
||||
|
||||
|
||||
void PISystemTime::toTimespec(void * ts) {
|
||||
#ifndef WINDOWS
|
||||
((timespec*)ts)->tv_sec = seconds;
|
||||
((timespec*)ts)->tv_nsec = nanoseconds;
|
||||
#endif
|
||||
}
|
||||
|
||||
PISystemTime PISystemTime::abs() const {
|
||||
if (seconds < 0)
|
||||
return PISystemTime(piAbsl(seconds) - 1, 1000000000l - piAbsl(nanoseconds));
|
||||
@@ -255,12 +262,12 @@ PISystemTime PISystemTime::current(bool precise_but_not_system) {
|
||||
timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
gettimeofday(&tv, NULL);
|
||||
gettimeofday(&tv, NULL);
|
||||
t_cur.tv_sec = tv.tv_sec;
|
||||
t_cur.tv_nsec = tv.tv_usec * 1000;
|
||||
# else
|
||||
timespec t_cur;
|
||||
clock_gettime(0, &t_cur);
|
||||
clock_gettime(precise_but_not_system ? CLOCK_MONOTONIC : 0, &t_cur);
|
||||
# endif
|
||||
# endif
|
||||
return PISystemTime(t_cur.tv_sec, t_cur.tv_nsec);
|
||||
|
||||
@@ -60,8 +60,6 @@ public:
|
||||
//! Contructs system time with s = "s" and ns = "ns"
|
||||
PISystemTime(int s, int ns) {seconds = s; nanoseconds = ns; checkOverflows();}
|
||||
|
||||
//! Contructs system time from another
|
||||
PISystemTime(const PISystemTime & t) {seconds = t.seconds; nanoseconds = t.nanoseconds;}
|
||||
|
||||
//! Returns stored system time value in seconds
|
||||
double toSeconds() const {return double(seconds) + nanoseconds / 1.e+9;}
|
||||
@@ -93,6 +91,8 @@ public:
|
||||
//! If you call this function on system time returned with \a PISystemTime::current() thread will be sleep almost forever.
|
||||
void sleep() {piUSleep(piFloord(toMicroseconds()));} // wait self value, useful to wait some dT = (t1 - t0)
|
||||
|
||||
//! On Unix system assign current value to timespec struct
|
||||
void toTimespec(void *ts);
|
||||
|
||||
//! Returns copy of this system time with absolutely values of s and ns
|
||||
PISystemTime abs() const;
|
||||
@@ -170,13 +170,6 @@ private:
|
||||
//! \relatesalso PICout \relatesalso PICout \brief Output operator to PICout
|
||||
inline PICout operator <<(PICout s, const PISystemTime & v) {s.space(); s.setControl(0, true); s << "(" << v.seconds << " s, " << v.nanoseconds << " ns)"; s.restoreControl(); return s;}
|
||||
|
||||
//! \relatesalso PISystemTime \relatesalso PIByteArray \brief Output operator to PIByteArray
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PISystemTime & v) {s << v.seconds << v.nanoseconds; return s;}
|
||||
|
||||
//! \relatesalso PISystemTime \relatesalso PIByteArray \brief Input operator from PIByteArray
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PISystemTime & v) {s >> v.seconds >> v.nanoseconds; return s;}
|
||||
|
||||
|
||||
|
||||
|
||||
struct PIP_EXPORT PITime {
|
||||
@@ -197,8 +190,6 @@ PIP_EXPORT bool operator >(const PITime & t0, const PITime & t1);
|
||||
inline bool operator !=(const PITime & t0, const PITime & t1) {return !(t0 == t1);}
|
||||
inline bool operator <=(const PITime & t0, const PITime & t1) {return !(t0 > t1);}
|
||||
inline bool operator >=(const PITime & t0, const PITime & t1) {return !(t0 < t1);}
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PITime & v) {s << v.hours << v.minutes << v.seconds << v.milliseconds; return s;}
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PITime & v) {s >> v.hours >> v.minutes >> v.seconds >> v.milliseconds; return s;}
|
||||
|
||||
//! \relatesalso PICout \relatesalso PICout \brief Output operator to PICout
|
||||
PIP_EXPORT PICout operator <<(PICout s, const PITime & v);
|
||||
@@ -221,8 +212,6 @@ PIP_EXPORT bool operator >(const PIDate & t0, const PIDate & t1);
|
||||
inline bool operator !=(const PIDate & t0, const PIDate & t1) {return !(t0 == t1);}
|
||||
inline bool operator <=(const PIDate & t0, const PIDate & t1) {return !(t0 > t1);}
|
||||
inline bool operator >=(const PIDate & t0, const PIDate & t1) {return !(t0 < t1);}
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIDate & v) {s << v.year << v.month << v.day; return s;}
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIDate & v) {s >> v.year >> v.month >> v.day; return s;}
|
||||
|
||||
//! \relatesalso PICout \relatesalso PICout \brief Output operator to PICout
|
||||
PIP_EXPORT PICout operator <<(PICout s, const PIDate & v);
|
||||
|
||||
@@ -661,6 +661,7 @@ template<> inline PIVariantTypes::Color PIVariant::value() const {return toColor
|
||||
template<> inline PIVariantTypes::IODevice PIVariant::value() const {return toIODevice();}
|
||||
template<> inline PIPointd PIVariant::value() const {return toPoint();}
|
||||
template<> inline PIRectd PIVariant::value() const {return toRect();}
|
||||
template<> inline PIVariant PIVariant::value() const {return *this;}
|
||||
|
||||
template<> inline PIVariant PIVariant::fromValue(const bool & v) {return PIVariant(v);}
|
||||
template<> inline PIVariant PIVariant::fromValue(const char & v) {return PIVariant(v);}
|
||||
@@ -691,6 +692,7 @@ template<> inline PIVariant PIVariant::fromValue(const PIPointd & v) {return PIV
|
||||
template<> inline PIVariant PIVariant::fromValue(const PIRectd & v) {return PIVariant(v);}
|
||||
template<> inline PIVariant PIVariant::fromValue(const PIMathVectord & v) {return PIVariant(v);}
|
||||
template<> inline PIVariant PIVariant::fromValue(const PIMathMatrixd & v) {return PIVariant(v);}
|
||||
template<> inline PIVariant PIVariant::fromValue(const PIVariant & v) {return PIVariant(v);}
|
||||
|
||||
template<> inline PIVariant::Type PIVariant::getType<bool>() {return PIVariant::pivBool;}
|
||||
template<> inline PIVariant::Type PIVariant::getType<char>() {return PIVariant::pivChar;}
|
||||
@@ -752,7 +754,6 @@ REGISTER_VARIANT(PIRectd)
|
||||
REGISTER_VARIANT(PIMathVectord)
|
||||
REGISTER_VARIANT(PIMathMatrixd)
|
||||
|
||||
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIVariant & v) {
|
||||
s << v._content << int(v._type);
|
||||
if (v._type == PIVariant::pivCustom) {
|
||||
|
||||
148
libs/main/core/pivariantsimple.h
Normal file
148
libs/main/core/pivariantsimple.h
Normal file
@@ -0,0 +1,148 @@
|
||||
/*! \file pivariantsimple.h
|
||||
* \brief Variant simple type
|
||||
*
|
||||
* This file declares PIVariantSimple
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Variant simple type
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PIVARIANTSIMPLE_H
|
||||
#define PIVARIANTSIMPLE_H
|
||||
|
||||
#include "pistring.h"
|
||||
#include <typeinfo>
|
||||
#ifdef PIP_FREERTOS
|
||||
#include "pivariant.h"
|
||||
#endif
|
||||
|
||||
|
||||
class __VariantFunctionsBase__ {
|
||||
public:
|
||||
virtual __VariantFunctionsBase__ * instance() {return 0;}
|
||||
virtual PIString typeName() const {return PIString();}
|
||||
virtual uint hash() const {return 0;}
|
||||
virtual void newT(void *& ptr, const void * value) {;}
|
||||
virtual void newNullT(void *& ptr) {;}
|
||||
virtual void assignT(void *& ptr, const void * value) {;}
|
||||
virtual void deleteT(void *& ptr) {;}
|
||||
};
|
||||
|
||||
|
||||
template<typename T>
|
||||
class __VariantFunctions__: public __VariantFunctionsBase__ {
|
||||
public:
|
||||
__VariantFunctionsBase__ * instance() final {static __VariantFunctions__<T> ret; return &ret;}
|
||||
#ifdef PIP_FREERTOS
|
||||
PIString typeName() const final {static PIString ret(PIVariant(T()).typeName()); return ret;}
|
||||
#else
|
||||
PIString typeName() const final {static PIString ret(typeid(T).name()); return ret;}
|
||||
#endif
|
||||
uint hash() const final {static uint ret = typeName().hash(); return ret;}
|
||||
void newT(void *& ptr, const void * value) final {ptr = (void*)(new T(*(const T*)value));}
|
||||
void newNullT(void *& ptr) final {ptr = (void*)(new T());}
|
||||
void assignT(void *& ptr, const void * value) final {*(T*)ptr = *(const T*)value;}
|
||||
void deleteT(void *& ptr) final {delete (T*)(ptr);}
|
||||
};
|
||||
|
||||
|
||||
class PIVariantSimple {
|
||||
public:
|
||||
PIVariantSimple() {ptr = 0; f = 0;}
|
||||
PIVariantSimple(const PIVariantSimple & v) {
|
||||
ptr = 0;
|
||||
f = v.f;
|
||||
if (f && v.ptr)
|
||||
f->newT(ptr, v.ptr);
|
||||
}
|
||||
~PIVariantSimple() {destroy();}
|
||||
|
||||
PIVariantSimple & operator=(const PIVariantSimple & v) {
|
||||
destroy();
|
||||
f = v.f;
|
||||
if (f && v.ptr)
|
||||
f->newT(ptr, v.ptr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void setValue(const T & v) {
|
||||
if (f) {
|
||||
if (isMyType<T>()) {
|
||||
f->assignT(ptr, (const void *)&v);
|
||||
return;
|
||||
}
|
||||
}
|
||||
destroy();
|
||||
f = __VariantFunctions__<T>().instance();
|
||||
f->newT(ptr, (const void *)&v);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T value() const {
|
||||
if (!f) return T();
|
||||
if (!isMyType<T>())
|
||||
return T();
|
||||
return *(T*)(ptr);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static PIVariantSimple fromValue(const T & v) {
|
||||
PIVariantSimple ret;
|
||||
ret.setValue(v);
|
||||
return ret;
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
bool isMyType() const {
|
||||
if (!f) return false;
|
||||
uint mh = f->hash(), th = __VariantFunctions__<T>().instance()->hash();
|
||||
if (mh == 0 || th == 0) return false;
|
||||
return mh == th;
|
||||
}
|
||||
|
||||
void destroy() {
|
||||
if (ptr && f)
|
||||
f->deleteT(ptr);
|
||||
ptr = 0;
|
||||
f = 0;
|
||||
}
|
||||
|
||||
void * ptr;
|
||||
__VariantFunctionsBase__ * f;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#define REGISTER_PIVARIANTSIMPLE(Type) \
|
||||
template<> \
|
||||
class __VariantFunctions__<Type>: public __VariantFunctionsBase__ { \
|
||||
public: \
|
||||
__VariantFunctionsBase__ * instance() final {static __VariantFunctions__<Type> ret; return &ret;} \
|
||||
PIString typeName() const final {static PIString ret(#Type); return ret;} \
|
||||
uint hash() const final {static uint ret = typeName().hash(); return ret;} \
|
||||
void newT(void *& ptr, const void * value) final {ptr = (void*)(new Type(*(const Type *)value));} \
|
||||
void newNullT(void *& ptr) final {ptr = (void*)(new Type());} \
|
||||
void assignT(void *& ptr, const void * value) final {*(Type *)ptr = *(const Type *)value;} \
|
||||
void deleteT(void *& ptr) final {delete (Type *)(ptr);} \
|
||||
};
|
||||
|
||||
REGISTER_PIVARIANTSIMPLE(std::function<void(void*)>)
|
||||
|
||||
#endif // PIVARIANTSIMPLE_H
|
||||
@@ -203,10 +203,7 @@ double PIGeoPosition::height() const {
|
||||
|
||||
|
||||
PIGeoPosition &PIGeoPosition::setGeodetic(double lat, double lon, double ht, PIEllipsoidModel ell) {
|
||||
if(lat > 90 || lat < -90) {
|
||||
piCout << "[PIGeoPosition]" << "Achtung! Invalid latitude in setGeodetic:" << lat;
|
||||
assert(lat <= 90 && lat >= -90);
|
||||
}
|
||||
assertm(lat <= 90 && lat >= -90, "Achtung! Invalid latitude in setGeodetic");
|
||||
(*this)[0] = lat;
|
||||
(*this)[1] = lon;
|
||||
if((*this)[1] < 0) (*this)[1] += 360 * (1 + (unsigned long)((*this)[1]/360));
|
||||
@@ -219,14 +216,8 @@ PIGeoPosition &PIGeoPosition::setGeodetic(double lat, double lon, double ht, PIE
|
||||
|
||||
|
||||
PIGeoPosition &PIGeoPosition::setGeocentric(double lat, double lon, double rad) {
|
||||
if(lat > 90 || lat < -90) {
|
||||
piCout << "[PIGeoPosition]" << "Achtung! Invalid latitude in setGeocentric:" << lat;
|
||||
assert(lat <= 90 && lat >= -90);
|
||||
}
|
||||
if(rad < 0) {
|
||||
piCout << "[PIGeoPosition]" << "Achtung! Invalid radius in setGeocentric:" << rad;
|
||||
assert(rad >= 0);
|
||||
}
|
||||
assertm(lat <= 90 && lat >= -90, "Achtung! Invalid latitude in setGeocentric");
|
||||
assertm(rad >= 0, "Achtung! Invalid radius in setGeocentric");
|
||||
(*this)[0] = lat;
|
||||
(*this)[1] = lon;
|
||||
(*this)[2] = rad;
|
||||
@@ -238,14 +229,8 @@ PIGeoPosition &PIGeoPosition::setGeocentric(double lat, double lon, double rad)
|
||||
|
||||
|
||||
PIGeoPosition &PIGeoPosition::setSpherical(double theta, double phi, double rad) {
|
||||
if(theta < 0 || theta > 180) {
|
||||
piCout << "[PIGeoPosition]" << "Achtung! Invalid theta in setSpherical:" << theta;
|
||||
assert(theta <= 180 && theta >= 0);
|
||||
}
|
||||
if(rad < 0) {
|
||||
piCout << "[PIGeoPosition]" << "Achtung! Invalid radius in setSpherical:" << rad;
|
||||
assert(rad >= 0);
|
||||
}
|
||||
assertm(theta <= 180 && theta >= 0, "Achtung! Invalid theta in setSpherical");
|
||||
assertm(rad >= 0, "Achtung! Invalid radius in setSpherical");
|
||||
(*this)[0] = theta;
|
||||
(*this)[1] = phi;
|
||||
(*this)[2] = rad;
|
||||
@@ -439,24 +424,15 @@ bool PIGeoPosition::operator==(const PIGeoPosition &right) const {
|
||||
void PIGeoPosition::initialize(PIMathVectorT3d v, PIGeoPosition::CoordinateSystem sys, PIEllipsoidModel ell) {
|
||||
double a(v[0]), b(v[1]), c(v[2]);
|
||||
if(sys == Geodetic || sys==Geocentric) {
|
||||
if(a > 90 || a < -90) {
|
||||
piCout << "[PIGeoPosition]" << "Achtung! Invalid latitude in constructor:" << a;
|
||||
assert(a <= 90 && a >= -90);
|
||||
}
|
||||
assertm(a <= 90 && a >= -90, "Achtung! Invalid latitude in constructor");
|
||||
if(b < 0) b += 360*(1+(unsigned long)(b/360));
|
||||
else if(b >= 360) b -= 360*(unsigned long)(b/360);
|
||||
}
|
||||
if(sys==Geocentric || sys==Spherical) {
|
||||
if(c < 0) {
|
||||
piCout << "[PIGeoPosition]" << "Achtung! Invalid radius in constructor:" << c;
|
||||
assert(c >= 0);
|
||||
}
|
||||
assertm(c >= 0, "Achtung! Invalid radius in constructor");
|
||||
}
|
||||
if(sys==Spherical) {
|
||||
if(a < 0 || a > 180) {
|
||||
piCout << "[PIGeoPosition]" << "Achtung! Invalid theta in constructor:" << a;
|
||||
assert(a >= 0 && a <= 180);
|
||||
}
|
||||
assertm(a >= 0 && a <= 180, "Achtung! Invalid theta in constructor");
|
||||
if(b < 0) b += 360*(1+(unsigned long)(b/360));
|
||||
else if(b >= 360) b -= 360*(unsigned long)(b/360);
|
||||
}
|
||||
@@ -493,10 +469,7 @@ double PIGeoPosition::elevationGeodetic(const PIGeoPosition &p) const {
|
||||
r.transformTo(Cartesian);
|
||||
s.transformTo(Cartesian);
|
||||
PIMathVectorT3d z = s - r;
|
||||
if (z.length() <= 1e-4) { // if the positions are within .1 millimeter
|
||||
piCout << "[PIGeoPosition]" << "Positions are within .1 millimeter" << z;
|
||||
assert(z.length() > 1e-4);
|
||||
}
|
||||
assertm(z.length() > 1e-4, "Positions are within .1 millimeter");
|
||||
PIMathVectorT3d kv; // Compute k vector in local North-East-Up (NEU) system
|
||||
kv[0] = cos(lat) * cos(lng);
|
||||
kv[1] = cos(lat) * sin(lng);
|
||||
@@ -517,10 +490,7 @@ double PIGeoPosition::azimuth(const PIGeoPosition &p) const {
|
||||
xyz = xy + r[2] * r[2];
|
||||
xy = sqrt(xy);
|
||||
xyz = sqrt(xyz);
|
||||
if (xy <= 1e-14 || xyz <=1e-14) {
|
||||
piCout << "[PIGeoPosition]" << "Divide by Zero Error";
|
||||
assert(xy > 1e-14 && xyz > 1e-14);
|
||||
}
|
||||
assertm(xy > 1e-14 && xyz > 1e-14, "Divide by Zero Error");
|
||||
cosl = r[0] / xy;
|
||||
sinl = r[1] / xy;
|
||||
sint = r[2] / xyz;
|
||||
@@ -535,10 +505,7 @@ double PIGeoPosition::azimuth(const PIGeoPosition &p) const {
|
||||
p1 = (xn1 * z1) + (xn2 * z2) + (xn3 * z3) ;
|
||||
p2 = (xe1 * z1) + (xe2 * z2) ;
|
||||
test = piAbsd(p1) + piAbsd(p2);
|
||||
if (test < 1.0e-16) {
|
||||
piCout << "[PIGeoPosition]" << "azAngle(), failed p1+p2 test" << test;
|
||||
assert(test >= 1.0e-16);
|
||||
}
|
||||
assertm(test >= 1.0e-16, "azAngle(), failed p1+p2 test");
|
||||
alpha = 90 - atan2(p1, p2) * rad2deg;
|
||||
if (alpha < 0) return alpha + 360;
|
||||
else return alpha;
|
||||
@@ -553,10 +520,7 @@ double PIGeoPosition::azimuthGeodetic(const PIGeoPosition &p) const {
|
||||
s.transformTo(Cartesian);
|
||||
PIMathVectorT3d z;
|
||||
z = s - r;
|
||||
if (z.length() <= 1e-4) { // if the positions are within .1 millimeter
|
||||
piCout << "[PIGeoPosition]" << "Positions are within 0.1 millimeter" << z.length();
|
||||
assert(z.length() > 1e-4);
|
||||
}
|
||||
assertm(z.length() > 1e-4, "Positions are within 0.1 millimeter");
|
||||
PIMathVectorT3d iv; // Compute i vector in local North-East-Up (NEU) system
|
||||
iv[0] = -sin(lat) * cos(lng);
|
||||
iv[1] = -sin(lat) * sin(lng);
|
||||
|
||||
@@ -65,8 +65,6 @@ public:
|
||||
//! \brief IPv4 network address, IP and port
|
||||
class PIP_EXPORT Address {
|
||||
friend class PIEthernet;
|
||||
friend inline PIByteArray & operator <<(PIByteArray & s, const PIEthernet::Address & v);
|
||||
friend inline PIByteArray & operator >>(PIByteArray & s, PIEthernet::Address & v);
|
||||
public:
|
||||
|
||||
//! Contructs %Address with binary representation of IP and port
|
||||
@@ -519,7 +517,5 @@ inline PICout operator <<(PICout s, const PIEthernet::Address & v) {s.space(); s
|
||||
|
||||
inline bool operator ==(const PIEthernet::Address & v0, const PIEthernet::Address & v1) {return (v0.ip() == v1.ip() && v0.port() == v1.port());}
|
||||
inline bool operator !=(const PIEthernet::Address & v0, const PIEthernet::Address & v1) {return (v0.ip() != v1.ip() || v0.port() != v1.port());}
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIEthernet::Address & v) {s << v.ip_ << v.port_; return s;}
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIEthernet::Address & v) {s >> v.ip_ >> v.port_; return s;}
|
||||
|
||||
#endif // PIETHERNET_H
|
||||
|
||||
@@ -124,10 +124,12 @@ PIString PIFile::FileInfo::extension() const {
|
||||
|
||||
PIString PIFile::FileInfo::dir() const {
|
||||
if (path.isEmpty()) return PIString();
|
||||
PIString ret = path.mid(0, path.findLast(PIDir::separator));
|
||||
if (ret.isEmpty()) ret = PIDir::separator;
|
||||
if (!PIDir(ret).isExists()) return (PIStringAscii(".") + PIDir::separator);
|
||||
return ret;
|
||||
int ind = path.findLast(PIDir::separator);
|
||||
PIString ret;
|
||||
if (ind >= 0)
|
||||
ret = path.mid(0, ind);
|
||||
if (ret.isEmpty()) ret = ".";
|
||||
return ret + PIDir::separator;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ public:
|
||||
explicit PIFile();
|
||||
|
||||
struct PIP_EXPORT FileInfo {
|
||||
FileInfo() {size = 0; id_group = id_user = 0;}
|
||||
FileInfo(const PIString & path_ = PIString()) {path = path_; size = 0; id_group = id_user = 0;}
|
||||
|
||||
enum Flag {
|
||||
File = 0x01,
|
||||
|
||||
@@ -709,7 +709,16 @@ int PISerial::readDevice(void * read_to, int max_size) {
|
||||
return PRIVATE->readed;
|
||||
#else
|
||||
if (!canRead()) return -1;
|
||||
return ::read(fd, read_to, max_size);
|
||||
int ret = ::read(fd, read_to, max_size);
|
||||
if (ret < 0) {
|
||||
int err = errno;
|
||||
if (err == EBADF || err == EFAULT || err == EINVAL || err == EIO) {
|
||||
PIThread::stop(false);
|
||||
close();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -330,8 +330,10 @@ void PIEvaluator::makeOutput(PIString & string) {
|
||||
void PIEvaluator::findUnknownVariables() {
|
||||
PIString cvar;
|
||||
unknownVars.clear();
|
||||
usedVars.clear();
|
||||
for (int i = 0; i < currentString.length(); i++) {
|
||||
if (elements[i].var_num == -666) cvar += currentString[i];
|
||||
if (elements[i].var_num >= 0) usedVars << content.variable(elements[i].var_num).name;
|
||||
else if (elements[i].var_num == -666) cvar += currentString[i];
|
||||
else {
|
||||
if (cvar.length() == 0) continue;
|
||||
unknownVars << cvar;
|
||||
@@ -340,6 +342,10 @@ void PIEvaluator::findUnknownVariables() {
|
||||
}
|
||||
if (cvar.length() > 0) unknownVars << cvar;
|
||||
unknownVars.removeDuplicates();
|
||||
usedVars.removeDuplicates();
|
||||
usedVars.removeOne("i");
|
||||
usedVars.removeOne("pi");
|
||||
usedVars.removeOne("e");
|
||||
}
|
||||
|
||||
|
||||
@@ -1196,7 +1202,7 @@ complexd PIEvaluator::evaluate() {
|
||||
|
||||
PIByteArray PIEvaluator::save() const {
|
||||
PIByteArray ret;
|
||||
ret << content << currentVariables << unknownVars << instructions << currentString << lastError << out << correct;
|
||||
ret << content << currentVariables << unknownVars << instructions << currentString << lastError << out << correct << usedVars;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1204,5 +1210,6 @@ PIByteArray PIEvaluator::save() const {
|
||||
void PIEvaluator::load(PIByteArray ba) {
|
||||
if (ba.size() <= 4) return;
|
||||
ba >> content >> currentVariables >> unknownVars >> instructions >> currentString >> lastError >> out >> correct;
|
||||
if (ba.size() >= 4) ba >> usedVars;
|
||||
variables = currentVariables;
|
||||
}
|
||||
|
||||
@@ -176,6 +176,9 @@ public:
|
||||
//! Returns all unknown variables founded in last expression passed to \a check() function
|
||||
const PIStringList & unknownVariables() const {return unknownVars;}
|
||||
|
||||
//! Returns all used variables founded in last expression passed to \a check() function
|
||||
const PIStringList & usedVariables() const {return usedVars;}
|
||||
|
||||
//! Returns processed last expression passed to \a check() function
|
||||
const PIString & expression() const {return currentString;}
|
||||
|
||||
@@ -220,7 +223,7 @@ private:
|
||||
PIDeque<PIEvaluatorTypes::Element> elements;
|
||||
PIVector<PIEvaluatorTypes::Variable> currentVariables, variables, tmpvars, * kvars;
|
||||
PIVector<PIEvaluatorTypes::Instruction> instructions;
|
||||
PIStringList unknownVars;
|
||||
PIStringList unknownVars, usedVars;
|
||||
PIString currentString, lastError;
|
||||
complexd out;
|
||||
bool correct;
|
||||
|
||||
@@ -177,17 +177,13 @@ void PIFFT_double::ftbasegeneratecomplexfftplan(uint n, ftplan * plan) {
|
||||
curplan.plan.resize(planarraysize);
|
||||
int ftbase_ftbasecffttask = 0;
|
||||
ftbase_ftbasegenerateplanrec(n, ftbase_ftbasecffttask, plan, &plansize, &precomputedsize, &planarraysize, &tmpmemsize, &stackmemsize, stackptr);
|
||||
if (stackptr != 0) {
|
||||
return;//ae_assert(stackptr==0, "Internal error in FTBaseGenerateComplexFFTPlan: stack ptr!");
|
||||
}
|
||||
assert(stackptr==0);
|
||||
curplan.stackbuf.resize(piMax<int>(stackmemsize, 1)); //ae_vector_set_length(&curplan.stackbuf, ae_maxint(stackmemsize, 1));
|
||||
curplan.tmpbuf.resize(piMax<int>(tmpmemsize, 1)); //ae_vector_set_length(&(curplan.tmpbuf), ae_maxint(tmpmemsize, 1));
|
||||
curplan.precomputed.resize(piMax<int>(precomputedsize, 1)); //ae_vector_set_length(&curplan.precomputed, ae_maxint(precomputedsize, 1));
|
||||
stackptr = 0;
|
||||
ftbase_ftbaseprecomputeplanrec(plan, 0, stackptr);
|
||||
if (stackptr != 0) {
|
||||
return;//ae_assert(stackptr==0, "Internal error in FTBaseGenerateComplexFFTPlan: stack ptr!");
|
||||
}
|
||||
assert(stackptr==0);
|
||||
}
|
||||
|
||||
|
||||
@@ -1117,17 +1113,13 @@ void PIFFT_float::ftbasegeneratecomplexfftplan(uint n, ftplan * plan) {
|
||||
curplan.plan.resize(planarraysize);
|
||||
int ftbase_ftbasecffttask = 0;
|
||||
ftbase_ftbasegenerateplanrec(n, ftbase_ftbasecffttask, plan, &plansize, &precomputedsize, &planarraysize, &tmpmemsize, &stackmemsize, stackptr);
|
||||
if (stackptr != 0) {
|
||||
return;//ae_assert(stackptr==0, "Internal error in FTBaseGenerateComplexFFTPlan: stack ptr!");
|
||||
}
|
||||
assertm(stackptr==0, "Internal error in FTBaseGenerateComplexFFTPlan");
|
||||
curplan.stackbuf.resize(piMax<int>(stackmemsize, 1)); //ae_vector_set_length(&curplan.stackbuf, ae_maxint(stackmemsize, 1));
|
||||
curplan.tmpbuf.resize(piMax<int>(tmpmemsize, 1)); //ae_vector_set_length(&(curplan.tmpbuf), ae_maxint(tmpmemsize, 1));
|
||||
curplan.precomputed.resize(piMax<int>(precomputedsize, 1)); //ae_vector_set_length(&curplan.precomputed, ae_maxint(precomputedsize, 1));
|
||||
stackptr = 0;
|
||||
ftbase_ftbaseprecomputeplanrec(plan, 0, stackptr);
|
||||
if (stackptr != 0) {
|
||||
return;//ae_assert(stackptr==0, "Internal error in FTBaseGenerateComplexFFTPlan: stack ptr!");
|
||||
}
|
||||
assertm(stackptr==0, "Internal error in FTBaseGenerateComplexFFTPlan");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -59,12 +59,6 @@ public:
|
||||
template<typename Type>
|
||||
PICout operator <<(PICout & s, const PIPoint<Type> & v) {s.setControl(0, true); s << "Point{" << v.x << ", " << v.y << "}"; s.restoreControl(); return s;}
|
||||
|
||||
template<typename Type>
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIPoint<Type> & v) {s << v.x << v.y; return s;}
|
||||
|
||||
template<typename Type>
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIPoint<Type> & v) {s >> v.x >> v.y; return s;}
|
||||
|
||||
|
||||
typedef PIPoint<int> PIPointi;
|
||||
typedef PIPoint<uint> PIPointu;
|
||||
@@ -145,12 +139,6 @@ public:
|
||||
template<typename Type>
|
||||
PICout operator <<(PICout & s, const PIRect<Type> & v) {s.setControl(0, true); s << "Rect{" << v.x0 << ", " << v.y0 << "; " << v.x1 - v.x0 << ", " << v.y1 - v.y0 << "}"; s.restoreControl(); return s;}
|
||||
|
||||
template<typename Type>
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIRect<Type> & v) {s << v.x0 << v.x1 << v.y0 << v.y1; return s;}
|
||||
|
||||
template<typename Type>
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIRect<Type> & v) {s >> v.x0 >> v.x1 >> v.y0 >> v.y1; return s;}
|
||||
|
||||
|
||||
typedef PIRect<int> PIRecti;
|
||||
typedef PIRect<uint> PIRectu;
|
||||
|
||||
@@ -95,12 +95,10 @@
|
||||
const double deg2rad = M_PI_180;
|
||||
const double rad2deg = M_180_PI;
|
||||
|
||||
inline int sign(const float & x) {return (x < 0.) ? -1 : (x > 0. ? 1 : 0);}
|
||||
inline int sign(const double & x) {return (x < 0.) ? -1 : (x > 0. ? 1 : 0);}
|
||||
inline int sign(const float & x) {return (x < 0.f) ? -1 : (x > 0.f ? 1 : 0);}
|
||||
inline int sign(const double & x) {return (x < 0. ) ? -1 : (x > 0. ? 1 : 0);}
|
||||
inline int sign(const ldouble & x) {return (x < 0.L) ? -1 : (x > 0.L ? 1 : 0);}
|
||||
inline int pow2(const int p) {return 1 << p;}
|
||||
inline int sqr(const int v) {return v * v;}
|
||||
inline float sqr(const float & v) {return v * v;}
|
||||
inline double sqr(const double & v) {return v * v;}
|
||||
inline double sinc(const double & v) {if (v == 0.) return 1.; double t = M_PI * v; return sin(t) / t;}
|
||||
|
||||
PIP_EXPORT double piJ0(const double & v);
|
||||
@@ -109,22 +107,27 @@ PIP_EXPORT double piJn(int n, const double & v);
|
||||
PIP_EXPORT double piY0(const double & v);
|
||||
PIP_EXPORT double piY1(const double & v);
|
||||
PIP_EXPORT double piYn(int n, const double & v);
|
||||
inline double toDb(double val) {return 10. * log10(val);}
|
||||
inline double fromDb(double val) {return pow(10., val / 10.);}
|
||||
inline double toRad(double deg) {return deg * M_PI_180;}
|
||||
inline double toDeg(double rad) {return rad * M_180_PI;}
|
||||
|
||||
inline constexpr float toRad(float deg) {return deg * M_PI_180;}
|
||||
inline constexpr double toRad(double deg) {return deg * M_PI_180;}
|
||||
inline constexpr ldouble toRad(ldouble deg) {return deg * M_PI_180;}
|
||||
inline constexpr float toDeg(float rad) {return rad * M_180_PI;}
|
||||
inline constexpr double toDeg(double rad) {return rad * M_180_PI;}
|
||||
inline constexpr ldouble toDeg(ldouble rad) {return rad * M_180_PI;}
|
||||
template <typename T> inline constexpr T sqr(const T & v) {return v * v;}
|
||||
template <typename T> inline constexpr T toDb (T val) {return T(10.) * std::log10(val);}
|
||||
template <typename T> inline constexpr T fromDb(T val) {return std::pow(T(10.), val / T(10.));}
|
||||
|
||||
// [-1 ; 1]
|
||||
PIP_EXPORT double randomd();
|
||||
// [-1 ; 1] normal
|
||||
PIP_EXPORT double randomn(double dv = 0., double sv = 1.);
|
||||
|
||||
|
||||
inline PIVector<double> abs(const PIVector<double> & v) {
|
||||
PIVector<double> result;
|
||||
template<typename T> inline PIVector<T> piAbs(const PIVector<T> & v) {
|
||||
PIVector<T> result;
|
||||
result.resize(v.size());
|
||||
for (uint i = 0; i < v.size(); i++)
|
||||
result[i] = fabs(v[i]);
|
||||
result[i] = piAbs<T>(v[i]);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,22 +47,6 @@ const complexld complexld_i(0., 1.);
|
||||
const complexld complexld_0(0.);
|
||||
const complexld complexld_1(1.);
|
||||
|
||||
__PICONTAINERS_SIMPLE_TYPE__(complexi)
|
||||
__PICONTAINERS_SIMPLE_TYPE__(complexs)
|
||||
__PICONTAINERS_SIMPLE_TYPE__(complexf)
|
||||
__PICONTAINERS_SIMPLE_TYPE__(complexd)
|
||||
__PICONTAINERS_SIMPLE_TYPE__(complexld)
|
||||
__PIVECTOR2D_SIMPLE_TYPE__(complexi)
|
||||
__PIVECTOR2D_SIMPLE_TYPE__(complexs)
|
||||
__PIVECTOR2D_SIMPLE_TYPE__(complexf)
|
||||
__PIVECTOR2D_SIMPLE_TYPE__(complexd)
|
||||
__PIVECTOR2D_SIMPLE_TYPE__(complexld)
|
||||
__PIBYTEARRAY_SIMPLE_TYPE__(complexi)
|
||||
__PIBYTEARRAY_SIMPLE_TYPE__(complexs)
|
||||
__PIBYTEARRAY_SIMPLE_TYPE__(complexf)
|
||||
__PIBYTEARRAY_SIMPLE_TYPE__(complexd)
|
||||
__PIBYTEARRAY_SIMPLE_TYPE__(complexld)
|
||||
|
||||
inline complexd sign(const complexd & x) {return complexd(sign(x.real()), sign(x.imag()));}
|
||||
|
||||
inline complexd round(const complexd & c) {return complexd(piRound<double>(c.real()), piRound<double>(c.imag()));}
|
||||
@@ -85,20 +69,6 @@ inline complexd log10(const complexd & c) {return log(c) / M_LN10;}
|
||||
template<typename T>
|
||||
inline PICout operator <<(PICout s, const complex<T> & v) {s.space(); s.setControl(0, true); s << "(" << v.real() << "; " << v.imag() << ")"; s.restoreControl(); return s;}
|
||||
|
||||
//! \relatesalso PIByteArray \brief Store operator
|
||||
inline PIByteArray & operator <<(PIByteArray & s, complexf v) {float t; t = v.real(); s << t; t = v.imag(); s << t; return s;}
|
||||
//! \relatesalso PIByteArray \brief Store operator
|
||||
inline PIByteArray & operator <<(PIByteArray & s, complexd v) {double t; t = v.real(); s << t; t = v.imag(); s << t; return s;}
|
||||
//! \relatesalso PIByteArray \brief Store operator
|
||||
inline PIByteArray & operator <<(PIByteArray & s, complexld v) {ldouble t; t = v.real(); s << t; t = v.imag(); s << t; return s;}
|
||||
|
||||
//! \relatesalso PIByteArray \brief Restore operator
|
||||
inline PIByteArray & operator >>(PIByteArray & s, complexf & v) {float t0, t1; s >> t0; s >> t1; v = complexf(t0, t1); return s;}
|
||||
//! \relatesalso PIByteArray \brief Restore operator
|
||||
inline PIByteArray & operator >>(PIByteArray & s, complexd & v) {double t0, t1; s >> t0; s >> t1; v = complexd(t0, t1); return s;}
|
||||
//! \relatesalso PIByteArray \brief Restore operator
|
||||
inline PIByteArray & operator >>(PIByteArray & s, complexld & v) {ldouble t0, t1; s >> t0; s >> t1; v = complexld(t0, t1); return s;}
|
||||
|
||||
|
||||
inline PIVector<double> abs(const PIVector<complexd> & v) {
|
||||
PIVector<double> result;
|
||||
@@ -117,4 +87,33 @@ inline PIVector2D<double> abs(const PIVector2D<complexd> & v) {
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief floating point number specific comparison between value passed as parameter and zero
|
||||
*
|
||||
* @param v floating point parameter for comparison
|
||||
* @return true if v in locality of zero, otherwise false
|
||||
*/
|
||||
template<typename T, typename std::enable_if<std::is_floating_point<T>::value, int>::type = 0>
|
||||
inline bool PIMathFloatNullCompare(const T v) {
|
||||
static_assert(std::is_floating_point<T>::value, "Type must be floating point");
|
||||
return (piAbs(v) < T(1E-200));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief floating point number specific comparison between parameter value and zero.
|
||||
*
|
||||
* @param v complex with floating point real and imag parts
|
||||
* @return true if absolute of v in locality of zero, otherwise false
|
||||
*/
|
||||
template<typename T,typename std::enable_if<
|
||||
std::is_floating_point<decltype(T::real)>::value &&
|
||||
std::is_floating_point<decltype(T::imag)>::value
|
||||
, int>::type = 0>
|
||||
inline bool PIMathFloatNullCompare(const T v) {
|
||||
static_assert(std::is_floating_point<decltype(v.real)>::value, "Type must be floating point");
|
||||
static_assert(std::is_floating_point<decltype(v.imag)>::value, "Type must be floating point");
|
||||
return (abs(v) < float(1E-200));
|
||||
}
|
||||
|
||||
#endif // PIMATHCOMPLEX_H
|
||||
|
||||
@@ -28,49 +28,12 @@
|
||||
#include "pimathvector.h"
|
||||
#include "pimathcomplex.h"
|
||||
|
||||
/**
|
||||
* @brief Inline funtion of compare with zero different types
|
||||
*
|
||||
* @param v is input parameter of type T
|
||||
* @return true if zero, false if not zero
|
||||
*/
|
||||
template<typename T>
|
||||
inline bool _PIMathMatrixNullCompare(const T v) {
|
||||
static_assert(std::is_floating_point<T>::value, "Type must be floating point");
|
||||
return (piAbs(v) < T(1E-200));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Inline funtion of compare with zero colmplexf type
|
||||
*
|
||||
* @param v is input parameter of type colmplexf
|
||||
* @return true if zero, false if not zero
|
||||
*/
|
||||
template<>
|
||||
inline bool _PIMathMatrixNullCompare<complexf>(const complexf v) {
|
||||
return (abs(v) < float(1E-200));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Inline funtion of compare with zero complexd type
|
||||
*
|
||||
* @param v is input parameter of type colmplexd
|
||||
* @return true if zero, false if not zero
|
||||
*/
|
||||
template<>
|
||||
inline bool _PIMathMatrixNullCompare<complexd>(const complexd v) {
|
||||
return (abs(v) < double(1E-200));
|
||||
}
|
||||
|
||||
|
||||
/// Matrix templated
|
||||
|
||||
#define PIMM_FOR(r, c) for (uint c = 0; c < Cols; ++c) { for (uint r = 0; r < Rows; ++r) {
|
||||
#define PIMM_FOR_WB(r, c) for (uint c = 0; c < Cols; ++c) for (uint r = 0; r < Rows; ++r) // without brakes
|
||||
#define PIMM_FOR_I(r, c) for (uint r = 0; r < Rows; ++r) { for (uint c = 0; c < Cols; ++c) {
|
||||
#define PIMM_FOR_I_WB(r, c) for (uint r = 0; r < Rows; ++r) for (uint c = 0; c < Cols; ++c) // without brakes
|
||||
#define PIMM_FOR_C(v) for (uint v = 0; v < Cols; ++v)
|
||||
#define PIMM_FOR_R(v) for (uint v = 0; v < Rows; ++v)
|
||||
#define PIMM_FOR for (uint r = 0; r < Rows; ++r) for (uint c = 0; c < Cols; ++c)
|
||||
#define PIMM_FOR_C for (uint i = 0; i < Cols; ++i)
|
||||
#define PIMM_FOR_R for (uint i = 0; i < Rows; ++i)
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
@@ -90,22 +53,26 @@ class PIP_EXPORT PIMathMatrixT {
|
||||
static_assert(Cols > 0, "Column count must be > 0");
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor that calls the private resize method
|
||||
*
|
||||
* @return identitied matrix of type PIMathMatrixT
|
||||
* @brief Constructs PIMathMatrixT that is filled by \a new_value
|
||||
*/
|
||||
PIMathMatrixT() { resize(Rows, Cols); }
|
||||
PIMathMatrixT(const Type &new_value = Type()) {PIMM_FOR m[r][c] = new_value;}
|
||||
|
||||
/**
|
||||
* @brief Constructor that calls the private resize method
|
||||
*
|
||||
* @param val is the PIVector with which the matrix is filled
|
||||
* @return identitied matrix of type PIMathMatrixT
|
||||
* @brief Contructs PIMathMatrixT from PIVector
|
||||
*/
|
||||
PIMathMatrixT(const PIVector<Type> &val) {
|
||||
resize(Rows, Cols);
|
||||
assert(Rows*Cols == val.size());
|
||||
int i = 0;
|
||||
PIMM_FOR_I_WB(r, c) m[r][c] = val[i++];
|
||||
PIMM_FOR m[r][c] = val[i++];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Contructs PIMathMatrixT from C++11 initializer list
|
||||
*/
|
||||
PIMathMatrixT(std::initializer_list<Type> init_list) {
|
||||
assert(Rows*Cols == init_list.size());
|
||||
int i = 0;
|
||||
PIMM_FOR m[r][c] = init_list.begin()[i++];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -115,98 +82,23 @@ public:
|
||||
*/
|
||||
static _CMatrix identity() {
|
||||
_CMatrix tm = _CMatrix();
|
||||
PIMM_FOR_WB(r, c) tm.m[r][c] = (c == r ? Type(1) : Type(0));
|
||||
PIMM_FOR tm.m[r][c] = (c == r ? Type(1) : Type(0));
|
||||
return tm;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Creates a matrix that is filled with elements
|
||||
*
|
||||
* @param v is a parameter the type and value of which is selected and later filled into the matrix
|
||||
* @return filled matrix of type PIMathMatrixT
|
||||
*/
|
||||
static _CMatrix filled(const Type &v) {
|
||||
_CMatrix tm;
|
||||
PIMM_FOR_WB(r, c) tm.m[r][c] = v;
|
||||
return tm;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Rotation the matrix by an "angle". Works only with 2x2 matrix,
|
||||
* else return default construction of PIMathMatrixT
|
||||
*
|
||||
* @param angle is the angle of rotation of the matrix
|
||||
* @return rotated matrix
|
||||
*/
|
||||
static _CMatrix rotation(double angle) { return _CMatrix(); }
|
||||
|
||||
/**
|
||||
* @brief Rotation of the matrix by an "angle" along the X axis. Works only with 3x3 matrix,
|
||||
* else return default construction of PIMathMatrixT
|
||||
*
|
||||
* @param angle is the angle of rotation of the matrix along the X axis
|
||||
* @return rotated matrix
|
||||
*/
|
||||
static _CMatrix rotationX(double angle) { return _CMatrix(); }
|
||||
|
||||
/**
|
||||
* @brief Rotation of the matrix by an "angle" along the Y axis. Works only with 3x3 matrix,
|
||||
* else return default construction of PIMathMatrixT
|
||||
*
|
||||
* @param angle is the angle of rotation of the matrix along the Y axis
|
||||
* @return rotated matrix
|
||||
*/
|
||||
static _CMatrix rotationY(double angle) { return _CMatrix(); }
|
||||
|
||||
/**
|
||||
* @brief Rotation of the matrix by an "angle" along the Z axis. Works only with 3x3 matrix,
|
||||
* else return default construction of PIMathMatrixT
|
||||
*
|
||||
* @param angle is the angle of rotation of the matrix along the Z axis
|
||||
* @return rotated matrix
|
||||
*/
|
||||
static _CMatrix rotationZ(double angle) { return _CMatrix(); }
|
||||
|
||||
/**
|
||||
* @brief Scaling the matrix along the X axis by the value "factor". Works only with 3x3 and 2x2 matrix,
|
||||
* else return default construction of PIMathMatrixT
|
||||
*
|
||||
* @param factor is the value of scaling by X axis
|
||||
* @return rotated matrix
|
||||
*/
|
||||
static _CMatrix scaleX(double factor) { return _CMatrix(); }
|
||||
|
||||
/**
|
||||
* @brief Scaling the matrix along the Y axis by the value "factor". Works only with 3x3 and 2x2 matrix,
|
||||
* else return default construction of PIMathMatrixT
|
||||
*
|
||||
* @param factor is the value of scaling by Y axis
|
||||
* @return rotated matrix
|
||||
*/
|
||||
static _CMatrix scaleY(double factor) { return _CMatrix(); }
|
||||
|
||||
/**
|
||||
* @brief Scaling the matrix along the Z axis by the value "factor". Works only with 3x3 matrix,
|
||||
* else return default construction of PIMathMatrixT
|
||||
*
|
||||
* @param factor is the value of scaling by Z axis
|
||||
* @return rotated matrix
|
||||
*/
|
||||
static _CMatrix scaleZ(double factor) { return _CMatrix(); }
|
||||
|
||||
/**
|
||||
* @brief Method which returns number of columns in matrix
|
||||
*
|
||||
* @return type uint shows number of columns
|
||||
*/
|
||||
uint cols() const { return Cols; }
|
||||
constexpr uint cols() const {return Cols;}
|
||||
|
||||
/**
|
||||
* @brief Method which returns number of rows in matrix
|
||||
*
|
||||
* @return type uint shows number of rows
|
||||
*/
|
||||
uint rows() const { return Rows; }
|
||||
constexpr uint rows() const {return Rows;}
|
||||
|
||||
/**
|
||||
* @brief Method which returns the selected column in PIMathVectorT format.
|
||||
@@ -217,7 +109,7 @@ public:
|
||||
*/
|
||||
_CMCol col(uint index) {
|
||||
_CMCol tv;
|
||||
PIMM_FOR_R(i) tv[i] = m[i][index];
|
||||
PIMM_FOR_R tv[i] = m[i][index];
|
||||
return tv;
|
||||
}
|
||||
|
||||
@@ -230,7 +122,7 @@ public:
|
||||
*/
|
||||
_CMRow row(uint index) {
|
||||
_CMRow tv;
|
||||
PIMM_FOR_C(i) tv[i] = m[index][i];
|
||||
PIMM_FOR_C tv[i] = m[index][i];
|
||||
return tv;
|
||||
}
|
||||
|
||||
@@ -243,7 +135,7 @@ public:
|
||||
* @return matrix type _CMatrix
|
||||
*/
|
||||
_CMatrix &setCol(uint index, const _CMCol &v) {
|
||||
PIMM_FOR_R(i) m[i][index] = v[i];
|
||||
PIMM_FOR_R m[i][index] = v[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -256,7 +148,7 @@ public:
|
||||
* @return matrix type _CMatrix
|
||||
*/
|
||||
_CMatrix &setRow(uint index, const _CMRow &v) {
|
||||
PIMM_FOR_C(i) m[index][i] = v[i];
|
||||
PIMM_FOR_C m[index][i] = v[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -268,13 +160,8 @@ public:
|
||||
* @param r1 is the number of the second selected row
|
||||
* @return matrix type _CMatrix
|
||||
*/
|
||||
_CMatrix &swapRows(uint r0, uint r1) {
|
||||
Type t;
|
||||
PIMM_FOR_C(i) {
|
||||
t = m[r0][i];
|
||||
m[r0][i] = m[r1][i];
|
||||
m[r1][i] = t;
|
||||
}
|
||||
_CMatrix &swapRows(uint rf, uint rs) {
|
||||
PIMM_FOR_C piSwap<Type>(m[rf][i], m[rs][i]);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -286,13 +173,8 @@ public:
|
||||
* @param c1 is the number of the second selected column
|
||||
* @return matrix type _CMatrix
|
||||
*/
|
||||
_CMatrix &swapCols(uint c0, uint c1) {
|
||||
Type t;
|
||||
PIMM_FOR_R(i) {
|
||||
t = m[i][c0];
|
||||
m[i][c0] = m[i][c1];
|
||||
m[i][c1] = t;
|
||||
}
|
||||
_CMatrix &swapCols(uint cf, uint cs) {
|
||||
PIMM_FOR_R piSwap<Type>(m[i][cf], m[i][cs]);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -303,7 +185,7 @@ public:
|
||||
* @return filled matrix type _CMatrix
|
||||
*/
|
||||
_CMatrix &fill(const Type &v) {
|
||||
PIMM_FOR_WB(r, c) m[r][c] = v;
|
||||
PIMM_FOR m[r][c] = v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -312,7 +194,7 @@ public:
|
||||
*
|
||||
* @return true if matrix is square, else false
|
||||
*/
|
||||
bool isSquare() const { return cols() == rows(); }
|
||||
constexpr bool isSquare() const { return Rows == Cols; }
|
||||
|
||||
/**
|
||||
* @brief Method which checks if main diagonal of matrix consists of ones and another elements are zeros
|
||||
@@ -320,7 +202,7 @@ public:
|
||||
* @return true if matrix is identitied, else false
|
||||
*/
|
||||
bool isIdentity() const {
|
||||
PIMM_FOR_WB(r, c) if ((c == r) ? m[r][c] != Type(1) : m[r][c] != Type(0)) return false;
|
||||
PIMM_FOR if ((c == r) ? m[r][c] != Type(1) : m[r][c] != Type(0)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -330,34 +212,45 @@ public:
|
||||
* @return true if matrix is null, else false
|
||||
*/
|
||||
bool isNull() const {
|
||||
PIMM_FOR_WB(r, c) if (m[r][c] != Type(0)) return false;
|
||||
PIMM_FOR if (m[r][c] != Type(0)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Full access to elements reference by row "row" and col "col".
|
||||
* If you enter an index out of the border of the matrix there will be "undefined behavior"
|
||||
*
|
||||
* @param row is a parameter that shows the row number of the matrix of the selected element
|
||||
* @param col is a parameter that shows the column number of the matrix of the selected element
|
||||
* @return reference to element of matrix by row "row" and col "col"
|
||||
*/
|
||||
Type &at(uint row, uint col) { return m[row][col]; }
|
||||
|
||||
/**
|
||||
* @brief Full access to element by row "row" and col "col".
|
||||
* @brief Read-only access to element by \a row and \a col.
|
||||
* If you enter an index out of the border of the matrix there will be "undefined behavior"
|
||||
*
|
||||
* @param row is a parameter that shows the row number of the matrix of the selected element
|
||||
* @param col is a parameter that shows the column number of the matrix of the selected element
|
||||
* @return element of matrix by row "row" and col "col"
|
||||
* @param row of matrix
|
||||
* @param col of matrix
|
||||
* @return copy of element of matrix
|
||||
*/
|
||||
Type at(uint row, uint col) const { return m[row][col]; }
|
||||
|
||||
/**
|
||||
* @brief Full access to element by \a row and \a col.
|
||||
* If you enter an index out of the border of the matrix there will be "undefined behavior"
|
||||
*
|
||||
* @param row of matrix
|
||||
* @param col of matrix
|
||||
* @return element of matrix
|
||||
*/
|
||||
inline Type & element(uint row, uint col) {return m[row][col];}
|
||||
|
||||
/**
|
||||
* @brief Read-only access to element by \a row and \a col.
|
||||
* If you enter an index out of the border of the matrix there will be "undefined behavior"
|
||||
*
|
||||
* @param row of matrix
|
||||
* @param col of matrix
|
||||
* @return element of matrix
|
||||
*/
|
||||
inline const Type & element(uint row, uint col) const {return m[row][col];}
|
||||
|
||||
/**
|
||||
* @brief Full access to the matrix row pointer. If you enter an index out of the border of the matrix there will be "undefined behavior"
|
||||
*
|
||||
* @param row is a row of necessary matrix
|
||||
* @param row of matrix
|
||||
* @return matrix row pointer
|
||||
*/
|
||||
Type *operator[](uint row) { return m[row]; }
|
||||
@@ -365,37 +258,26 @@ public:
|
||||
/**
|
||||
* @brief Read-only access to the matrix row pointer. If you enter an index out of the border of the matrix there will be "undefined behavior"
|
||||
*
|
||||
* @param row is a row of necessary matrix
|
||||
* @param row of matrix
|
||||
* @return matrix row pointer
|
||||
*/
|
||||
const Type *operator[](uint row) const { return m[row]; }
|
||||
const Type *operator[](uint row) const {return m[row];}
|
||||
|
||||
/**
|
||||
* @brief Matrix assignment to matrix "sm"
|
||||
* @brief Matrix compare
|
||||
*
|
||||
* @param sm matrix for the assigment
|
||||
* @return matrix equal with sm
|
||||
*/
|
||||
_CMatrix &operator=(const _CMatrix &sm) {
|
||||
memcpy(m, sm.m, sizeof(Type) * Cols * Rows);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compare with matrix "sm"
|
||||
*
|
||||
* @param sm matrix for the compare
|
||||
* @param sm matrix for compare
|
||||
* @return if matrices are equal true, else false
|
||||
*/
|
||||
bool operator==(const _CMatrix &sm) const {
|
||||
PIMM_FOR_WB(r, c) if (m[r][c] != sm.m[r][c]) return false;
|
||||
PIMM_FOR if (m[r][c] != sm.m[r][c]) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compare with matrix "sm"
|
||||
* @brief Matrix negative compare
|
||||
*
|
||||
* @param sm matrix for the compare
|
||||
* @param sm matrix for compare
|
||||
* @return if matrices are not equal true, else false
|
||||
*/
|
||||
bool operator!=(const _CMatrix &sm) const { return !(*this == sm); }
|
||||
@@ -405,28 +287,33 @@ public:
|
||||
*
|
||||
* @param sm matrix for the addition assigment
|
||||
*/
|
||||
void operator+=(const _CMatrix &sm) { PIMM_FOR_WB(r, c) m[r][c] += sm.m[r][c]; }
|
||||
void operator+=(const _CMatrix &sm) {PIMM_FOR m[r][c] += sm.m[r][c];}
|
||||
|
||||
/**
|
||||
* @brief Subtraction assignment with matrix "sm"
|
||||
*
|
||||
* @param sm matrix for the subtraction assigment
|
||||
*/
|
||||
void operator-=(const _CMatrix &sm) { PIMM_FOR_WB(r, c) m[r][c] -= sm.m[r][c]; }
|
||||
void operator-=(const _CMatrix &sm) {PIMM_FOR m[r][c] -= sm.m[r][c];}
|
||||
|
||||
/**
|
||||
* @brief Multiplication assignment with value "v"
|
||||
*
|
||||
* @param v value for the multiplication assigment
|
||||
*/
|
||||
void operator*=(const Type &v) { PIMM_FOR_WB(r, c) m[r][c] *= v; }
|
||||
void operator*=(const Type &v) {
|
||||
PIMM_FOR m[r][c] *= v;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Division assignment with value "v"
|
||||
*
|
||||
* @param v value for the division assigment
|
||||
*/
|
||||
void operator/=(const Type &v) { PIMM_FOR_WB(r, c) m[r][c] /= v; }
|
||||
void operator/=(const Type &v) {
|
||||
assert(piAbs<Type>(v) > PIMATHVECTOR_ZERO_CMP);
|
||||
PIMM_FOR m[r][c] /= v;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Matrix substraction
|
||||
@@ -435,7 +322,7 @@ public:
|
||||
*/
|
||||
_CMatrix operator-() const {
|
||||
_CMatrix tm;
|
||||
PIMM_FOR_WB(r, c) tm.m[r][c] = -m[r][c];
|
||||
PIMM_FOR tm.m[r][c] = -m[r][c];
|
||||
return tm;
|
||||
}
|
||||
|
||||
@@ -447,7 +334,7 @@ public:
|
||||
*/
|
||||
_CMatrix operator+(const _CMatrix &sm) const {
|
||||
_CMatrix tm = _CMatrix(*this);
|
||||
PIMM_FOR_WB(r, c) tm.m[r][c] += sm.m[r][c];
|
||||
PIMM_FOR tm.m[r][c] += sm.m[r][c];
|
||||
return tm;
|
||||
}
|
||||
|
||||
@@ -459,7 +346,7 @@ public:
|
||||
*/
|
||||
_CMatrix operator-(const _CMatrix &sm) const {
|
||||
_CMatrix tm = _CMatrix(*this);
|
||||
PIMM_FOR_WB(r, c) tm.m[r][c] -= sm.m[r][c];
|
||||
PIMM_FOR tm.m[r][c] -= sm.m[r][c];
|
||||
return tm;
|
||||
}
|
||||
|
||||
@@ -471,7 +358,7 @@ public:
|
||||
*/
|
||||
_CMatrix operator*(const Type &v) const {
|
||||
_CMatrix tm = _CMatrix(*this);
|
||||
PIMM_FOR_WB(r, c) tm.m[r][c] *= v;
|
||||
PIMM_FOR tm.m[r][c] *= v;
|
||||
return tm;
|
||||
}
|
||||
|
||||
@@ -482,8 +369,9 @@ public:
|
||||
* @return the result of matrix division
|
||||
*/
|
||||
_CMatrix operator/(const Type &v) const {
|
||||
assert(piAbs<Type>(v) > PIMATHVECTOR_ZERO_CMP);
|
||||
_CMatrix tm = _CMatrix(*this);
|
||||
PIMM_FOR_WB(r, c) tm.m[r][c] /= v;
|
||||
PIMM_FOR tm.m[r][c] /= v;
|
||||
return tm;
|
||||
}
|
||||
|
||||
@@ -501,10 +389,21 @@ public:
|
||||
if (ok) *ok = k;
|
||||
if (!k) return ret;
|
||||
ret = Type(1);
|
||||
for (uint c = 0; c < Cols; ++c)
|
||||
for (uint r = 0; r < Rows; ++r)
|
||||
if (r == c)
|
||||
ret *= m[r][c];
|
||||
PIMM_FOR if (r == c) ret *= m[r][c];
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Trace of the matrix is calculated. Works only with square matrix, nonzero matrices and invertible matrix
|
||||
*
|
||||
* @return matrix trace
|
||||
*/
|
||||
Type trace() const {
|
||||
static_assert(Rows == Cols, "Works only with square matrix");
|
||||
Type ret = Type(0);
|
||||
for (uint i = 0; i < Cols; ++i) {
|
||||
ret += m[i][i];
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -515,10 +414,7 @@ public:
|
||||
* @return copy of transformed upper triangular matrix
|
||||
*/
|
||||
_CMatrix &toUpperTriangular(bool *ok = 0) {
|
||||
if (Cols != Rows) {
|
||||
if (ok != 0) *ok = false;
|
||||
return *this;
|
||||
}
|
||||
static_assert(Rows == Cols, "Works only with square matrix");
|
||||
_CMatrix smat(*this);
|
||||
bool ndet;
|
||||
uint crow;
|
||||
@@ -540,7 +436,7 @@ public:
|
||||
for (uint k = i; k < Cols; ++k) smat.m[k][j] -= mul * smat.m[k][i];
|
||||
}
|
||||
if (i < Cols - 1) {
|
||||
if (fabs(smat.m[i + 1][i + 1]) < Type(1E-200)) {
|
||||
if (piAbs<Type>(smat.m[i + 1][i + 1]) < Type(1E-200)) {
|
||||
if (ok != 0) *ok = false;
|
||||
return *this;
|
||||
}
|
||||
@@ -558,7 +454,7 @@ public:
|
||||
* @return copy of inverted matrix
|
||||
*/
|
||||
_CMatrix &invert(bool *ok = 0) {
|
||||
static_assert(Cols == Rows, "Only square matrix invertable");
|
||||
static_assert(Rows == Cols, "Works only with square matrix");
|
||||
_CMatrix mtmp = _CMatrix::identity(), smat(*this);
|
||||
bool ndet;
|
||||
uint crow;
|
||||
@@ -584,7 +480,7 @@ public:
|
||||
for (uint k = 0; k < Cols; ++k) mtmp.m[k][j] -= mul * mtmp.m[k][i];
|
||||
}
|
||||
if (i < Cols - 1) {
|
||||
if (fabs(smat.m[i + 1][i + 1]) < Type(1E-200)) {
|
||||
if (piAbs<Type>(smat.m[i + 1][i + 1]) < Type(1E-200)) {
|
||||
if (ok != 0) *ok = false;
|
||||
return *this;
|
||||
}
|
||||
@@ -624,111 +520,43 @@ public:
|
||||
*/
|
||||
_CMatrixI transposed() const {
|
||||
_CMatrixI tm;
|
||||
PIMM_FOR_WB(r, c) tm[c][r] = m[r][c];
|
||||
PIMM_FOR tm[c][r] = m[r][c];
|
||||
return tm;
|
||||
}
|
||||
|
||||
private:
|
||||
void resize(uint rows_, uint cols_, const Type &new_value = Type()) {
|
||||
r_ = rows_;
|
||||
c_ = cols_;
|
||||
PIMM_FOR_WB(r, c) m[r][c] = new_value;
|
||||
_CMatrix rotate(Type angle) {
|
||||
static_assert(Rows == 2 && Cols == 2, "Works only with 2x2 matrix");
|
||||
Type c = std::cos(angle);
|
||||
Type s = std::sin(angle);
|
||||
PIMathMatrixT<2u, 2u> tm;
|
||||
tm[0][0] = tm[1][1] = c;
|
||||
tm[0][1] = -s;
|
||||
tm[1][0] = s;
|
||||
*this = *this * tm;
|
||||
return *this;
|
||||
}
|
||||
|
||||
int c_, r_;
|
||||
private:
|
||||
Type m[Rows][Cols];
|
||||
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
template<>
|
||||
inline PIMathMatrixT<2u, 2u> PIMathMatrixT<2u, 2u>::rotation(double angle) {
|
||||
double c = cos(angle), s = sin(angle);
|
||||
PIMathMatrixT<2u, 2u> tm;
|
||||
tm[0][0] = tm[1][1] = c;
|
||||
tm[0][1] = -s;
|
||||
tm[1][0] = s;
|
||||
return tm;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline PIMathMatrixT<2u, 2u> PIMathMatrixT<2u, 2u>::scaleX(double factor) {
|
||||
PIMathMatrixT<2u, 2u> tm;
|
||||
tm[0][0] = factor;
|
||||
tm[1][1] = 1.;
|
||||
return tm;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline PIMathMatrixT<2u, 2u> PIMathMatrixT<2u, 2u>::scaleY(double factor) {
|
||||
PIMathMatrixT<2u, 2u> tm;
|
||||
tm[0][0] = 1.;
|
||||
tm[1][1] = factor;
|
||||
return tm;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline PIMathMatrixT<3u, 3u> PIMathMatrixT<3u, 3u>::rotationX(double angle) {
|
||||
double c = cos(angle), s = sin(angle);
|
||||
PIMathMatrixT<3u, 3u> tm;
|
||||
tm[0][0] = 1.;
|
||||
tm[1][1] = tm[2][2] = c;
|
||||
tm[2][1] = s;
|
||||
tm[1][2] = -s;
|
||||
return tm;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline PIMathMatrixT<3u, 3u> PIMathMatrixT<3u, 3u>::rotationY(double angle) {
|
||||
double c = cos(angle), s = sin(angle);
|
||||
PIMathMatrixT<3u, 3u> tm;
|
||||
tm[1][1] = 1.;
|
||||
tm[0][0] = tm[2][2] = c;
|
||||
tm[2][0] = -s;
|
||||
tm[0][2] = s;
|
||||
return tm;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline PIMathMatrixT<3u, 3u> PIMathMatrixT<3u, 3u>::rotationZ(double angle) {
|
||||
double c = cos(angle), s = sin(angle);
|
||||
PIMathMatrixT<3u, 3u> tm;
|
||||
tm[2][2] = 1.;
|
||||
tm[0][0] = tm[1][1] = c;
|
||||
tm[1][0] = s;
|
||||
tm[0][1] = -s;
|
||||
return tm;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline PIMathMatrixT<3u, 3u> PIMathMatrixT<3u, 3u>::scaleX(double factor) {
|
||||
PIMathMatrixT<3u, 3u> tm;
|
||||
tm[1][1] = tm[2][2] = 1.;
|
||||
tm[0][0] = factor;
|
||||
return tm;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline PIMathMatrixT<3u, 3u> PIMathMatrixT<3u, 3u>::scaleY(double factor) {
|
||||
PIMathMatrixT<3u, 3u> tm;
|
||||
tm[0][0] = tm[2][2] = 1.;
|
||||
tm[1][1] = factor;
|
||||
return tm;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline PIMathMatrixT<3u, 3u> PIMathMatrixT<3u, 3u>::scaleZ(double factor) {
|
||||
PIMathMatrixT<3u, 3u> tm;
|
||||
tm[0][0] = tm[1][1] = 1.;
|
||||
tm[2][2] = factor;
|
||||
return tm;
|
||||
}
|
||||
|
||||
#ifdef PIP_STD_IOSTREAM
|
||||
template<uint Rows, uint Cols, typename Type>
|
||||
inline std::ostream & operator <<(std::ostream & s, const PIMathMatrixT<Rows, Cols, Type> & m) {s << "{"; PIMM_FOR_I(r, c) s << m[r][c]; if (c < Cols - 1 || r < Rows - 1) s << ", ";} if (r < Rows - 1) s << std::endl << " ";} s << "}"; return s;}
|
||||
inline std::ostream & operator <<(std::ostream & s, const PIMathMatrixT<Rows, Cols, Type> & m) {
|
||||
s << "{";
|
||||
for (uint r = 0; r < Rows; ++r) {
|
||||
for (uint c = 0; c < Cols; ++c) {
|
||||
s << m[r][c];
|
||||
if (c < Cols - 1 || r < Rows - 1) s << ", ";
|
||||
}
|
||||
if (r < Rows - 1) s << std::endl << " ";
|
||||
}
|
||||
s << "}";
|
||||
return s;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -741,9 +569,13 @@ inline std::ostream & operator <<(std::ostream & s, const PIMathMatrixT<Rows, Co
|
||||
template<uint Rows, uint Cols, typename Type>
|
||||
inline PICout operator<<(PICout s, const PIMathMatrixT<Rows, Cols, Type> &m) {
|
||||
s << "{";
|
||||
PIMM_FOR_I(r, c) s << m[r][c];
|
||||
if (c < Cols - 1 || r < Rows - 1) s << ", "; }
|
||||
if (r < Rows - 1) s << PICoutManipulators::NewLine << " "; }
|
||||
for (uint r = 0; r < Rows; ++r) {
|
||||
for (uint c = 0; c < Cols; ++c) {
|
||||
s << m[r][c];
|
||||
if (c < Cols - 1 || r < Rows - 1) s << ", ";
|
||||
}
|
||||
if (r < Rows - 1) s << PICoutManipulators::NewLine << " ";
|
||||
}
|
||||
s << "}";
|
||||
return s;
|
||||
}
|
||||
@@ -838,9 +670,6 @@ template<typename Type>
|
||||
class PIMathMatrix;
|
||||
|
||||
#undef PIMM_FOR
|
||||
#undef PIMM_FOR_WB
|
||||
#undef PIMM_FOR_I
|
||||
#undef PIMM_FOR_I_WB
|
||||
#undef PIMM_FOR_C
|
||||
#undef PIMM_FOR_R
|
||||
|
||||
@@ -850,11 +679,10 @@ class PIMathMatrix;
|
||||
|
||||
/// Matrix
|
||||
|
||||
#define PIMM_FOR(c, r) for (uint c = 0; c < _V2D::cols_; ++c) for (uint r = 0; r < _V2D::rows_; ++r)
|
||||
#define PIMM_FOR_I(c, r) for (uint r = 0; r < _V2D::rows_; ++r) for (uint c = 0; c < _V2D::cols_; ++c)
|
||||
#define PIMM_FOR_A(v) for (uint v = 0; v < _V2D::mat.size(); ++v)
|
||||
#define PIMM_FOR_C(v) for (uint v = 0; v < _V2D::cols_; ++v)
|
||||
#define PIMM_FOR_R(v) for (uint v = 0; v < _V2D::rows_; ++v)
|
||||
#define PIMM_FOR for (uint r = 0; r < _V2D::rows_; ++r) for (uint c = 0; c < _V2D::cols_; ++c)
|
||||
#define PIMM_FOR_A for (uint i = 0; i < _V2D::mat.size(); ++i)
|
||||
#define PIMM_FOR_C for (uint i = 0; i < _V2D::cols_; ++i)
|
||||
#define PIMM_FOR_R for (uint i = 0; i < _V2D::rows_; ++i)
|
||||
|
||||
//! \brief A class that works with matrix operations, the input data of which is the data type of the matrix
|
||||
//! @tparam There are can be basic C++ language data and different classes where the arithmetic operators(=, +=, -=, *=, /=, ==, !=, +, -, *, /)
|
||||
@@ -863,7 +691,6 @@ template<typename Type>
|
||||
class PIP_EXPORT PIMathMatrix : public PIVector2D<Type> {
|
||||
typedef PIVector2D<Type> _V2D;
|
||||
typedef PIMathMatrix<Type> _CMatrix;
|
||||
typedef PIMathVector<Type> _CMCol;
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor of class PIMathMatrix, which creates a matrix
|
||||
@@ -884,7 +711,7 @@ public:
|
||||
PIMathMatrix(const uint cols, const uint rows, const PIVector<Type> &val) {
|
||||
_V2D::resize(rows, cols);
|
||||
int i = 0;
|
||||
PIMM_FOR_I(c, r) _V2D::element(r, c) = val[i++];
|
||||
PIMM_FOR _V2D::element(r, c) = val[i++];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -895,7 +722,11 @@ public:
|
||||
PIMathMatrix(const PIVector<PIVector<Type> > &val) {
|
||||
if (!val.isEmpty()) {
|
||||
_V2D::resize(val.size(), val[0].size());
|
||||
PIMM_FOR_I(c, r) _V2D::element(r, c) = val[r][c];
|
||||
for (uint r = 0; r < _V2D::rows_; ++r) {
|
||||
assert(val[r].size() == _V2D::cols_);
|
||||
for (uint c = 0; c < _V2D::cols_; ++c)
|
||||
_V2D::element(r, c) = val[r][c];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -907,7 +738,7 @@ public:
|
||||
PIMathMatrix(const PIVector2D<Type> &val) {
|
||||
if (!val.isEmpty()) {
|
||||
_V2D::resize(val.rows(), val.cols());
|
||||
PIMM_FOR_I(c, r) _V2D::element(r, c) = val.element(r, c);
|
||||
PIMM_FOR _V2D::element(r, c) = val.element(r, c);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -916,7 +747,7 @@ public:
|
||||
*
|
||||
* @param cols is number of matrix column uint type
|
||||
* @param rows is number of matrix row uint type
|
||||
* @return identity matrix of type PIMathMatrix
|
||||
* @return identity matrix(cols,rows)
|
||||
*/
|
||||
static _CMatrix identity(const uint cols, const uint rows) {
|
||||
_CMatrix tm(cols, rows);
|
||||
@@ -930,7 +761,7 @@ public:
|
||||
* @param val is the vector type PIMathVector
|
||||
* @return row matrix of every element that is equal to every element of the vector
|
||||
*/
|
||||
static _CMatrix matrixRow(const PIMathVector<Type> &val) { return _CMatrix(val.size(), 1, val.toVector()); }
|
||||
static _CMatrix matrixRow(const PIMathVector<Type> &val) {return _CMatrix(val.size(), 1, val.toVector());}
|
||||
|
||||
/**
|
||||
* @brief Creates a column matrix of every element that is equal to every element of the vector
|
||||
@@ -938,18 +769,19 @@ public:
|
||||
* @param val is the vector type PIMathVector
|
||||
* @return column matrix of every element that is equal to every element of the vector
|
||||
*/
|
||||
static _CMatrix matrixCol(const PIMathVector<Type> &val) { return _CMatrix(1, val.size(), val.toVector()); }
|
||||
static _CMatrix matrixCol(const PIMathVector<Type> &val) {return _CMatrix(1, val.size(), val.toVector());}
|
||||
|
||||
/**
|
||||
* @brief Set the selected column in matrix. If there are more elements of the vector than elements in the column of the matrix
|
||||
* or index larger than the number of columns otherwise there will be "undefined behavior"
|
||||
* or index larger than the number of columns otherwise there will be "undefined behavior"
|
||||
*
|
||||
* @param index is the number of the selected column
|
||||
* @param v is a vector of the type _CMCol that needs to fill the column
|
||||
* @return matrix type _CMatrix
|
||||
*/
|
||||
_CMatrix &setCol(uint index, const _CMCol &v) {
|
||||
PIMM_FOR_R(i) _V2D::element(i, index) = v[i];
|
||||
_CMatrix &setCol(uint index, const PIMathVector<Type> &v) {
|
||||
assert(_V2D::rows() == v.size());
|
||||
PIMM_FOR_R _V2D::element(i, index) = v[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -960,8 +792,9 @@ public:
|
||||
* @param v is a vector of the type _CMCol that needs to fill the row
|
||||
* @return matrix type _CMatrix
|
||||
*/
|
||||
_CMatrix &setRow(uint index, const _CMCol &v) {
|
||||
PIMM_FOR_C(i) _V2D::element(index, i) = v[i];
|
||||
_CMatrix &setRow(uint index, const PIMathVector<Type> &v) {
|
||||
assert(_V2D::cols() == v.size());
|
||||
PIMM_FOR_C _V2D::element(index, i) = v[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -974,7 +807,7 @@ public:
|
||||
* @return matrix type _CMatrix
|
||||
*/
|
||||
_CMatrix &swapCols(uint r0, uint r1) {
|
||||
PIMM_FOR_C(i) { piSwap(_V2D::element(i, r0), _V2D::element(i, r1)); }
|
||||
PIMM_FOR_C piSwap<Type>(_V2D::element(i, r0), _V2D::element(i, r1));
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -987,7 +820,7 @@ public:
|
||||
* @return matrix type _CMatrix
|
||||
*/
|
||||
_CMatrix &swapRows(uint c0, uint c1) {
|
||||
PIMM_FOR_R(i) { piSwap(_V2D::element(c0, i), _V2D::element(c1, i)); }
|
||||
PIMM_FOR_R piSwap<Type>(_V2D::element(c0, i), _V2D::element(c1, i));
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -998,7 +831,7 @@ public:
|
||||
* @return filled matrix type _CMatrix
|
||||
*/
|
||||
_CMatrix &fill(const Type &v) {
|
||||
PIMM_FOR_A(i) _V2D::mat[i] = v;
|
||||
PIMM_FOR_A _V2D::mat[i] = v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -1015,7 +848,7 @@ public:
|
||||
* @return true if matrix is identity, else false
|
||||
*/
|
||||
bool isIdentity() const {
|
||||
PIMM_FOR(c, r) if ((c == r) ? _V2D::element(r, c) != Type(1) : _V2D::element(r, c) != Type(0))return false;
|
||||
PIMM_FOR if ((c == r) ? _V2D::element(r, c) != Type(1) : _V2D::element(r, c) != Type(0))return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1025,7 +858,7 @@ public:
|
||||
* @return true if matrix elements equal to zero, else false
|
||||
*/
|
||||
bool isNull() const {
|
||||
PIMM_FOR_A(i) if (_V2D::mat[i] != Type(0)) return false;
|
||||
PIMM_FOR_A if (_V2D::mat[i] != Type(0)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1036,63 +869,46 @@ public:
|
||||
*/
|
||||
bool isValid() const { return !PIVector2D<Type>::isEmpty(); }
|
||||
|
||||
/**
|
||||
* @brief Matrix assignment to matrix "v"
|
||||
*
|
||||
* @param v matrix for the assigment
|
||||
* @return matrix equal with v
|
||||
*/
|
||||
_CMatrix &operator=(const PIVector<PIVector<Type> > &v) {
|
||||
*this = _CMatrix(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compare with matrix "sm"
|
||||
*
|
||||
* @param sm matrix for the compare
|
||||
* @return if matrices are equal true, else false
|
||||
*/
|
||||
bool operator==(const _CMatrix &sm) const {
|
||||
PIMM_FOR_A(i) if (_V2D::mat[i] != sm.mat[i]) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compare with matrix "sm"
|
||||
*
|
||||
* @param sm matrix for the compare
|
||||
* @return if matrices are not equal true, else false
|
||||
*/
|
||||
bool operator!=(const _CMatrix &sm) const { return !(*this == sm); }
|
||||
|
||||
/**
|
||||
* @brief Addition assignment with matrix "sm"
|
||||
*
|
||||
* @param sm matrix for the addition assigment
|
||||
*/
|
||||
void operator+=(const _CMatrix &sm) { PIMM_FOR_A(i) _V2D::mat[i] += sm.mat[i]; }
|
||||
void operator+=(const _CMatrix &sm) {
|
||||
assert(_V2D::rows() == sm.rows());
|
||||
assert(_V2D::cols() == sm.cols());
|
||||
PIMM_FOR_A _V2D::mat[i] += sm.mat[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Subtraction assignment with matrix "sm"
|
||||
*
|
||||
* @param sm matrix for the subtraction assigment
|
||||
*/
|
||||
void operator-=(const _CMatrix &sm) { PIMM_FOR_A(i) _V2D::mat[i] -= sm.mat[i]; }
|
||||
void operator-=(const _CMatrix &sm) {
|
||||
assert(_V2D::rows() == sm.rows());
|
||||
assert(_V2D::cols() == sm.cols());
|
||||
PIMM_FOR_A _V2D::mat[i] -= sm.mat[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Multiplication assignment with value "v"
|
||||
*
|
||||
* @param v value for the multiplication assigment
|
||||
*/
|
||||
void operator*=(const Type &v) { PIMM_FOR_A(i) _V2D::mat[i] *= v; }
|
||||
void operator*=(const Type &v) {
|
||||
PIMM_FOR_A _V2D::mat[i] *= v;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Division assignment with value "v"
|
||||
*
|
||||
* @param v value for the division assigment
|
||||
*/
|
||||
void operator/=(const Type &v) { PIMM_FOR_A(i) _V2D::mat[i] /= v; }
|
||||
void operator/=(const Type &v) {
|
||||
assert(piAbs<Type>(v) > PIMATHVECTOR_ZERO_CMP);
|
||||
PIMM_FOR_A _V2D::mat[i] /= v;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Matrix substraction
|
||||
@@ -1101,7 +917,7 @@ public:
|
||||
*/
|
||||
_CMatrix operator-() const {
|
||||
_CMatrix tm(*this);
|
||||
PIMM_FOR_A(i) tm.mat[i] = -_V2D::mat[i];
|
||||
PIMM_FOR_A tm.mat[i] = -_V2D::mat[i];
|
||||
return tm;
|
||||
}
|
||||
|
||||
@@ -1113,7 +929,9 @@ public:
|
||||
*/
|
||||
_CMatrix operator+(const _CMatrix &sm) const {
|
||||
_CMatrix tm(*this);
|
||||
PIMM_FOR_A(i) tm.mat[i] += sm.mat[i];
|
||||
assert(tm.rows() == sm.rows());
|
||||
assert(tm.cols() == sm.cols());
|
||||
PIMM_FOR_A tm.mat[i] += sm.mat[i];
|
||||
return tm;
|
||||
}
|
||||
|
||||
@@ -1125,7 +943,9 @@ public:
|
||||
*/
|
||||
_CMatrix operator-(const _CMatrix &sm) const {
|
||||
_CMatrix tm(*this);
|
||||
PIMM_FOR_A(i) tm.mat[i] -= sm.mat[i];
|
||||
assert(tm.rows() == sm.rows());
|
||||
assert(tm.cols() == sm.cols());
|
||||
PIMM_FOR_A tm.mat[i] -= sm.mat[i];
|
||||
return tm;
|
||||
}
|
||||
|
||||
@@ -1137,7 +957,7 @@ public:
|
||||
*/
|
||||
_CMatrix operator*(const Type &v) const {
|
||||
_CMatrix tm(*this);
|
||||
PIMM_FOR_A(i) tm.mat[i] *= v;
|
||||
PIMM_FOR_A tm.mat[i] *= v;
|
||||
return tm;
|
||||
}
|
||||
|
||||
@@ -1148,8 +968,9 @@ public:
|
||||
* @return the result of matrix division
|
||||
*/
|
||||
_CMatrix operator/(const Type &v) const {
|
||||
assert(piAbs<Type>(v) > PIMATHVECTOR_ZERO_CMP);
|
||||
_CMatrix tm(*this);
|
||||
PIMM_FOR_A(i) tm.mat[i] /= v;
|
||||
PIMM_FOR_A tm.mat[i] /= v;
|
||||
return tm;
|
||||
}
|
||||
|
||||
@@ -1162,8 +983,8 @@ public:
|
||||
Type determinant(bool *ok = 0) const {
|
||||
_CMatrix m(*this);
|
||||
bool k;
|
||||
Type ret = Type(0);
|
||||
m.toUpperTriangular(&k);
|
||||
Type ret = Type(0);
|
||||
if (ok) *ok = k;
|
||||
if (!k) return ret;
|
||||
ret = Type(1);
|
||||
@@ -1177,19 +998,14 @@ public:
|
||||
/**
|
||||
* @brief Trace of the matrix is calculated. Works only with square matrix, nonzero matrices and invertible matrix
|
||||
*
|
||||
* @param ok is a parameter with which we can find out if the method worked correctly
|
||||
* @return matrix trace
|
||||
*/
|
||||
Type trace(bool *ok = 0) const {
|
||||
Type trace() const {
|
||||
assert(isSquare());
|
||||
Type ret = Type(0);
|
||||
if (!isSquare()) {
|
||||
if (ok != 0) *ok = false;
|
||||
return ret;
|
||||
}
|
||||
for (uint i = 0; i < _V2D::cols_; ++i) {
|
||||
ret += _V2D::element(i, i);
|
||||
}
|
||||
if (ok != 0) *ok = true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1200,10 +1016,7 @@ public:
|
||||
* @return copy of transformed upper triangular matrix
|
||||
*/
|
||||
_CMatrix &toUpperTriangular(bool *ok = 0) {
|
||||
if (!isSquare()) {
|
||||
if (ok != 0) *ok = false;
|
||||
return *this;
|
||||
}
|
||||
assert(isSquare());
|
||||
_CMatrix smat(*this);
|
||||
bool ndet;
|
||||
uint crow;
|
||||
@@ -1225,7 +1038,7 @@ public:
|
||||
for (uint k = i; k < _V2D::cols_; ++k) smat.element(k, j) -= mul * smat.element(k, i);
|
||||
}
|
||||
if (i < _V2D::cols_ - 1) {
|
||||
if (_PIMathMatrixNullCompare(smat.element(i + 1, i + 1))) {
|
||||
if (PIMathFloatNullCompare(smat.element(i + 1, i + 1))) {
|
||||
if (ok != 0) *ok = false;
|
||||
return *this;
|
||||
}
|
||||
@@ -1243,11 +1056,8 @@ public:
|
||||
* @param sv is a vector multiplier
|
||||
* @return copy of inverted matrix
|
||||
*/
|
||||
_CMatrix &invert(bool *ok = 0, _CMCol *sv = 0) {
|
||||
if (!isSquare()) {
|
||||
if (ok != 0) *ok = false;
|
||||
return *this;
|
||||
}
|
||||
_CMatrix &invert(bool *ok = 0, PIMathVector<Type> *sv = 0) {
|
||||
assert(isSquare());
|
||||
_CMatrix mtmp = _CMatrix::identity(_V2D::cols_, _V2D::rows_), smat(*this);
|
||||
bool ndet;
|
||||
uint crow;
|
||||
@@ -1266,7 +1076,7 @@ public:
|
||||
++crow;
|
||||
smat.swapRows(i, crow);
|
||||
mtmp.swapRows(i, crow);
|
||||
if (sv != 0) sv->swap(i, crow);
|
||||
if (sv != 0) sv->swapElements(i, crow);
|
||||
}
|
||||
for (uint j = i + 1; j < _V2D::rows_; ++j) {
|
||||
mul = smat.element(i, j) / smat.element(i, i);
|
||||
@@ -1275,7 +1085,7 @@ public:
|
||||
if (sv != 0) (*sv)[j] -= mul * (*sv)[i];
|
||||
}
|
||||
if (i < _V2D::cols_ - 1) {
|
||||
if (_PIMathMatrixNullCompare(smat.element(i + 1, i + 1))) {
|
||||
if (PIMathFloatNullCompare(smat.element(i + 1, i + 1))) {
|
||||
if (ok != 0) *ok = false;
|
||||
return *this;
|
||||
}
|
||||
@@ -1317,7 +1127,7 @@ public:
|
||||
*/
|
||||
_CMatrix transposed() const {
|
||||
_CMatrix tm(_V2D::rows_, _V2D::cols_);
|
||||
PIMM_FOR(c, r) tm.element(c, r) = _V2D::element(r, c);
|
||||
PIMM_FOR tm.element(c, r) = _V2D::element(r, c);
|
||||
return tm;
|
||||
}
|
||||
};
|
||||
@@ -1386,14 +1196,13 @@ inline PIByteArray &operator>>(PIByteArray &s, PIMathMatrix<Type> &v) {
|
||||
template<typename Type>
|
||||
inline PIMathMatrix<Type> operator*(const PIMathMatrix<Type> &fm,
|
||||
const PIMathMatrix<Type> &sm) {
|
||||
uint cr = fm.cols(), rows0 = fm.rows(), cols1 = sm.cols();
|
||||
PIMathMatrix<Type> tm(cols1, rows0);
|
||||
if (fm.cols() != sm.rows()) return tm;
|
||||
assert(fm.cols() == sm.rows());
|
||||
PIMathMatrix<Type> tm(sm.cols(), fm.rows());
|
||||
Type t;
|
||||
for (uint j = 0; j < rows0; ++j) {
|
||||
for (uint i = 0; i < cols1; ++i) {
|
||||
for (uint j = 0; j < fm.rows(); ++j) {
|
||||
for (uint i = 0; i < sm.cols(); ++i) {
|
||||
t = Type(0);
|
||||
for (uint k = 0; k < cr; ++k)
|
||||
for (uint k = 0; k < fm.cols(); ++k)
|
||||
t += fm.element(j, k) * sm.element(k, i);
|
||||
tm.element(j, i) = t;
|
||||
}
|
||||
@@ -1411,13 +1220,12 @@ inline PIMathMatrix<Type> operator*(const PIMathMatrix<Type> &fm,
|
||||
template<typename Type>
|
||||
inline PIMathVector<Type> operator*(const PIMathMatrix<Type> &fm,
|
||||
const PIMathVector<Type> &sv) {
|
||||
uint c = fm.cols(), r = fm.rows();
|
||||
PIMathVector<Type> tv(r);
|
||||
if (c != sv.size()) return tv;
|
||||
assert(fm.cols() == sv.size());
|
||||
PIMathVector<Type> tv(fm.rows());
|
||||
Type t;
|
||||
for (uint j = 0; j < r; ++j) {
|
||||
for (uint j = 0; j < fm.rows(); ++j) {
|
||||
t = Type(0);
|
||||
for (uint i = 0; i < c; ++i)
|
||||
for (uint i = 0; i < fm.cols(); ++i)
|
||||
t += fm.element(j, i) * sv[i];
|
||||
tv[j] = t;
|
||||
}
|
||||
@@ -1434,12 +1242,12 @@ inline PIMathVector<Type> operator*(const PIMathMatrix<Type> &fm,
|
||||
template<typename Type>
|
||||
inline PIMathVector<Type> operator*(const PIMathVector<Type> &sv,
|
||||
const PIMathMatrix<Type> &fm) {
|
||||
uint c = fm.cols(), r = fm.rows();
|
||||
PIMathVector<Type> tv(c);
|
||||
PIMathVector<Type> tv(fm.cols());
|
||||
assert(fm.rows() == sv.size());
|
||||
Type t;
|
||||
for (uint j = 0; j < c; ++j) {
|
||||
for (uint j = 0; j < fm.cols(); ++j) {
|
||||
t = Type(0);
|
||||
for (uint i = 0; i < r; ++i)
|
||||
for (uint i = 0; i < fm.rows(); ++i)
|
||||
t += fm.element(i, j) * sv[i];
|
||||
tv[j] = t;
|
||||
}
|
||||
@@ -1477,7 +1285,6 @@ PIMathMatrix<complex<T> > hermitian(const PIMathMatrix<complex<T> > &m) {
|
||||
}
|
||||
|
||||
#undef PIMM_FOR
|
||||
#undef PIMM_FOR_I
|
||||
#undef PIMM_FOR_A
|
||||
#undef PIMM_FOR_C
|
||||
#undef PIMM_FOR_R
|
||||
|
||||
@@ -28,85 +28,202 @@
|
||||
template<uint Cols, uint Rows, typename Type>
|
||||
class PIMathMatrixT;
|
||||
|
||||
#define PIMATHVECTOR_ZERO_CMP Type(1E-100)
|
||||
|
||||
|
||||
/// Vector templated
|
||||
|
||||
#define PIMV_FOR(v, s) for (uint v = s; v < Size; ++v)
|
||||
#define PIMV_FOR for (uint i = 0; i < Size; ++i)
|
||||
|
||||
template<uint Size, typename Type = double>
|
||||
class PIP_EXPORT PIMathVectorT {
|
||||
typedef PIMathVectorT<Size, Type> _CVector;
|
||||
static_assert(std::is_arithmetic<Type>::value, "Type must be arithmetic");
|
||||
static_assert(Size > 0, "Size count must be > 0");
|
||||
static_assert(Size > 0, "Size must be > 0");
|
||||
public:
|
||||
PIMathVectorT() {resize();}
|
||||
PIMathVectorT(const PIVector<Type> & val) {resize(); PIMV_FOR(i, 0) c[i] = val[i];}
|
||||
PIMathVectorT(const _CVector & st, const _CVector & fn) {resize(); set(st, fn);}
|
||||
PIMathVectorT(const Type & v = Type()) {PIMV_FOR c[i] = v;}
|
||||
PIMathVectorT(const PIVector<Type> & val) {
|
||||
assert(Size == val.size());
|
||||
PIMV_FOR c[i] = val[i];
|
||||
}
|
||||
PIMathVectorT(std::initializer_list<Type> init_list) {
|
||||
assert(Size == init_list.size());
|
||||
PIMV_FOR c[i] = init_list.begin()[i];
|
||||
}
|
||||
static _CVector fromTwoPoints(const _CVector & st, const _CVector & fn) {
|
||||
_CVector tv;
|
||||
PIMV_FOR tv[i] = fn[i] - st[i];
|
||||
return tv;
|
||||
}
|
||||
|
||||
uint size() const {return Size;}
|
||||
_CVector & fill(const Type & v) {PIMV_FOR(i, 0) c[i] = v; return *this;}
|
||||
_CVector & set(const _CVector & st, const _CVector & fn) {PIMV_FOR(i, 0) c[i] = fn[i] - st[i]; return *this;}
|
||||
_CVector & move(const Type & v) {PIMV_FOR(i, 0) c[i] += v; return *this;}
|
||||
_CVector & move(const _CVector & v) {PIMV_FOR(i, 0) c[i] += v[i]; return *this;}
|
||||
Type lengthSqr() const {Type tv(0); PIMV_FOR(i, 0) tv += (c[i] * c[i]); return tv;}
|
||||
Type length() const {return sqrt(lengthSqr());}
|
||||
Type manhattanLength() const {Type tv(0); PIMV_FOR(i, 0) tv += fabs(c[i]); return tv;}
|
||||
Type angleCos(const _CVector & v) const {Type tv = v.length() * length(); return (tv == Type(0) ? Type(0) : ((*this) ^ v) / tv);}
|
||||
Type angleSin(const _CVector & v) const {Type tv = angleCos(v); return sqrt(Type(1) - tv * tv);}
|
||||
Type angleRad(const _CVector & v) const {return acos(angleCos(v));}
|
||||
Type angleDeg(const _CVector & v) const {return toDeg(acos(angleCos(v)));}
|
||||
Type angleElevation(const _CVector & v) const {_CVector z = v - *this; double c = z.angleCos(*this); return 90.0 - acos(c) * rad2deg;}
|
||||
_CVector projection(const _CVector & v) {Type tv = v.length(); return (tv == Type(0) ? _CVector() : v * (((*this) ^ v) / tv));}
|
||||
_CVector & normalize() {Type tv = length(); if (tv == Type(1)) return *this; if (piAbs<Type>(tv) <= Type(1E-100)) {fill(Type(0)); return *this;} PIMV_FOR(i, 0) c[i] /= tv; return *this;}
|
||||
constexpr uint size() const {return Size;}
|
||||
_CVector & fill(const Type & v) {PIMV_FOR c[i] = v; return *this;}
|
||||
_CVector & move(const Type & v) {PIMV_FOR c[i] += v; return *this;}
|
||||
_CVector & move(const _CVector & v) {PIMV_FOR c[i] += v[i]; return *this;}
|
||||
_CVector & swapElements(uint f, uint s) {
|
||||
piSwap<Type>(c[f], c[s]);
|
||||
return *this;
|
||||
}
|
||||
Type lengthSqr() const {
|
||||
Type tv(0);
|
||||
PIMV_FOR tv += c[i] * c[i];
|
||||
return tv;
|
||||
}
|
||||
Type length() const {return std::sqrt(lengthSqr());}
|
||||
Type manhattanLength() const {
|
||||
Type tv(0);
|
||||
PIMV_FOR tv += piAbs<Type>(c[i]);
|
||||
return tv;
|
||||
}
|
||||
Type angleCos(const _CVector & v) const {
|
||||
Type tv = v.length() * length();
|
||||
assert(piAbs<Type>(tv) > PIMATHVECTOR_ZERO_CMP);
|
||||
return dot(v) / tv;
|
||||
}
|
||||
Type angleSin(const _CVector & v) const {
|
||||
Type tv = angleCos(v);
|
||||
return std::sqrt(Type(1) - tv * tv);
|
||||
}
|
||||
Type angleRad(const _CVector & v) const {return std::acos(angleCos(v));}
|
||||
Type angleDeg(const _CVector & v) const {return toDeg(angleRad(v));}
|
||||
Type angleElevation(const _CVector & v) const {return 90.0 - angleDeg(v - *this);}
|
||||
_CVector projection(const _CVector & v) {
|
||||
Type tv = v.length();
|
||||
assert(piAbs<Type>(tv) > PIMATHVECTOR_ZERO_CMP);
|
||||
return v * (dot(v) / tv);
|
||||
}
|
||||
_CVector & normalize() {
|
||||
Type tv = length();
|
||||
assert(piAbs<Type>(tv) > PIMATHVECTOR_ZERO_CMP);
|
||||
if (tv == Type(1)) return *this;
|
||||
PIMV_FOR c[i] /= tv;
|
||||
return *this;
|
||||
}
|
||||
_CVector normalized() {_CVector tv(*this); tv.normalize(); return tv;}
|
||||
_CVector cross(const _CVector & v) {return (*this) * v;}
|
||||
Type dot(const _CVector & v) const {return (*this) ^ v;}
|
||||
bool isNull() const {PIMV_FOR(i, 0) if (c[i] != Type(0)) return false; return true;}
|
||||
bool isNull() const {PIMV_FOR if (c[i] != Type(0)) return false; return true;}
|
||||
bool isOrtho(const _CVector & v) const {return ((*this) ^ v) == Type(0);}
|
||||
|
||||
Type & at(uint index) {return c[index];}
|
||||
Type at(uint index) const {return c[index];}
|
||||
Type & operator [](uint index) {return c[index];}
|
||||
Type operator [](uint index) const {return c[index];}
|
||||
_CVector & operator =(const _CVector & v) {memcpy(c, v.c, sizeof(Type) * Size); return *this;}
|
||||
_CVector & operator =(const Type & v) {PIMV_FOR(i, 0) c[i] = v; return *this;}
|
||||
bool operator ==(const _CVector & v) const {PIMV_FOR(i, 0) if (c[i] != v[i]) return false; return true;}
|
||||
const Type & operator [](uint index) const {return c[index];}
|
||||
Type at(uint index) const {return c[index];}
|
||||
|
||||
_CVector & operator =(const Type & v) {PIMV_FOR c[i] = v; return *this;}
|
||||
|
||||
bool operator ==(const _CVector & v) const {PIMV_FOR if (c[i] != v[i]) return false; return true;}
|
||||
bool operator !=(const _CVector & v) const {return !(*this == c);}
|
||||
void operator +=(const _CVector & v) {PIMV_FOR(i, 0) c[i] += v[i];}
|
||||
void operator -=(const _CVector & v) {PIMV_FOR(i, 0) c[i] -= v[i];}
|
||||
void operator *=(const Type & v) {PIMV_FOR(i, 0) c[i] *= v;}
|
||||
void operator *=(const _CVector & v) {PIMV_FOR(i, 0) c[i] *= v[i];}
|
||||
void operator /=(const Type & v) {PIMV_FOR(i, 0) c[i] /= v;}
|
||||
void operator /=(const _CVector & v) {PIMV_FOR(i, 0) c[i] /= v[i];}
|
||||
_CVector operator -() const {_CVector tv; PIMV_FOR(i, 0) tv[i] = -c[i]; return tv;}
|
||||
_CVector operator +(const _CVector & v) const {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] += v[i]; return tv;}
|
||||
_CVector operator -(const _CVector & v) const {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] -= v[i]; return tv;}
|
||||
_CVector operator *(const Type & v) const {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] *= v; return tv;}
|
||||
_CVector operator /(const Type & v) const {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] /= v; return tv;}
|
||||
_CVector operator /(const _CVector & v) const {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] /= v[i]; return tv;}
|
||||
_CVector operator *(const _CVector & v) const {if (Size != 3) return _CVector(); _CVector tv; tv.fill(Type(1)); tv[0] = c[1]*v[2] - v[1]*c[2]; tv[1] = v[0]*c[2] - c[0]*v[2]; tv[2] = c[0]*v[1] - v[0]*c[1]; return tv;}
|
||||
_CVector operator &(const _CVector & v) const {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] *= v[i]; return tv;}
|
||||
Type operator ^(const _CVector & v) const {Type tv(0); PIMV_FOR(i, 0) tv += c[i] * v[i]; return tv;}
|
||||
|
||||
|
||||
void operator +=(const _CVector & v) {PIMV_FOR c[i] += v[i];}
|
||||
void operator -=(const _CVector & v) {PIMV_FOR c[i] -= v[i];}
|
||||
void operator *=(const Type & v) {PIMV_FOR c[i] *= v;}
|
||||
void operator /=(const Type & v) {
|
||||
assert(piAbs<Type>(v) > PIMATHVECTOR_ZERO_CMP);
|
||||
PIMV_FOR c[i] /= v;
|
||||
}
|
||||
_CVector operator -() const {
|
||||
_CVector tv;
|
||||
PIMV_FOR tv[i] = -c[i];
|
||||
return tv;
|
||||
}
|
||||
_CVector operator +(const _CVector & v) const {
|
||||
_CVector tv(*this);
|
||||
PIMV_FOR tv[i] += v[i];
|
||||
return tv;
|
||||
}
|
||||
_CVector operator -(const _CVector & v) const {
|
||||
_CVector tv(*this);
|
||||
PIMV_FOR tv[i] -= v[i];
|
||||
return tv;
|
||||
}
|
||||
_CVector operator *(const Type & v) const {
|
||||
_CVector tv(*this);
|
||||
PIMV_FOR tv[i] *= v;
|
||||
return tv;
|
||||
}
|
||||
_CVector operator /(const Type & v) const {
|
||||
assert(piAbs<Type>(v) > PIMATHVECTOR_ZERO_CMP);
|
||||
_CVector tv = _CVector(*this);
|
||||
PIMV_FOR tv[i] /= v;
|
||||
return tv;
|
||||
}
|
||||
|
||||
_CVector cross(const _CVector & v) const {
|
||||
static_assert(Size == 3, "cross product avalible only for 3D vectors");
|
||||
_CVector tv;
|
||||
tv[0] = c[1]*v[2] - v[1]*c[2];
|
||||
tv[1] = v[0]*c[2] - c[0]*v[2];
|
||||
tv[2] = c[0]*v[1] - v[0]*c[1];
|
||||
return tv;
|
||||
}
|
||||
Type dot(const _CVector & v) const {
|
||||
Type tv(0);
|
||||
PIMV_FOR tv += c[i] * v[i];
|
||||
return tv;
|
||||
}
|
||||
_CVector mul(const _CVector & v) const {
|
||||
_CVector tv(*this);
|
||||
PIMV_FOR tv[i] *= v[i];
|
||||
return tv;
|
||||
}
|
||||
_CVector mul(const Type & v) const {
|
||||
return (*this) * v;
|
||||
}
|
||||
_CVector div(const _CVector & v) const {
|
||||
_CVector tv(*this);
|
||||
PIMV_FOR {
|
||||
assert(piAbs<Type>(v[i]) > PIMATHVECTOR_ZERO_CMP);
|
||||
tv[i] /= v[i];
|
||||
}
|
||||
return tv;
|
||||
}
|
||||
_CVector div(const Type & v) const {
|
||||
return (*this) / v;
|
||||
}
|
||||
|
||||
PIMathMatrixT<1, Size, Type> transposed() const {
|
||||
PIMathMatrixT<1, Size, Type> ret;
|
||||
PIMV_FOR(i, 0) ret[0][i] = c[i];
|
||||
PIMV_FOR ret[0][i] = c[i];
|
||||
return ret;
|
||||
}
|
||||
|
||||
Type distToLine(const _CVector & lp0, const _CVector & lp1) {
|
||||
_CVector a(lp0, lp1), b(lp0, *this), c(lp1, *this);
|
||||
Type f = fabs(a[0]*b[1] - a[1]*b[0]) / a.length();
|
||||
return f;}
|
||||
_CVector a(lp0, lp1);
|
||||
Type tv = a.length();
|
||||
assert(piAbs<Type>(tv) > PIMATHVECTOR_ZERO_CMP);
|
||||
_CVector b(lp0, *this);
|
||||
return piAbs<Type>(a[0]*b[1] - a[1]*b[0]) / tv;
|
||||
}
|
||||
|
||||
template<uint Size1, typename Type1> /// vector {Size, Type} to vector {Size1, Type1}
|
||||
PIMathVectorT<Size1, Type1> turnTo() const {PIMathVectorT<Size1, Type1> tv; uint sz = piMin<uint>(Size, Size1); for (uint i = 0; i < sz; ++i) tv[i] = c[i]; return tv;}
|
||||
PIMathVectorT<Size1, Type1> turnTo() const {
|
||||
PIMathVectorT<Size1, Type1> tv;
|
||||
uint sz = piMin<uint>(Size, Size1);
|
||||
for (uint i = 0; i < sz; ++i) tv[i] = c[i];
|
||||
return tv;
|
||||
}
|
||||
|
||||
static _CVector filled(const Type & v) {_CVector vv; PIMV_FOR(i, 0) vv[i] = v; return vv;}
|
||||
static _CVector cross(const _CVector & v1, const _CVector & v2) {
|
||||
return v1.cross(v2);
|
||||
}
|
||||
static _CVector dot(const _CVector & v1, const _CVector & v2) {
|
||||
return v1.dot(v2);
|
||||
}
|
||||
static _CVector mul(const _CVector & v1, const _CVector & v2) {
|
||||
return v1.mul(v2);
|
||||
}
|
||||
static _CVector mul(const Type & v1, const _CVector & v2) {
|
||||
return v2 * v1;
|
||||
}
|
||||
static _CVector mul(const _CVector & v1, const Type & v2) {
|
||||
return v1 * v2;
|
||||
}
|
||||
static _CVector div(const _CVector & v1, const _CVector & v2) {
|
||||
return v1.div(v2);
|
||||
}
|
||||
static _CVector div(const _CVector & v1, const Type & v2) {
|
||||
return v1 / v2;
|
||||
}
|
||||
|
||||
private:
|
||||
void resize(const Type & new_value = Type()) {for (uint i = 0; i < Size; ++i) c[i] = new_value;}
|
||||
|
||||
Type c[Size];
|
||||
|
||||
};
|
||||
@@ -117,25 +234,8 @@ inline PIMathVectorT<Size, Type> operator *(const Type & x, const PIMathVectorT<
|
||||
}
|
||||
|
||||
template<uint Size, typename Type>
|
||||
inline PICout operator <<(PICout s, const PIMathVectorT<Size, Type> & v) {s << "{"; PIMV_FOR(i, 0) {s << v[i]; if (i < Size - 1) s << ", ";} s << "}"; return s;}
|
||||
template<uint Size, typename Type>
|
||||
inline bool operator ||(const PIMathVectorT<Size, Type> & f, const PIMathVectorT<Size, Type> & s) {return (f * s).isNull();}
|
||||
template<uint Size, typename Type>
|
||||
inline PIMathVectorT<Size, Type> sqrt(const PIMathVectorT<Size, Type> & v) {PIMathVectorT<Size, Type> ret; PIMV_FOR(i, 0) {ret[i] = sqrt(v[i]);} return ret;}
|
||||
template<uint Size, typename Type>
|
||||
inline PIMathVectorT<Size, Type> sqr(const PIMathVectorT<Size, Type> & v) {PIMathVectorT<Size, Type> ret; PIMV_FOR(i, 0) {ret[i] = sqr(v[i]);} return ret;}
|
||||
inline PICout operator <<(PICout s, const PIMathVectorT<Size, Type> & v) {s << "{"; PIMV_FOR {s << v[i]; if (i < Size - 1) s << ", ";} s << "}"; return s;}
|
||||
|
||||
template<uint Size, typename Type>
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIMathVectorT<Size, Type> & v) {for (uint i = 0; i < Size; ++i) s << v[i]; return s;}
|
||||
template<uint Size, typename Type>
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIMathVectorT<Size, Type> & v) {for (uint i = 0; i < Size; ++i) s >> v[i]; return s;}
|
||||
|
||||
template<typename T>
|
||||
inline PIMathVectorT<2u, T> createVectorT2(T x, T y) {return PIMathVectorT<2u, T>(PIVector<T>() << x << y);}
|
||||
template<typename T>
|
||||
inline PIMathVectorT<3u, T> createVectorT3(T x, T y, T z) {return PIMathVectorT<3u, T>(PIVector<T>() << x << y << z);}
|
||||
template<typename T>
|
||||
inline PIMathVectorT<4u, T> createVectorT4(T x, T y, T z, T w) {return PIMathVectorT<4u, T>(PIVector<T>() << x << y << z << w);}
|
||||
|
||||
typedef PIMathVectorT<2u, int> PIMathVectorT2i;
|
||||
typedef PIMathVectorT<3u, int> PIMathVectorT3i;
|
||||
@@ -143,21 +243,13 @@ typedef PIMathVectorT<4u, int> PIMathVectorT4i;
|
||||
typedef PIMathVectorT<2u, double> PIMathVectorT2d;
|
||||
typedef PIMathVectorT<3u, double> PIMathVectorT3d;
|
||||
typedef PIMathVectorT<4u, double> PIMathVectorT4d;
|
||||
#define createVectorT2i createVectorT2<int>
|
||||
#define createVectorT3i createVectorT3<int>
|
||||
#define createVectorT4i createVectorT4<int>
|
||||
#define createVectorT2f createVectorT2<float>
|
||||
#define createVectorT3f createVectorT3<float>
|
||||
#define createVectorT4f createVectorT4<float>
|
||||
#define createVectorT2d createVectorT2<double>
|
||||
#define createVectorT3d createVectorT3<double>
|
||||
#define createVectorT4d createVectorT4<double>
|
||||
|
||||
|
||||
#undef PIMV_FOR
|
||||
|
||||
/// Vector
|
||||
|
||||
#define PIMV_FOR(v, s) for (uint v = s; v < c.size(); ++v)
|
||||
#define PIMV_FOR for (uint i = 0; i < c.size(); ++i)
|
||||
|
||||
template<typename Type>
|
||||
class PIP_EXPORT PIMathVector {
|
||||
@@ -165,73 +257,228 @@ class PIP_EXPORT PIMathVector {
|
||||
template<typename TypeOp> friend PIByteArray & operator <<(PIByteArray & s, const PIMathVector<TypeOp> & v);
|
||||
template<typename TypeOp> friend PIByteArray & operator >>(PIByteArray & s, PIMathVector<TypeOp> & v);
|
||||
public:
|
||||
PIMathVector(const uint size = 0) {c.resize(size);}
|
||||
PIMathVector(const PIVector<Type> & val) {c.resize(val.size()); PIMV_FOR(i, 0) c[i] = val[i];}
|
||||
PIMathVector(const _CVector & st, const _CVector & fn) {c.resize(st.size()); PIMV_FOR(i, 0) c[i] = fn[i] - st[i];}
|
||||
PIMathVector(const uint size = 0, const Type & new_value = Type()) {c.resize(size, new_value);}
|
||||
PIMathVector(const PIVector<Type> & val) {c = val;}
|
||||
PIMathVector(std::initializer_list<Type> init_list) {c = PIVector<Type>(init_list);}
|
||||
|
||||
uint size() const {return c.size();}
|
||||
_CVector & resize(uint size, const Type & new_value = Type()) {c.resize(size, new_value); return *this;}
|
||||
_CVector resized(uint size, const Type & new_value = Type()) {_CVector tv = _CVector(*this); tv.resize(size, new_value); return tv;}
|
||||
_CVector & fill(const Type & v) {PIMV_FOR(i, 0) c[i] = v; return *this;}
|
||||
_CVector & move(const Type & v) {PIMV_FOR(i, 0) c[i] += v; return *this;}
|
||||
_CVector & move(const _CVector & v) {PIMV_FOR(i, 0) c[i] += v[i]; return *this;}
|
||||
_CVector & swap(uint fe, uint se) {piSwap<Type>(c[fe], c[se]); return *this;}
|
||||
Type lengthSqr() const {Type tv(0); PIMV_FOR(i, 0) tv += (c[i] * c[i]); return tv;}
|
||||
Type length() const {return sqrt(lengthSqr());}
|
||||
Type manhattanLength() const {Type tv(0); PIMV_FOR(i, 0) tv += fabs(c[i]); return tv;}
|
||||
Type angleCos(const _CVector & v) const {Type tv = v.length() * length(); return (tv == Type(0) ? Type(0) : ((*this) ^ v) / tv);}
|
||||
Type angleSin(const _CVector & v) const {Type tv = angleCos(v); return sqrt(Type(1) - tv * tv);}
|
||||
Type angleRad(const _CVector & v) const {return acos(angleCos(v));}
|
||||
Type angleDeg(const _CVector & v) const {return toDeg(acos(angleCos(v)));}
|
||||
_CVector projection(const _CVector & v) {Type tv = v.length(); return (tv == Type(0) ? _CVector() : v * (((*this) ^ v) / tv));}
|
||||
_CVector & normalize() {Type tv = length(); if (tv == Type(1)) return *this; if (piAbs<Type>(tv) <= Type(1E-100)) {fill(Type(0)); return *this;} PIMV_FOR(i, 0) c[i] /= tv; return *this;}
|
||||
_CVector normalized() {_CVector tv(*this); tv.normalize(); return tv;}
|
||||
bool isNull() const {PIMV_FOR(i, 0) if (c[i] != Type(0)) return false; return true;}
|
||||
bool isValid() const {return !c.isEmpty();}
|
||||
template<uint Size>
|
||||
PIMathVector(const PIMathVectorT<Size, Type> & val) {c.resize(Size); PIMV_FOR c[i] = val[i];}
|
||||
|
||||
bool isOrtho(const _CVector & v) const {return ((*this) ^ v) == Type(0);}
|
||||
|
||||
Type & at(uint index) {return c[index];}
|
||||
Type at(uint index) const {return c[index];}
|
||||
Type & operator [](uint index) {return c[index];}
|
||||
Type operator [](uint index) const {return c[index];}
|
||||
_CVector & operator =(const _CVector & v) {c = v.c; return *this;}
|
||||
_CVector & operator =(const Type & v) {PIMV_FOR(i, 0) c[i] = v; return *this;}
|
||||
bool operator ==(const _CVector & v) const {PIMV_FOR(i, 0) if (c[i] != v[i]) return false; return true;}
|
||||
bool operator !=(const _CVector & v) const {return !(*this == c);}
|
||||
void operator +=(const _CVector & v) {PIMV_FOR(i, 0) c[i] += v[i];}
|
||||
void operator -=(const _CVector & v) {PIMV_FOR(i, 0) c[i] -= v[i];}
|
||||
void operator *=(const Type & v) {PIMV_FOR(i, 0) c[i] *= v;}
|
||||
void operator *=(const _CVector & v) {PIMV_FOR(i, 0) c[i] *= v[i];}
|
||||
void operator /=(const Type & v) {PIMV_FOR(i, 0) c[i] /= v;}
|
||||
void operator /=(const _CVector & v) {PIMV_FOR(i, 0) c[i] /= v[i];}
|
||||
_CVector operator -() const {_CVector tv; PIMV_FOR(i, 0) tv[i] = -c[i]; return tv;}
|
||||
_CVector operator +(const _CVector & v) const {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] += v[i]; return tv;}
|
||||
_CVector operator -(const _CVector & v) const {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] -= v[i]; return tv;}
|
||||
_CVector operator *(const Type & v) const {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] *= v; return tv;}
|
||||
_CVector operator /(const Type & v) const {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] /= v; return tv;}
|
||||
_CVector operator *(const _CVector & v) const {if (c.size() < 3) return _CVector(); _CVector tv; tv.fill(Type(1)); tv[0] = c[1]*v[2] - v[1]*c[2]; tv[1] = v[0]*c[2] - c[0]*v[2]; tv[2] = c[0]*v[1] - v[0]*c[1]; return tv;}
|
||||
_CVector operator &(const _CVector & v) const {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] *= v[i]; return tv;}
|
||||
Type operator ^(const _CVector & v) const {Type tv(0); PIMV_FOR(i, 0) tv += c[i] * v[i]; return tv;}
|
||||
|
||||
Type distToLine(const _CVector & lp0, const _CVector & lp1) {
|
||||
_CVector a(lp0, lp1), b(lp0, *this), c(lp1, *this);
|
||||
Type f = fabs(a[0]*b[1] - a[1]*b[0]) / a.length();
|
||||
return f;
|
||||
static PIMathVector fromTwoPoints(const _CVector & st, const _CVector & fn) {
|
||||
assert(st.size() == fn.size());
|
||||
_CVector v(st.size());
|
||||
for (uint i = 0; i < v.size(); ++i) v.c[i] = fn[i] - st[i];
|
||||
}
|
||||
|
||||
uint size() const {return c.size();}
|
||||
_CVector & resize(uint size, const Type & new_value = Type()) {
|
||||
c.resize(size, new_value);
|
||||
return *this;
|
||||
}
|
||||
_CVector resized(uint size, const Type & new_value = Type()) {
|
||||
_CVector tv = _CVector(*this);
|
||||
tv.resize(size, new_value);
|
||||
return tv;
|
||||
}
|
||||
_CVector & fill(const Type & v) {
|
||||
c.fill(v);
|
||||
return *this;
|
||||
}
|
||||
_CVector & move(const Type & v) {
|
||||
PIMV_FOR c[i] += v;
|
||||
return *this;
|
||||
}
|
||||
_CVector & move(const _CVector & v) {
|
||||
assert(c.size() == v.size());
|
||||
PIMV_FOR c[i] += v[i];
|
||||
return *this;
|
||||
}
|
||||
_CVector & swapElements(uint f, uint s) {
|
||||
piSwap<Type>(c[f], c[s]);
|
||||
return *this;
|
||||
}
|
||||
Type lengthSqr() const {
|
||||
Type tv(0);
|
||||
PIMV_FOR tv += c[i] * c[i];
|
||||
return tv;
|
||||
}
|
||||
Type length() const {return std::sqrt(lengthSqr());}
|
||||
Type manhattanLength() const {
|
||||
Type tv(0);
|
||||
PIMV_FOR tv += piAbs<Type>(c[i]);
|
||||
return tv;
|
||||
}
|
||||
Type angleCos(const _CVector & v) const {
|
||||
assert(c.size() == v.size());
|
||||
Type tv = v.length() * length();
|
||||
assert(piAbs<Type>(tv) > PIMATHVECTOR_ZERO_CMP);
|
||||
return dot(v) / tv;
|
||||
}
|
||||
Type angleSin(const _CVector & v) const {
|
||||
assert(c.size() == v.size());
|
||||
Type tv = angleCos(v);
|
||||
return std::sqrt(Type(1) - tv * tv);
|
||||
}
|
||||
Type angleRad(const _CVector & v) const {return std::acos(angleCos(v));}
|
||||
Type angleDeg(const _CVector & v) const {return toDeg(angleRad(v));}
|
||||
_CVector projection(const _CVector & v) {
|
||||
assert(c.size() == v.size());
|
||||
Type tv = v.length();
|
||||
assert(piAbs<Type>(tv) > PIMATHVECTOR_ZERO_CMP);
|
||||
return v * (dot(v) / tv);
|
||||
}
|
||||
_CVector & normalize() {
|
||||
Type tv = length();
|
||||
assert(piAbs<Type>(tv) > PIMATHVECTOR_ZERO_CMP);
|
||||
if (tv == Type(1)) return *this;
|
||||
PIMV_FOR c[i] /= tv;
|
||||
return *this;
|
||||
}
|
||||
_CVector normalized() {
|
||||
_CVector tv(*this);
|
||||
tv.normalize();
|
||||
return tv;
|
||||
}
|
||||
bool isNull() const {
|
||||
PIMV_FOR if (c[i] != Type(0)) return false;
|
||||
return true;
|
||||
}
|
||||
bool isValid() const {return !c.isEmpty();}
|
||||
bool isOrtho(const _CVector & v) const {return dot(v) == Type(0);}
|
||||
|
||||
Type & operator [](uint index) {return c[index];}
|
||||
const Type & operator [](uint index) const {return c[index];}
|
||||
Type at(uint index) const {return c[index];}
|
||||
|
||||
_CVector & operator =(const Type & v) {PIMV_FOR c[i] = v; return *this;}
|
||||
|
||||
bool operator ==(const _CVector & v) const {return c == v.c;}
|
||||
bool operator !=(const _CVector & v) const {return c != v.c;}
|
||||
|
||||
void operator +=(const _CVector & v) {
|
||||
assert(c.size() == v.size());
|
||||
PIMV_FOR c[i] += v[i];
|
||||
}
|
||||
void operator -=(const _CVector & v) {
|
||||
assert(c.size() == v.size());
|
||||
PIMV_FOR c[i] -= v[i];
|
||||
}
|
||||
void operator *=(const Type & v) {PIMV_FOR c[i] *= v;}
|
||||
void operator /=(const Type & v) {
|
||||
assert(piAbs<Type>(v) > PIMATHVECTOR_ZERO_CMP);
|
||||
PIMV_FOR c[i] /= v;
|
||||
}
|
||||
_CVector operator -() const {
|
||||
_CVector tv(c.size());
|
||||
PIMV_FOR tv[i] = -c[i];
|
||||
return tv;
|
||||
}
|
||||
_CVector operator +(const _CVector & v) const {
|
||||
assert(c.size() == v.size());
|
||||
_CVector tv(*this);
|
||||
PIMV_FOR tv[i] += v[i];
|
||||
return tv;
|
||||
}
|
||||
_CVector operator -(const _CVector & v) const {
|
||||
assert(c.size() == v.size());
|
||||
_CVector tv(*this);
|
||||
PIMV_FOR tv[i] -= v[i];
|
||||
return tv;
|
||||
}
|
||||
_CVector operator *(const Type & v) const {
|
||||
_CVector tv(*this);
|
||||
PIMV_FOR tv[i] *= v;
|
||||
return tv;
|
||||
}
|
||||
_CVector operator /(const Type & v) const {
|
||||
assert(piAbs<Type>(v) > PIMATHVECTOR_ZERO_CMP);
|
||||
_CVector tv(*this);
|
||||
PIMV_FOR tv[i] /= v;
|
||||
return tv;
|
||||
}
|
||||
_CVector cross(const _CVector & v) const {
|
||||
assert(c.size() == 3);
|
||||
assert(v.size() == 3);
|
||||
_CVector tv(3);
|
||||
tv[0] = c[1]*v[2] - v[1]*c[2];
|
||||
tv[1] = c[2]*v[0] - v[2]*c[0];
|
||||
tv[2] = c[0]*v[1] - v[0]*c[1];
|
||||
return tv;
|
||||
}
|
||||
Type dot(const _CVector & v) const {
|
||||
assert(c.size() == v.size());
|
||||
Type tv(0);
|
||||
PIMV_FOR tv += c[i] * v[i];
|
||||
return tv;
|
||||
}
|
||||
_CVector mul(const _CVector & v) const {
|
||||
assert(c.size() == v.size());
|
||||
_CVector tv(*this);
|
||||
PIMV_FOR tv[i] *= v[i];
|
||||
return tv;
|
||||
}
|
||||
_CVector mul(const Type & v) const {
|
||||
return (*this) * v;
|
||||
}
|
||||
_CVector div(const _CVector & v) const {
|
||||
assert(c.size() == v.size());
|
||||
_CVector tv(*this);
|
||||
PIMV_FOR {
|
||||
assert(piAbs<Type>(v[i]) > PIMATHVECTOR_ZERO_CMP);
|
||||
tv[i] /= v[i];
|
||||
}
|
||||
return tv;
|
||||
}
|
||||
_CVector div(const Type & v) const {
|
||||
return (*this) / v;
|
||||
}
|
||||
|
||||
Type distToLine(const _CVector & lp0, const _CVector & lp1) {
|
||||
assert(c.size() == lp0.size());
|
||||
assert(c.size() == lp1.size());
|
||||
_CVector a = _CVector::fromTwoPoints(lp0, lp1);
|
||||
Type tv = a.length();
|
||||
assert(piAbs<Type>(tv) > PIMATHVECTOR_ZERO_CMP);
|
||||
_CVector b = _CVector::fromTwoPoints(lp0, *this);
|
||||
return piAbs<Type>(a[0]*b[1] - a[1]*b[0]) / tv;
|
||||
}
|
||||
|
||||
template<typename Type1>
|
||||
PIMathVector turnTo(uint size) const {PIMathVector<Type1> tv; uint sz = piMin<uint>(c.size(), size); for (uint i = 0; i < sz; ++i) tv[i] = c[i]; return tv;}
|
||||
PIVector<Type> toVector() const {return c;}
|
||||
|
||||
inline Type * data() {return c.data();}
|
||||
inline const Type * data() const {return c.data();}
|
||||
|
||||
|
||||
static _CVector cross(const _CVector & v1, const _CVector & v2) {
|
||||
return v1.cross(v2);
|
||||
}
|
||||
static _CVector dot(const _CVector & v1, const _CVector & v2) {
|
||||
return v1.dot(v2);
|
||||
}
|
||||
static _CVector mul(const _CVector & v1, const _CVector & v2) {
|
||||
return v1.mul(v2);
|
||||
}
|
||||
static _CVector mul(const Type & v1, const _CVector & v2) {
|
||||
return v2 * v1;
|
||||
}
|
||||
static _CVector mul(const _CVector & v1, const Type & v2) {
|
||||
return v1 * v2;
|
||||
}
|
||||
static _CVector div(const _CVector & v1, const _CVector & v2) {
|
||||
return v1.div(v2);
|
||||
}
|
||||
static _CVector div(const _CVector & v1, const Type & v2) {
|
||||
return v1 / v2;
|
||||
}
|
||||
private:
|
||||
PIVector<Type> c;
|
||||
|
||||
};
|
||||
|
||||
template<typename Type>
|
||||
inline PIMathVector<Type> operator *(const Type & x, const PIMathVector<Type> & v) {
|
||||
return v * x;
|
||||
}
|
||||
|
||||
#undef PIMV_FOR
|
||||
|
||||
#ifdef PIP_STD_IOSTREAM
|
||||
|
||||
@@ -40,7 +40,7 @@ PIMathVectorT3d PIQuaternion::eyler() const {
|
||||
angle_z = atan2(-rmat[0][1] / c, rmat[0][0] / c);
|
||||
}
|
||||
if (angle_z < 0) angle_z = 2*M_PI + angle_z;
|
||||
return createVectorT3d(angle_x,angle_y,angle_z);
|
||||
return PIMathVectorT3d({angle_x,angle_y,angle_z});
|
||||
}
|
||||
|
||||
|
||||
@@ -96,16 +96,6 @@ void PIQuaternion::normalize() {
|
||||
}
|
||||
|
||||
|
||||
PIMathMatrixT44d PIQuaternion::makeMatrix() const {
|
||||
PIMathMatrixT44d ret;
|
||||
ret[0][0] = q[0]; ret[0][1] = -q[1]; ret[0][2] = -q[2]; ret[0][3] = -q[3];
|
||||
ret[1][0] = q[1]; ret[1][1] = q[0]; ret[1][2] = -q[3]; ret[1][3] = q[2];
|
||||
ret[2][0] = q[2]; ret[2][1] = q[3]; ret[2][2] = q[0]; ret[2][3] = -q[1];
|
||||
ret[3][0] = q[3]; ret[3][1] = -q[2]; ret[3][2] = q[1]; ret[3][3] = q[0];
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
PIQuaternion PIQuaternion::fromEyler(double ax, double ay, double az) {
|
||||
PIQuaternion q_heading;
|
||||
PIQuaternion q_pinch;
|
||||
@@ -153,7 +143,7 @@ PIQuaternion PIQuaternion::fromAngles(double ax, double ay, double az) {
|
||||
}
|
||||
|
||||
PIQuaternion PIQuaternion::fromAngles2(double ax, double ay, double az) {
|
||||
double om = createVectorT3d(ax,ay,az).length();
|
||||
double om = PIMathVectorT3d({ax,ay,az}).length();
|
||||
if (om == 0.) return PIQuaternion(PIMathVectorT3d(), 1.);
|
||||
PIQuaternion res;
|
||||
res.q[0] = cos(om/2);
|
||||
@@ -199,8 +189,8 @@ PIQuaternion PIQuaternion::fromRotationMatrix(const PIMathMatrixT33d & m) {
|
||||
|
||||
PIQuaternion operator*(const PIQuaternion & q0, const PIQuaternion & q1) {
|
||||
PIMathVectorT3d v0(q0.vector()), v1(q1.vector());
|
||||
double r0 = q0.q[0] * q1.q[0] - (v0^v1);
|
||||
PIMathVectorT3d qv = v1*q0.q[0] + v0*q1.q[0] + v0*v1;
|
||||
double r0 = q0.q[0] * q1.q[0] - v0.dot(v1);
|
||||
PIMathVectorT3d qv = v1*q0.q[0] + v0*q1.q[0] + v0.cross(v1);
|
||||
PIQuaternion ret;
|
||||
ret.q[0] = r0;
|
||||
ret.q[1] = qv[0];
|
||||
|
||||
@@ -39,7 +39,7 @@ public:
|
||||
|
||||
double & scalar() {return q[0];}
|
||||
double scalar() const {return q[0];}
|
||||
PIMathVectorT3d vector() const {return createVectorT3<double>(q[1], q[2], q[3]);}
|
||||
PIMathVectorT3d vector() const {return PIMathVectorT3d({q[1], q[2], q[3]});}
|
||||
|
||||
PIMathVectorT3d eyler() const;
|
||||
PIMathMatrixT33d rotationMatrix() const;
|
||||
@@ -52,9 +52,6 @@ public:
|
||||
|
||||
protected:
|
||||
double q[4];
|
||||
PIMathMatrixT44d makeMatrix() const;
|
||||
|
||||
|
||||
};
|
||||
|
||||
PIP_EXPORT PIQuaternion operator *(const double & a, const PIQuaternion & q);
|
||||
|
||||
@@ -31,11 +31,13 @@ public:
|
||||
struct Device;
|
||||
struct Platform;
|
||||
class Context;
|
||||
class Buffer;
|
||||
class Program;
|
||||
class Kernel;
|
||||
|
||||
typedef PIVector<Device> DeviceList;
|
||||
|
||||
|
||||
enum AddressQualifier {
|
||||
AddressGlobal,
|
||||
AddressLocal,
|
||||
@@ -50,6 +52,12 @@ public:
|
||||
AccessNone,
|
||||
};
|
||||
|
||||
enum Direction {
|
||||
Input = 0x01,
|
||||
Output = 0x02,
|
||||
InputOutput = Input | Output,
|
||||
};
|
||||
|
||||
enum TypeQualifier {
|
||||
TypeConst,
|
||||
TypeRestrict,
|
||||
@@ -70,10 +78,12 @@ public:
|
||||
Double,
|
||||
};
|
||||
|
||||
|
||||
struct PIP_OPENCL_EXPORT KernelArg {
|
||||
KernelArg();
|
||||
AddressQualifier address_qualifier;
|
||||
AccessQualifier access_qualifier;
|
||||
Direction direction;
|
||||
TypeQualifier type_qualifier;
|
||||
PIString arg_name;
|
||||
PIString type_name;
|
||||
@@ -86,6 +96,7 @@ public:
|
||||
void init(void * _k, uint index);
|
||||
};
|
||||
|
||||
|
||||
struct PIP_OPENCL_EXPORT Device {
|
||||
Device() {id = platform_id = 0; max_compute_units = max_clock_frequency = 0; max_memory_size = 0;}
|
||||
bool isValid() const {return id != 0;}
|
||||
@@ -101,6 +112,7 @@ public:
|
||||
ullong max_memory_size;
|
||||
};
|
||||
|
||||
|
||||
struct PIP_OPENCL_EXPORT Platform {
|
||||
Platform() {id = 0;}
|
||||
bool isValid() const {return id != 0;}
|
||||
@@ -114,28 +126,86 @@ public:
|
||||
PIVector<Device> devices;
|
||||
};
|
||||
|
||||
|
||||
class PIP_OPENCL_EXPORT Context {
|
||||
friend class Buffer;
|
||||
friend class Program;
|
||||
friend class Kernel;
|
||||
public:
|
||||
~Context();
|
||||
static Context * create(const DeviceList & dl);
|
||||
static Context * create(const Device & d) {return create(DeviceList() << d);}
|
||||
static Context * create(const PIString & part_name);
|
||||
Program * createProgram(const PIString & source, PIString * error = 0);
|
||||
template <typename T> Buffer * createBuffer(PIOpenCL::Direction dir, PIVector <T> & container) {
|
||||
T def = T();
|
||||
return createBuffer(dir, &container, Buffer::cVector , PIByteArray(&def, sizeof(T)), container.size());
|
||||
}
|
||||
template <typename T> Buffer * createBuffer(PIOpenCL::Direction dir, PIDeque <T> & container) {
|
||||
T def = T();
|
||||
return createBuffer(dir, &container, Buffer::cDeque , PIByteArray(&def, sizeof(T)), container.size());
|
||||
}
|
||||
template <typename T> Buffer * createBuffer(PIOpenCL::Direction dir, PIVector2D<T> & container) {
|
||||
T def = T();
|
||||
return createBuffer(dir, &container, Buffer::cVector2D, PIByteArray(&def, sizeof(T)), container.size());
|
||||
}
|
||||
template <typename T> Buffer * createBuffer(PIOpenCL::Direction dir, uint elements) {
|
||||
T def = T();
|
||||
Buffer * ret = createBuffer(dir, 0, Buffer::cNone, PIByteArray(&def, sizeof(T)), elements);
|
||||
if (ret)
|
||||
ret->clear();
|
||||
return ret;
|
||||
}
|
||||
private:
|
||||
Context();
|
||||
void zero();
|
||||
void deletePrograms();
|
||||
void deleteBuffers();
|
||||
Buffer * createBuffer(PIOpenCL::Direction dir, void * container, int type, PIByteArray def, uint elements);
|
||||
PIVector<Program * > programs_;
|
||||
PIVector<Buffer * > buffers_;
|
||||
PRIVATE_DECLARATION(PIP_OPENCL_EXPORT)
|
||||
};
|
||||
|
||||
|
||||
class PIP_OPENCL_EXPORT Buffer {
|
||||
friend class Context;
|
||||
friend class Kernel;
|
||||
public:
|
||||
~Buffer();
|
||||
bool resize(uint new_elements);
|
||||
void clear();
|
||||
void copyToContainer();
|
||||
void copyFromContainer();
|
||||
private:
|
||||
enum Container {
|
||||
cNone,
|
||||
cVector,
|
||||
cDeque,
|
||||
cVector2D,
|
||||
};
|
||||
Buffer();
|
||||
void zero();
|
||||
bool init();
|
||||
void * containerData();
|
||||
Context * context_;
|
||||
Direction dir;
|
||||
Container type;
|
||||
void * container;
|
||||
PIByteArray def;
|
||||
uint elements;
|
||||
PRIVATE_DECLARATION(PIP_OPENCL_EXPORT)
|
||||
};
|
||||
|
||||
|
||||
class PIP_OPENCL_EXPORT Program {
|
||||
friend class Context;
|
||||
friend class Kernel;
|
||||
friend class Buffer;
|
||||
public:
|
||||
~Program();
|
||||
const PIString & sourceCode() const {return source_;}
|
||||
const Kernel * kernel(int index = 0) const {return kernels_[index];}
|
||||
Kernel * kernel(int index = 0) const {return kernels_[index];}
|
||||
const PIVector<Kernel * > & kernels() const {return kernels_;}
|
||||
private:
|
||||
Program();
|
||||
@@ -147,28 +217,38 @@ public:
|
||||
PRIVATE_DECLARATION(PIP_OPENCL_EXPORT)
|
||||
};
|
||||
|
||||
|
||||
class PIP_OPENCL_EXPORT Kernel {
|
||||
friend class Program;
|
||||
friend class Buffer;
|
||||
public:
|
||||
bool execute();
|
||||
void setExecuteRange(int size) {setExecuteRanges(PIVector<int>() << size);}
|
||||
void setExecuteRanges(const PIVector<int> & ranges);
|
||||
const PIString & name() const {return name_;}
|
||||
const PIVector<KernelArg> & args() const {return args_;}
|
||||
template <typename T> bool setArgValue(int index, const T & value) {return setArgValueV(index, PIVariant::fromValue(value));}
|
||||
template <typename T> bool setArgValue(int index, const T & value) {return setArgValueS(index, PIVariant::fromValue(value));}
|
||||
template <typename T> bool setArgValue(const PIString & arg, const T & value) {return setArgValue(argIndex(arg), value);}
|
||||
bool setArgValue(const PIString & arg, const PIVariant & value) {return setArgValueS(argIndex(arg), value);}
|
||||
bool bindArgValue(int index, Buffer * buffer);
|
||||
bool bindArgValue(const PIString & arg, Buffer * buffer) {return bindArgValue(argIndex(arg), buffer);}
|
||||
private:
|
||||
Kernel();
|
||||
~Kernel();
|
||||
void zero();
|
||||
bool init();
|
||||
bool setArgValueV(int index, const PIVariant & value);
|
||||
bool setArgValueS(int index, const PIVariant & value);
|
||||
int argIndex(const PIString & an) const;
|
||||
KernelArg argByName(const PIString & an) const;
|
||||
Context * context_;
|
||||
Program * program_;
|
||||
PIString name_;
|
||||
PIVector<KernelArg> args_;
|
||||
PIVector<size_t> dims;
|
||||
PRIVATE_DECLARATION(PIP_OPENCL_EXPORT)
|
||||
};
|
||||
|
||||
|
||||
static void init();
|
||||
static const PIVector<Platform> & platforms();
|
||||
static const PIVector<Device> devices();
|
||||
@@ -189,7 +269,7 @@ private:
|
||||
};
|
||||
|
||||
|
||||
PICout operator <<(PICout s, const PIOpenCL::KernelArg & v);
|
||||
PIP_OPENCL_EXPORT PICout operator <<(PICout s, const PIOpenCL::KernelArg & v);
|
||||
|
||||
|
||||
#endif // PIOPENCL_H
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
/*! \file pilibrary.h
|
||||
* \brief Dynamic library
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Dynamic library
|
||||
|
||||
398
libs/main/system/piplugin.cpp
Normal file
398
libs/main/system/piplugin.cpp
Normal file
@@ -0,0 +1,398 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Plugin helpers
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PIP_FREERTOS
|
||||
|
||||
#include "piplugin.h"
|
||||
#include "pifile.h"
|
||||
#include "piincludes_p.h"
|
||||
|
||||
/*! \class PIPluginLoader
|
||||
* \brief Plugin loader
|
||||
*
|
||||
* \section PIPluginLoader_sec0 Synopsis
|
||||
* This class provides several macro to define plugin and %PIPluginLoader - class
|
||||
* to load and check plugin.
|
||||
*
|
||||
* \section PIPluginLoader_sec1 Plugin side
|
||||
* Plugin is a shared library that can be loaded in run-time.
|
||||
* This is only PIP_PLUGIN macro necessary to define plugin.
|
||||
* If you want to set and check some version, use macro
|
||||
* \a PIP_PLUGIN_SET_USER_VERSION(version). Also you can
|
||||
* define a function to merge static sections between application
|
||||
* and plugin with macro \a PIP_PLUGIN_STATIC_SECTION_MERGE. Before
|
||||
* merge, you should set pointers to that sections with macro
|
||||
* \a PIP_PLUGIN_ADD_STATIC_SECTION(type, ptr).
|
||||
*
|
||||
* \section PIPluginLoader_sec2 Application side
|
||||
* Application should use class \a PIPluginLoader to load
|
||||
* plugin. Main function is \a load(PIString name).
|
||||
* "name" is base name of library, %PIPluginLoader
|
||||
* try to use sevaral names, <name>, lib<name> and
|
||||
* "dll", "so" and "dylib" extensions, depends on system.
|
||||
* For example:
|
||||
* \code
|
||||
* PIPluginLoader l;
|
||||
* l.load("foo");
|
||||
* \endcode
|
||||
* On Windows, try to open "foo", "libfoo", "foo.dll" and
|
||||
* "libfoo.dll".
|
||||
* If you using user version check, you should set it
|
||||
* with macro \a PIP_PLUGIN_SET_USER_VERSION(version).
|
||||
* When plugin is successfully loaded and checked,
|
||||
* you can load your custom symbols with function
|
||||
* \a resolve(name), similar to PILibrary.
|
||||
* \note You should use PIP_PLUGIN_EXPORT and "export "C""
|
||||
* with functions you want to use with \a resolve(name)!
|
||||
*
|
||||
* \section PIPluginLoader_sec3 Static sections
|
||||
* Macro \a PIP_PLUGIN_STATIC_SECTION_MERGE defines function
|
||||
* with arguments (int type, void * from, void * to), so you
|
||||
* can leave this macro as declaration or define its body next:
|
||||
* \code
|
||||
* PIP_PLUGIN_STATIC_SECTION_MERGE() {
|
||||
* switch (type) {
|
||||
* ...
|
||||
* }
|
||||
* }
|
||||
* \endcode
|
||||
* \note If you using singletones, remember that cpp-defined
|
||||
* singletones in shared libraries are single for whole application,
|
||||
* including plugins! But if you use h-defined singletones or
|
||||
* static linking, there are many objects in application and you
|
||||
* should merge their content with this macro.
|
||||
*
|
||||
* Anyway, if this is macro \a PIP_PLUGIN_STATIC_SECTION_MERGE, it
|
||||
* called once while loading plugin with "from" - plugin side
|
||||
* and "to" - application side, and second (optionally) on method
|
||||
* \a mergeStatic() with "from" - application side and "to" - plugin side.
|
||||
* First direction allow you to copy all defined static content from plugin
|
||||
* to application, and second - after loading all plugins (for example)
|
||||
* to copy static content from application (and all plugins) to plugin.
|
||||
*
|
||||
* \section PIPluginLoader_sec4 Examples
|
||||
* Simple plugin:
|
||||
* \code
|
||||
* #include <piplugin.h>
|
||||
*
|
||||
* PIP_PLUGIN
|
||||
*
|
||||
* extern "C" {
|
||||
* PIP_PLUGIN_EXPORT void myFunc() {
|
||||
* piCout << "Hello plugin!";
|
||||
* }
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* Application:
|
||||
* \code
|
||||
* #include <piplugin.h>
|
||||
* int main() {
|
||||
* PIPluginLoader pl;
|
||||
* pl.load("your_lib");
|
||||
* if (pl.isLoaded()) {
|
||||
* typedef void(*MyFunc)();
|
||||
* MyFunc f = (MyFunc)pl.resolve("myFunc");
|
||||
* if (f) f();
|
||||
* }
|
||||
* return 0;
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* Complex plugin:
|
||||
* \code
|
||||
* #include <piplugin.h>
|
||||
*
|
||||
* PIStringList global_list;
|
||||
*
|
||||
* PIP_PLUGIN
|
||||
* PIP_PLUGIN_SET_USER_VERSION("1.0.0")
|
||||
* PIP_PLUGIN_ADD_STATIC_SECTION(1, &global_list)
|
||||
*
|
||||
* STATIC_INITIALIZER_BEGIN
|
||||
* global_list << "plugin_init";
|
||||
* STATIC_INITIALIZER_END
|
||||
*
|
||||
* PIP_PLUGIN_STATIC_SECTION_MERGE {
|
||||
* PIStringList * sfrom = (PIStringList*)from, * sto = (PIStringList*)to;
|
||||
* *sto << *sfrom;
|
||||
* sto->removeDuplicates();
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* Application:
|
||||
* \code
|
||||
* #include <piplugin.h>
|
||||
*
|
||||
* PIStringList global_list;
|
||||
*
|
||||
* PIP_PLUGIN_SET_USER_VERSION("1.0.0");
|
||||
* PIP_PLUGIN_ADD_STATIC_SECTION(1, &global_list);
|
||||
*
|
||||
* int main() {
|
||||
* global_list << "app";
|
||||
* PIPluginLoader pl;
|
||||
* pl.load("your_lib");
|
||||
* pl.mergeStatic();
|
||||
* piCout << "list =" << global_list;
|
||||
* return 0;
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
*/
|
||||
|
||||
#define STR_WF(s) #s
|
||||
#define STR(s) STR_WF(s)
|
||||
|
||||
|
||||
PIPluginInfo::PIPluginInfo() {
|
||||
}
|
||||
|
||||
|
||||
void PIPluginInfo::setUserVersion(const PIString & v) {
|
||||
user_version = v;
|
||||
}
|
||||
|
||||
|
||||
void PIPluginInfo::setStaticSection(int type, void * ptr) {
|
||||
static_sections[type] = ptr;
|
||||
}
|
||||
|
||||
|
||||
PIString PIPluginInfo::userVersion() const {
|
||||
return user_version;
|
||||
}
|
||||
|
||||
|
||||
PIMap<int, void *> PIPluginInfo::staticSections() const {
|
||||
return static_sections;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
PIPluginInfoStorage::PIPluginInfoStorage() {
|
||||
enterPlugin(0);
|
||||
}
|
||||
|
||||
|
||||
PIPluginInfo * PIPluginInfoStorage::currentInfo() {
|
||||
return info[current];
|
||||
}
|
||||
|
||||
|
||||
PIPluginInfo * PIPluginInfoStorage::pluginInfo(void * p) {
|
||||
return info.value(p, nullptr);
|
||||
}
|
||||
|
||||
|
||||
PIPluginInfo * PIPluginInfoStorage::applicationInfo() {
|
||||
return info[0];
|
||||
}
|
||||
|
||||
|
||||
PIPluginInfo * PIPluginInfoStorage::enterPlugin(void * p) {
|
||||
current = p;
|
||||
PIPluginInfo *& i(info[p]);
|
||||
if (!i) i = new PIPluginInfo();
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
void PIPluginInfoStorage::unloadPlugin(void * p) {
|
||||
if (current == p) current = 0;
|
||||
PIPluginInfo *& i(info[p]);
|
||||
if (i) delete i;
|
||||
info.remove(p);
|
||||
}
|
||||
|
||||
|
||||
PIPluginInfoStorage * PIPluginInfoStorage::instance() {
|
||||
static PIPluginInfoStorage ret;
|
||||
return &ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
PIPluginLoader::PIPluginLoader(const PIString & name) {
|
||||
func_loader_version = nullptr;
|
||||
func_static_merge = nullptr;
|
||||
error = Unknown;
|
||||
loaded = false;
|
||||
messages = true;
|
||||
if (!name.isEmpty())
|
||||
load(name);
|
||||
}
|
||||
|
||||
|
||||
PIPluginLoader::~PIPluginLoader() {
|
||||
unload();
|
||||
}
|
||||
|
||||
|
||||
bool PIPluginLoader::load(const PIString & name) {
|
||||
unload();
|
||||
PIPluginInfo * ai = PIPluginInfoStorage::instance()->applicationInfo();
|
||||
PIPluginInfo * pi = PIPluginInfoStorage::instance()->enterPlugin(this);
|
||||
if (!lib.load(findLibrary(name))) {
|
||||
unload();
|
||||
error = LibraryLoadError;
|
||||
error_str = "Load plugin \"" + lib.path() + "\" error: can`t load lib: " + lib.lastError();
|
||||
if (messages) piCout << error_str;
|
||||
return false;
|
||||
}
|
||||
//piCout << "loading" << lib.path() << "...";
|
||||
func_loader_version = (FunctionLoaderVersion)lib.resolve(STR(__PIP_PLUGIN_LOADER_VERSION_FUNC__));
|
||||
if (!func_loader_version) {
|
||||
unload();
|
||||
error = MissingSymbols;
|
||||
error_str = "Load plugin \"" + lib.path() + "\" error: can`t find " + STR(__PIP_PLUGIN_LOADER_VERSION_FUNC__);
|
||||
if (messages) piCout << error_str;
|
||||
return false;
|
||||
}
|
||||
if (__PIP_PLUGIN_LOADER_VERSION__ != func_loader_version()) {
|
||||
unload();
|
||||
error = InvalidLoaderVersion;
|
||||
error_str = "Load plugin \"" + lib.path() + "\" error: invalid loader version: application = " + PIString::fromNumber(func_loader_version())
|
||||
+ ", plugin = " + PIString::fromNumber(__PIP_PLUGIN_LOADER_VERSION__);
|
||||
if (messages) piCout << error_str;
|
||||
return false;
|
||||
}
|
||||
if (ai->userVersion().size_s() > 1) {
|
||||
PIString pversion = pi->userVersion(), lversion = ai->userVersion();
|
||||
if (pversion != lversion) {
|
||||
unload();
|
||||
error = InvalidUserVersion;
|
||||
error_str = "Load plugin \"" + lib.path() + "\" error: invalid user version: application = " + lversion + ", plugin = " + pversion;
|
||||
if (messages) piCout << error_str;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
func_static_merge = (FunctionStaticMerge)lib.resolve(STR(__PIP_PLUGIN_STATIC_MERGE_FUNC__));
|
||||
if (func_static_merge) {
|
||||
auto pss = pi->staticSections(), lss = ai->staticSections();
|
||||
//piCout << lss.keys() << pss.keys();
|
||||
auto it = lss.makeIterator();
|
||||
while (it.next()) {
|
||||
if (!pss.contains(it.key()))
|
||||
continue;
|
||||
void * from = pss.value(it.key()), * to = it.value();
|
||||
if (from != to)
|
||||
func_static_merge(it.key(), from, to);
|
||||
}
|
||||
}
|
||||
loaded = true;
|
||||
error = NoError;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void PIPluginLoader::unload() {
|
||||
lib.unload();
|
||||
loaded = false;
|
||||
error_str.clear();
|
||||
error = Unknown;
|
||||
PIPluginInfoStorage::instance()->unloadPlugin(this);
|
||||
}
|
||||
|
||||
|
||||
bool PIPluginLoader::isLoaded() const {
|
||||
return loaded;
|
||||
}
|
||||
|
||||
|
||||
PIPluginLoader::Error PIPluginLoader::lastError() const {
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
PIString PIPluginLoader::lastErrorText() const {
|
||||
return error_str;
|
||||
}
|
||||
|
||||
|
||||
void PIPluginLoader::setMessages(bool yes) {
|
||||
messages = yes;
|
||||
}
|
||||
|
||||
|
||||
bool PIPluginLoader::isMessages() const {
|
||||
return messages;
|
||||
}
|
||||
|
||||
|
||||
PIString PIPluginLoader::libPath() {
|
||||
return lib.path();
|
||||
}
|
||||
|
||||
|
||||
void * PIPluginLoader::resolve(const char * name) {
|
||||
if (!loaded) return nullptr;
|
||||
return lib.resolve(name);
|
||||
}
|
||||
|
||||
|
||||
void PIPluginLoader::mergeStatic() {
|
||||
if (!loaded || !func_static_merge) return;
|
||||
PIPluginInfo * ai = PIPluginInfoStorage::instance()->applicationInfo();
|
||||
PIPluginInfo * pi = PIPluginInfoStorage::instance()->pluginInfo(this);
|
||||
auto pss = pi->staticSections(), lss = ai->staticSections();
|
||||
auto it = lss.makeIterator();
|
||||
while (it.next()) {
|
||||
if (!pss.contains(it.key()))
|
||||
continue;
|
||||
void * from = it.value(), * to = pss.value(it.key());
|
||||
if (from != to)
|
||||
func_static_merge(it.key(), from, to);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PIString PIPluginLoader::findLibrary(const PIString & path) {
|
||||
static const PIStringList prefixes({"", "lib"});
|
||||
static const PIStringList suffixes({"", libExtension()});
|
||||
PIFile::FileInfo fi(path);
|
||||
PIString dir = fi.dir(), name = fi.name();
|
||||
piForeachC (PIString & p, prefixes) {
|
||||
piForeachC (PIString & s, suffixes) {
|
||||
PIString fn = dir + p + name + s;
|
||||
if (PIFile::isExists(fn))
|
||||
return fn;
|
||||
}
|
||||
}
|
||||
return PIString();
|
||||
}
|
||||
|
||||
|
||||
PIString PIPluginLoader::libExtension() {
|
||||
return
|
||||
#ifdef WINDOWS
|
||||
".dll"
|
||||
#elif defined(MAC_OS)
|
||||
".dylib"
|
||||
#else
|
||||
".so"
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
#endif // PIP_FREERTOS
|
||||
214
libs/main/system/piplugin.h
Normal file
214
libs/main/system/piplugin.h
Normal file
@@ -0,0 +1,214 @@
|
||||
/*! \file piplugin.h
|
||||
* \brief Plugin helpers
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Plugin helpers
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PIPLUGIN_H
|
||||
#define PIPLUGIN_H
|
||||
|
||||
#ifndef PIP_FREERTOS
|
||||
|
||||
#include "pilibrary.h"
|
||||
#include "pistringlist.h"
|
||||
|
||||
#ifdef DOXYGEN
|
||||
|
||||
|
||||
//! Declare plugin export functions, should be used before other PIP_PLUGIN_* macros
|
||||
//! \relatedalso PIPluginLoader
|
||||
#define PIP_PLUGIN
|
||||
|
||||
//! Set user version to check it while loading
|
||||
//! \relatedalso PIPluginLoader
|
||||
#define PIP_PLUGIN_SET_USER_VERSION(version)
|
||||
|
||||
//! Add pointer to future merge with plugin. Type is integer
|
||||
//! \relatedalso PIPluginLoader
|
||||
#define PIP_PLUGIN_ADD_STATIC_SECTION(type, ptr)
|
||||
|
||||
//! Declare function to merge static sections. This is functions
|
||||
//! with 3 arguments: (int type, void * from, void * to).
|
||||
//! This function invoked first while loading plugin with
|
||||
//! "from" - plugin scope, "to" - application scope, and second
|
||||
//! (optionally) on \a PIPluginLoader::mergeStatic() method with
|
||||
//! "from" - application scope, "to" - plugin scope. So with macro
|
||||
//! you can merge application and plugin static data.
|
||||
//! \relatedalso PIPluginLoader
|
||||
#define PIP_PLUGIN_STATIC_SECTION_MERGE
|
||||
|
||||
//! Mark method to export
|
||||
//! \relatedalso PIPluginLoader
|
||||
#define PIP_PLUGIN_EXPORT
|
||||
|
||||
|
||||
#else
|
||||
|
||||
|
||||
#ifdef WINDOWS
|
||||
# define PIP_PLUGIN_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
# define PIP_PLUGIN_EXPORT
|
||||
#endif
|
||||
|
||||
#define __PIP_PLUGIN_LOADER_VERSION_FUNC__ pip_loader_version
|
||||
#define __PIP_PLUGIN_STATIC_MERGE_FUNC__ pip_merge_static
|
||||
#define __PIP_PLUGIN_LOADER_VERSION__ 2
|
||||
|
||||
#define PIP_PLUGIN_SET_USER_VERSION(v) \
|
||||
STATIC_INITIALIZER_BEGIN \
|
||||
PIPluginInfo * pi = PIPluginInfoStorage::instance()->currentInfo(); \
|
||||
if (pi) pi->setUserVersion(v); \
|
||||
STATIC_INITIALIZER_END
|
||||
|
||||
#define PIP_PLUGIN_ADD_STATIC_SECTION(type, ptr) \
|
||||
STATIC_INITIALIZER_BEGIN \
|
||||
PIPluginInfo * pi = PIPluginInfoStorage::instance()->currentInfo(); \
|
||||
if (pi) pi->setStaticSection(type, ptr); \
|
||||
STATIC_INITIALIZER_END
|
||||
|
||||
#define PIP_PLUGIN \
|
||||
extern "C" { \
|
||||
PIP_PLUGIN_EXPORT int __PIP_PLUGIN_LOADER_VERSION_FUNC__() {return __PIP_PLUGIN_LOADER_VERSION__;} \
|
||||
}
|
||||
|
||||
#define PIP_PLUGIN_STATIC_SECTION_MERGE \
|
||||
extern "C" { \
|
||||
PIP_PLUGIN_EXPORT void __PIP_PLUGIN_STATIC_MERGE_FUNC__(int type, void * from, void * to); \
|
||||
} \
|
||||
void __PIP_PLUGIN_STATIC_MERGE_FUNC__(int type, void * from, void * to)
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
class PIP_EXPORT PIPluginInfo {
|
||||
public:
|
||||
PIPluginInfo();
|
||||
|
||||
void setUserVersion(const PIString & v);
|
||||
void setStaticSection(int type, void * ptr);
|
||||
PIString userVersion() const;
|
||||
PIMap<int, void*> staticSections() const;
|
||||
|
||||
private:
|
||||
PIString user_version;
|
||||
PIMap<int, void*> static_sections;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
class PIP_EXPORT PIPluginInfoStorage {
|
||||
public:
|
||||
PIPluginInfoStorage();
|
||||
|
||||
PIPluginInfo * currentInfo();
|
||||
PIPluginInfo * pluginInfo(void * p);
|
||||
PIPluginInfo * applicationInfo();
|
||||
PIPluginInfo * enterPlugin(void * p);
|
||||
void unloadPlugin(void * p);
|
||||
|
||||
static PIPluginInfoStorage * instance();
|
||||
|
||||
private:
|
||||
NO_COPY_CLASS(PIPluginInfoStorage)
|
||||
|
||||
void * current;
|
||||
PIMap<void*, PIPluginInfo * > info;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
class PIP_EXPORT PIPluginLoader {
|
||||
public:
|
||||
typedef int(*FunctionLoaderVersion)();
|
||||
typedef void(*FunctionStaticMerge)(int, void *, void *);
|
||||
|
||||
//! Possible load plugin error
|
||||
enum Error {
|
||||
Unknown /** No \a load call yet */ ,
|
||||
NoError /** No error */ ,
|
||||
LibraryLoadError /** System can`t load library */ ,
|
||||
MissingSymbols /** Can`t find necessary symbols */ ,
|
||||
InvalidLoaderVersion /** Integer version mismatch */ ,
|
||||
InvalidUserVersion /** User version mismatch */ ,
|
||||
};
|
||||
|
||||
//! Contruscts loader with filename "name"
|
||||
PIPluginLoader(const PIString & name = PIString());
|
||||
|
||||
//! Destructor
|
||||
~PIPluginLoader();
|
||||
|
||||
|
||||
//! Load plugin with base filename "name". Loader try prefix "lib"
|
||||
//! and suffix ".dll", ".so" or ".dylib", depends on platform
|
||||
bool load(const PIString & name);
|
||||
|
||||
//! Unload plugin and free library
|
||||
void unload();
|
||||
|
||||
//! Returns if plugin is successfully loaded
|
||||
bool isLoaded() const;
|
||||
|
||||
//! Returns error of last \a load() call
|
||||
Error lastError() const;
|
||||
|
||||
//! Returns error message of last \a load() call
|
||||
PIString lastErrorText() const;
|
||||
|
||||
//! Set if %PIPluginLoader should print load messages, \b true by default
|
||||
void setMessages(bool yes);
|
||||
|
||||
//! Returns if %PIPluginLoader should print load messages, \b true by default
|
||||
bool isMessages() const;
|
||||
|
||||
//! Returns loaded plugin library path
|
||||
PIString libPath();
|
||||
|
||||
//! Resolve symbol "name" from plugin library
|
||||
void * resolve(const char * name);
|
||||
|
||||
//! Invoke plugin PIP_PLUGIN_STATIC_SECTION_MERGE function
|
||||
//! on every common type, with "from" - application scope,
|
||||
//! "to" - plugin scope
|
||||
void mergeStatic();
|
||||
|
||||
private:
|
||||
NO_COPY_CLASS(PIPluginLoader)
|
||||
|
||||
PIString findLibrary(const PIString & path);
|
||||
static PIString libExtension();
|
||||
|
||||
PILibrary lib;
|
||||
FunctionLoaderVersion func_loader_version;
|
||||
FunctionStaticMerge func_static_merge;
|
||||
PIString error_str;
|
||||
Error error;
|
||||
bool loaded, messages;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // PIP_FREERTOS
|
||||
#endif // PIPLUGIN_H
|
||||
@@ -35,7 +35,6 @@ PRIVATE_DEFINITION_START(PIConditionVariable)
|
||||
CONDITION_VARIABLE nativeHandle;
|
||||
#else
|
||||
pthread_cond_t nativeHandle;
|
||||
PIMutex * currentLock;
|
||||
#endif
|
||||
bool isDestroying;
|
||||
PRIVATE_DEFINITION_END(PIConditionVariable)
|
||||
@@ -46,9 +45,14 @@ PIConditionVariable::PIConditionVariable() {
|
||||
InitializeConditionVariable(&PRIVATE->nativeHandle);
|
||||
#else
|
||||
PRIVATE->isDestroying = false;
|
||||
PRIVATE->currentLock = nullptr;
|
||||
|
||||
pthread_condattr_t condattr;
|
||||
pthread_condattr_init(&condattr);
|
||||
# ifndef MAC_OS
|
||||
pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC);
|
||||
# endif
|
||||
memset(&(PRIVATE->nativeHandle), 0, sizeof(PRIVATE->nativeHandle));
|
||||
pthread_cond_init(&PRIVATE->nativeHandle, NULL);
|
||||
pthread_cond_init(&PRIVATE->nativeHandle, &condattr);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -90,8 +94,11 @@ bool PIConditionVariable::waitFor(PIMutex &lk, int timeoutMs) {
|
||||
#ifdef WINDOWS
|
||||
isNotTimeout = SleepConditionVariableCS(&PRIVATE->nativeHandle, (PCRITICAL_SECTION)lk.handle(), timeoutMs) != 0;
|
||||
#else
|
||||
timespec abstime = {.tv_sec = timeoutMs / 1000, .tv_nsec = timeoutMs % 1000 * 1000000};
|
||||
isNotTimeout = pthread_cond_timedwait(&PRIVATE->nativeHandle, (pthread_mutex_t*)lk.handle(), &abstime) == 0;
|
||||
timespec expire_ts;
|
||||
PISystemTime st = PISystemTime::current(true);
|
||||
st.addMilliseconds(timeoutMs);
|
||||
st.toTimespec(&expire_ts);
|
||||
isNotTimeout = pthread_cond_timedwait(&PRIVATE->nativeHandle, (pthread_mutex_t*)lk.handle(), &expire_ts) == 0;
|
||||
#endif
|
||||
if (PRIVATE->isDestroying) return false;
|
||||
return isNotTimeout;
|
||||
@@ -100,7 +107,14 @@ bool PIConditionVariable::waitFor(PIMutex &lk, int timeoutMs) {
|
||||
|
||||
bool PIConditionVariable::waitFor(PIMutex& lk, int timeoutMs, const std::function<bool()> &condition) {
|
||||
bool isCondition;
|
||||
#ifdef WINDOWS
|
||||
PITimeMeasurer measurer;
|
||||
#else
|
||||
timespec expire_ts;
|
||||
PISystemTime st = PISystemTime::current(true);
|
||||
st.addMilliseconds(timeoutMs);
|
||||
st.toTimespec(&expire_ts);
|
||||
#endif
|
||||
while (true) {
|
||||
isCondition = condition();
|
||||
if (isCondition) break;
|
||||
@@ -110,9 +124,7 @@ bool PIConditionVariable::waitFor(PIMutex& lk, int timeoutMs, const std::functio
|
||||
(PCRITICAL_SECTION)lk.handle(),
|
||||
timeoutMs - (int)measurer.elapsed_m()) == 0;
|
||||
#else
|
||||
int timeoutCurr = timeoutMs - (int)measurer.elapsed_m();
|
||||
timespec abstime = {.tv_sec = timeoutCurr / 1000, .tv_nsec = timeoutCurr % 1000 * 1000000};
|
||||
bool isTimeout = pthread_cond_timedwait(&PRIVATE->nativeHandle, (pthread_mutex_t*)lk.handle(), &abstime) != 0;
|
||||
bool isTimeout = pthread_cond_timedwait(&PRIVATE->nativeHandle, (pthread_mutex_t*)lk.handle(), &expire_ts) != 0;
|
||||
#endif
|
||||
if (isTimeout) return false;
|
||||
if (PRIVATE->isDestroying) return false;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Mutex
|
||||
PIMutex, PIMutexLocker
|
||||
Ivan Pelipenko peri4ko@yandex.ru, Stephan Fomenko, Andrey Bychkov work.a.b@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
@@ -105,7 +105,7 @@ void PIMutex::init() {
|
||||
pthread_mutexattr_t attr;
|
||||
memset(&attr, 0, sizeof(attr));
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||
memset(&(PRIVATE->mutex), 0, sizeof(PRIVATE->mutex));
|
||||
pthread_mutex_init(&(PRIVATE->mutex), &attr);
|
||||
pthread_mutexattr_destroy(&attr);
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/*! \file pimutex.h
|
||||
* \brief PIMutexLocker
|
||||
* \brief PIMutex, PIMutexLocker
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
PIMutexLocker
|
||||
PIMutex, PIMutexLocker
|
||||
Ivan Pelipenko peri4ko@yandex.ru, Stephan Fomenko, Andrey Bychkov work.a.b@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
|
||||
30
libs/main/thread/pispinlock.cpp
Normal file
30
libs/main/thread/pispinlock.cpp
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
PISpinlock
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** \class PISpinlock
|
||||
* \brief Spinlock
|
||||
* \details
|
||||
* \section PISpinlock_sec0 Synopsis
|
||||
* %PISpinlock provides synchronization blocks between several threads.
|
||||
* PISpinlock functionality similar to PIMutex, but working on atomic
|
||||
* type and \a lock() method wait with 100% CPU load.
|
||||
* \note
|
||||
* Use this type instead of PIMutex when less waiting time is more
|
||||
* important than CPU load!
|
||||
* */
|
||||
75
libs/main/thread/pispinlock.h
Normal file
75
libs/main/thread/pispinlock.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/*! \file pispinlock.h
|
||||
* \brief PISpinlock
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
PISpinlock
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PISPINLOCK_H
|
||||
#define PISPINLOCK_H
|
||||
|
||||
#include "piinit.h"
|
||||
#include <atomic>
|
||||
|
||||
|
||||
class PIP_EXPORT PISpinlock
|
||||
{
|
||||
public:
|
||||
NO_COPY_CLASS(PISpinlock)
|
||||
|
||||
//! Constructs unlocked spinlock
|
||||
explicit PISpinlock() {flag.clear();}
|
||||
|
||||
//! Destroy spinlock
|
||||
~PISpinlock() {}
|
||||
|
||||
|
||||
//! \brief Lock spinlock
|
||||
//! \details If spinlock is unlocked it set to locked state and returns immediate.
|
||||
//! If spinlock is already locked function blocks until spinlock will be unlocked
|
||||
void lock() {while (flag.test_and_set(std::memory_order_acquire));}
|
||||
|
||||
//! \brief Unlock spinlock
|
||||
//! \details In any case this function returns immediate
|
||||
void unlock() {flag.clear(std::memory_order_release);}
|
||||
|
||||
private:
|
||||
std::atomic_flag flag;
|
||||
|
||||
};
|
||||
|
||||
|
||||
//! \brief PISpinlockLocker
|
||||
//! \details
|
||||
//! When a PISpinlockLocker object is created, it attempts to lock the spinlock it is given, if "condition" true.
|
||||
//! When control leaves the scope in which the PISpinlockLocker object was created,
|
||||
//! the PISpinlockLocker is destructed and the spinlock is released, if "condition" true.
|
||||
//! If "condition" false this class do nothing.
|
||||
//! The PISpinlockLocker class is non-copyable.
|
||||
class PIP_EXPORT PISpinlockLocker
|
||||
{
|
||||
public:
|
||||
NO_COPY_CLASS(PISpinlockLocker)
|
||||
PISpinlockLocker(PISpinlock & s, bool condition = true): spinlock(s), cond(condition) {if (cond) spinlock.lock();}
|
||||
~PISpinlockLocker() {if (cond) spinlock.unlock();}
|
||||
private:
|
||||
PISpinlock & spinlock;
|
||||
bool cond;
|
||||
};
|
||||
|
||||
#endif // PISPINLOCK_H
|
||||
@@ -21,6 +21,7 @@
|
||||
#define PITHREADMODULE_H
|
||||
|
||||
#include "pimutex.h"
|
||||
#include "pispinlock.h"
|
||||
#include "pithread.h"
|
||||
#include "pitimer.h"
|
||||
#include "pipipelinethread.h"
|
||||
|
||||
@@ -15,6 +15,11 @@ PRIVATE_DEFINITION_START(PIOpenCL::Context)
|
||||
PRIVATE_DEFINITION_END(PIOpenCL::Context)
|
||||
|
||||
|
||||
PRIVATE_DEFINITION_START(PIOpenCL::Buffer)
|
||||
cl_mem buffer;
|
||||
PRIVATE_DEFINITION_END(PIOpenCL::Buffer)
|
||||
|
||||
|
||||
PRIVATE_DEFINITION_START(PIOpenCL::Program)
|
||||
cl_program program;
|
||||
PRIVATE_DEFINITION_END(PIOpenCL::Program)
|
||||
@@ -141,6 +146,7 @@ PIOpenCL::Context::Context() {
|
||||
PIOpenCL::Context::~Context() {
|
||||
piCout << "destroy context" << this;
|
||||
deletePrograms();
|
||||
deleteBuffers();
|
||||
if (PRIVATE->queue)
|
||||
clReleaseCommandQueue(PRIVATE->queue);
|
||||
if (PRIVATE->context)
|
||||
@@ -151,6 +157,7 @@ PIOpenCL::Context::~Context() {
|
||||
|
||||
void PIOpenCL::Context::zero() {
|
||||
programs_.clear();
|
||||
buffers_.clear();
|
||||
PRIVATE->context = 0;
|
||||
PRIVATE->queue = 0;
|
||||
PRIVATE->devices.clear();
|
||||
@@ -158,7 +165,7 @@ void PIOpenCL::Context::zero() {
|
||||
|
||||
|
||||
void PIOpenCL::Context::deletePrograms() {
|
||||
piCout << "context: delete" << programs_.size() << "progs";
|
||||
piCout << "context: delete" << programs_.size() << "programs";
|
||||
PIVector<Program * > ptdl = programs_;
|
||||
programs_.clear();
|
||||
piForeach (Program * p, ptdl) {
|
||||
@@ -167,6 +174,16 @@ void PIOpenCL::Context::deletePrograms() {
|
||||
}
|
||||
|
||||
|
||||
void PIOpenCL::Context::deleteBuffers() {
|
||||
piCout << "context: delete" << buffers_.size() << "buffers";
|
||||
PIVector<Buffer * > btdl = buffers_;
|
||||
buffers_.clear();
|
||||
piForeach (Buffer * b, btdl) {
|
||||
if (b) delete b;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PIOpenCL::Context * PIOpenCL::Context::create(const PIOpenCL::DeviceList & dl) {
|
||||
if (dl.isEmpty()) return 0;
|
||||
Context * rc = 0;
|
||||
@@ -195,6 +212,17 @@ PIOpenCL::Context * PIOpenCL::Context::create(const PIOpenCL::DeviceList & dl) {
|
||||
}
|
||||
|
||||
|
||||
PIOpenCL::Context * PIOpenCL::Context::create(const PIString & part_name) {
|
||||
PIString pn = part_name.toLowerCase();
|
||||
PIVector<Device> dl = PIOpenCL::devices();
|
||||
piForeachC (Device & d, dl) {
|
||||
if (d.displayText().toLowerCase().contains(pn))
|
||||
return create(d);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
PIOpenCL::Program * PIOpenCL::Context::createProgram(const PIString & source, PIString * error) {
|
||||
if (error) error->clear();
|
||||
if (source.isEmpty()) {
|
||||
@@ -264,6 +292,105 @@ PIOpenCL::Program * PIOpenCL::Context::createProgram(const PIString & source, PI
|
||||
}
|
||||
|
||||
|
||||
PIOpenCL::Buffer * PIOpenCL::Context::createBuffer(PIOpenCL::Direction dir, void * container, int type, PIByteArray def, uint elements) {
|
||||
Buffer * ret = new Buffer();
|
||||
ret->context_ = this;
|
||||
ret->dir = dir;
|
||||
ret->type = (Buffer::Container)type;
|
||||
ret->container = container;
|
||||
ret->def = def;
|
||||
ret->elements = elements;
|
||||
if (!ret->init()) {
|
||||
delete ret;
|
||||
return 0;
|
||||
}
|
||||
buffers_ << ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
PIOpenCL::Buffer::Buffer() {
|
||||
zero();
|
||||
}
|
||||
|
||||
|
||||
PIOpenCL::Buffer::~Buffer() {
|
||||
if (context_)
|
||||
context_->buffers_.removeAll(this);
|
||||
if (PRIVATE->buffer)
|
||||
clReleaseMemObject(PRIVATE->buffer);
|
||||
zero();
|
||||
}
|
||||
|
||||
|
||||
void PIOpenCL::Buffer::zero() {
|
||||
type = cNone;
|
||||
container = 0;
|
||||
elements = 0;
|
||||
PRIVATE->buffer = 0;
|
||||
}
|
||||
|
||||
|
||||
bool PIOpenCL::Buffer::init() {
|
||||
cl_int ret = 0;
|
||||
cl_mem_flags f = container ? CL_MEM_COPY_HOST_PTR : 0;
|
||||
switch (dir) {
|
||||
case Input : f |= CL_MEM_READ_ONLY ; break;
|
||||
case Output : f |= CL_MEM_WRITE_ONLY; break;
|
||||
case InputOutput: f |= CL_MEM_READ_WRITE; break;
|
||||
default: break;
|
||||
}
|
||||
PRIVATE->buffer = clCreateBuffer(context_->PRIVATEWB->context, f, elements * def.size(), container ? containerData() : 0, &ret);
|
||||
if (ret != 0) {
|
||||
piCout << "[PIOpenCL::Buffer]" << "clCreateBuffer error" << ret;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void * PIOpenCL::Buffer::containerData() {
|
||||
if (type == cNone || !container) return 0;
|
||||
switch (type) {
|
||||
case cVector : return ((PIVector <uchar>*)container)->data();
|
||||
case cDeque : return ((PIDeque <uchar>*)container)->data();
|
||||
case cVector2D: return ((PIVector2D<uchar>*)container)->data();
|
||||
default: break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void PIOpenCL::Buffer::clear() {
|
||||
if (!PRIVATE->buffer) return;
|
||||
if (def.isEmpty() || elements == 0) return;
|
||||
cl_int ret = clEnqueueFillBuffer(context_->PRIVATEWB->queue, PRIVATE->buffer, def.data(), def.size_s(), 0, elements * def.size(), 0, 0, 0);
|
||||
if (ret != 0) {
|
||||
piCout << "[PIOpenCL::Buffer]" << "clEnqueueFillBuffer error" << ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PIOpenCL::Buffer::copyToContainer() {
|
||||
if (!PRIVATE->buffer || !container) return;
|
||||
cl_int ret = clEnqueueReadBuffer(context_->PRIVATEWB->queue, PRIVATE->buffer, CL_TRUE, 0, elements * def.size(), containerData(), 0, 0, 0);
|
||||
if (ret != 0) {
|
||||
piCout << "[PIOpenCL::Buffer]" << "clEnqueueReadBuffer error" << ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PIOpenCL::Buffer::copyFromContainer() {
|
||||
if (!PRIVATE->buffer || !container) return;
|
||||
cl_int ret = clEnqueueWriteBuffer(context_->PRIVATEWB->queue, PRIVATE->buffer, CL_TRUE, 0, elements * def.size(), containerData(), 0, 0, 0);
|
||||
if (ret != 0) {
|
||||
piCout << "[PIOpenCL::Buffer]" << "clEnqueueWriteBuffer error" << ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
PIOpenCL::Program::Program() {
|
||||
@@ -310,6 +437,25 @@ bool PIOpenCL::Program::initKernels(PIVector<void * > kerns) {
|
||||
|
||||
|
||||
|
||||
bool PIOpenCL::Kernel::execute() {
|
||||
if (dims.isEmpty()) {
|
||||
piCout << "[PIOpenCL::Kernel]" << "Error: empty range";
|
||||
return false;
|
||||
}
|
||||
cl_int ret = clEnqueueNDRangeKernel(context_->PRIVATEWB->queue, PRIVATE->kernel, dims.size(), 0, dims.data(), 0, 0, 0, 0);
|
||||
if (ret != 0) {
|
||||
piCout << "[PIOpenCL::Kernel]" << "clEnqueueNDRangeKernel error" << ret;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void PIOpenCL::Kernel::setExecuteRanges(const PIVector<int> & ranges) {
|
||||
dims = ranges.toType<size_t>();
|
||||
}
|
||||
|
||||
|
||||
PIOpenCL::Kernel::Kernel() {
|
||||
zero();
|
||||
//piCout << "new Kernel" << this;
|
||||
@@ -349,17 +495,56 @@ bool PIOpenCL::Kernel::init() {
|
||||
ka.init(PRIVATE->kernel, i);
|
||||
args_ << ka;
|
||||
}
|
||||
piCout << "kname" << kname << na;
|
||||
//piCout << "kname" << kname << na;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool PIOpenCL::Kernel::setArgValueV(int index, const PIVariant & value) {
|
||||
template <typename T>
|
||||
void setArgV(cl_kernel k, int index, T v) {
|
||||
//piCout << "setArgV" << k << index <<sizeof(v)<< v;
|
||||
clSetKernelArg(k, index, sizeof(v), &v);
|
||||
}
|
||||
|
||||
bool PIOpenCL::Kernel::setArgValueS(int index, const PIVariant & value) {
|
||||
if (index < 0 || index >= args_.size_s()) {
|
||||
piCout << "[PIOpenCL::Kernel]" << "setArgValue invalid index" << index;
|
||||
return false;
|
||||
}
|
||||
KernelArg & ka(args_[index]);
|
||||
if (ka.dims > 0) {
|
||||
piCout << "[PIOpenCL::Kernel]" << "setArgValue set scalar to \"" << ka.type_name << ka.arg_name << "\"";
|
||||
return false;
|
||||
}
|
||||
switch (ka.arg_type) {
|
||||
case Char : setArgV(PRIVATE->kernel, index, (cl_char)(value.toInt())); break;
|
||||
case UChar : setArgV(PRIVATE->kernel, index, (cl_uchar)(value.toInt())); break;
|
||||
case Short : setArgV(PRIVATE->kernel, index, (cl_short)(value.toInt())); break;
|
||||
case UShort: setArgV(PRIVATE->kernel, index, (cl_ushort)(value.toInt())); break;
|
||||
case Int : setArgV(PRIVATE->kernel, index, (cl_int)(value.toInt())); break;
|
||||
case UInt : setArgV(PRIVATE->kernel, index, (cl_uint)(value.toInt())); break;
|
||||
case Long : setArgV(PRIVATE->kernel, index, (cl_long)(value.toLLong())); break;
|
||||
case ULong : setArgV(PRIVATE->kernel, index, (cl_ulong)(value.toLLong())); break;
|
||||
case Float : setArgV(PRIVATE->kernel, index, (cl_float)(value.toFloat())); break;
|
||||
case Double: setArgV(PRIVATE->kernel, index, (cl_double)(value.toDouble())); break;
|
||||
default: break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool PIOpenCL::Kernel::bindArgValue(int index, Buffer * buffer) {
|
||||
if (!buffer) return false;
|
||||
if (index < 0 || index >= args_.size_s()) {
|
||||
piCout << "[PIOpenCL::Kernel]" << "bindArgValue invalid index" << index;
|
||||
return false;
|
||||
}
|
||||
KernelArg & ka(args_[index]);
|
||||
if (ka.dims <= 0) {
|
||||
piCout << "[PIOpenCL::Kernel]" << "bindArgValue set buffer to \"" << ka.type_name << ka.arg_name << "\"";
|
||||
return false;
|
||||
}
|
||||
clSetKernelArg(PRIVATE->kernel, index, sizeof(buffer->PRIVATEWB->buffer), &(buffer->PRIVATEWB->buffer));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -441,14 +626,26 @@ void PIOpenCL::KernelArg::init(void * _k, uint index) {
|
||||
case CL_KERNEL_ARG_TYPE_VOLATILE: type_qualifier = TypeVolatile; break;
|
||||
case CL_KERNEL_ARG_TYPE_NONE : type_qualifier = TypeNone; break;
|
||||
}
|
||||
base_type_name = type_name;
|
||||
is_pointer = false;
|
||||
if (type_name.endsWith("*")) {
|
||||
is_pointer = true;
|
||||
base_type_name.cutRight(1);
|
||||
base_type_name = type_name;
|
||||
base_type_name.removeAll("__global");
|
||||
dims = piMaxi(0, base_type_name.entries('*') + base_type_name.entries('['));
|
||||
base_type_name.removeAll('*');
|
||||
while (base_type_name.contains('[')) {
|
||||
int i = base_type_name.find('[');
|
||||
base_type_name.remove(i, base_type_name.find(']') - i + 1);
|
||||
}
|
||||
dims = piMaxi(1, base_type_name.right(1).toInt());
|
||||
if (dims > 1) base_type_name.cutRight(1);
|
||||
if (base_type_name == "char" ) arg_type = Char ;
|
||||
if (base_type_name == "uchar" ) arg_type = UChar ;
|
||||
if (base_type_name == "short") arg_type = Short;
|
||||
if (base_type_name == "ushort") arg_type = UShort;
|
||||
if (base_type_name == "int" ) arg_type = Int ;
|
||||
if (base_type_name == "uint" ) arg_type = UInt ;
|
||||
if (base_type_name == "long" ) arg_type = Long ;
|
||||
if (base_type_name == "ulong" ) arg_type = ULong ;
|
||||
if (base_type_name == "float" ) arg_type = Float ;
|
||||
if (base_type_name == "double") arg_type = Double;
|
||||
//piCout << type_name << base_type_name;
|
||||
}
|
||||
|
||||
|
||||
|
||||
106
main.cpp
106
main.cpp
@@ -1,79 +1,53 @@
|
||||
#include "pip.h"
|
||||
#include "pivariantsimple.h"
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct MM {
|
||||
int x;
|
||||
int x2;
|
||||
double y;
|
||||
char c[16];
|
||||
int e2;
|
||||
int e;
|
||||
//PIPointd h;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
#define REGISTER_CNT (__COUNTER__)
|
||||
#define REGISTER_V_STREAM_INTERNAL(T, C) \
|
||||
class _VariantRegistrator_##C##__ { \
|
||||
public: \
|
||||
_VariantRegistrator_##C##__() { \
|
||||
__VariantFunctionsBase__ * f = __VariantFunctions__<int>().instance(); \
|
||||
__VariantFunctionsBase__::registered()[f->hash()] = f; \
|
||||
} \
|
||||
}; \
|
||||
_VariantRegistrator_##C##__ __registrator_##C##__;
|
||||
int Acnt = 0;
|
||||
|
||||
|
||||
#define REGISTER_V_STREAM_INTERNAL_W(T, C) REGISTER_V_STREAM_INTERNAL(T, C)
|
||||
#define REGISTER_V_STREAM(T) REGISTER_V_STREAM_INTERNAL_W(T, __COUNTER__)
|
||||
|
||||
|
||||
|
||||
|
||||
class Send: public PIObject {
|
||||
PIOBJECT(Send)
|
||||
class A {
|
||||
public:
|
||||
Send() {piCout << "Send";}
|
||||
~Send() {piCout << "~Send";}
|
||||
EVENT1(ev, PIObject * , o);
|
||||
A() {moved = false; i = "constructor"; piCout << "A()"; ++Acnt;}
|
||||
A(const PIString & s): i(s) {moved = false; piCout << "A(String)"; ++Acnt;}
|
||||
A(const A & a): i(a.i) {moved = false; piCout << "copy A(&)"; ++Acnt;}
|
||||
A(A && a): i(std::move(a.i)) {moved = false; a.moved = true; piCout << "copy A(&&)"; ++Acnt;}
|
||||
~A() {piCout << "~A()" << moved; --Acnt;}
|
||||
void swap(A & a) {piCout << "swap A()"; piSwap(i, a.i);}
|
||||
A & operator =(const A & a) {i = a.i; piCout << "= A&"; return *this;}
|
||||
A & operator =(A && a) {piSwap(i, a.i); a.moved = true; piCout << "= A&&)"; return *this;}
|
||||
bool operator ==(const A & a) {return true;}
|
||||
PIString i;
|
||||
bool moved;
|
||||
MM m;
|
||||
static void F(int) {}
|
||||
};
|
||||
|
||||
inline PIByteArray & operator <<(PIByteArray & ba, const A & v) {ba << v.i << v.m; return ba;}
|
||||
inline PIByteArray & operator >>(PIByteArray & ba, A & v) {ba >> v.i >> v.m; return ba;}
|
||||
|
||||
class Recv: public PIObject {
|
||||
PIOBJECT(Recv)
|
||||
public:
|
||||
Recv() {piCout << "Recv";}
|
||||
~Recv() {piCout << "~Recv";}
|
||||
EVENT_HANDLER1(void, eh, PIObject * , o) {
|
||||
piCout << "eh ..." << o;
|
||||
o->deleteLater();
|
||||
piMSleep(1000);
|
||||
piCout << "eh ok";
|
||||
}
|
||||
};
|
||||
inline PIByteArray & operator <<(PIByteArray & ba, const MM & v) {piCout << "<<"; ba << v.x << v.y << v.c; return ba;}
|
||||
inline PIByteArray & operator >>(PIByteArray & ba, MM & v) {piCout << ">>"; ba >> v.x >> v.y >> v.c; return ba;}
|
||||
|
||||
|
||||
Send * s = new Send();
|
||||
Recv * r = new Recv();
|
||||
|
||||
#include "piconditionvar.h"
|
||||
int main() {
|
||||
|
||||
CONNECTU(s, ev, r, eh);
|
||||
s->ev(r);
|
||||
r->deleteLater();
|
||||
s->deleteLater();
|
||||
piMSleep(1500);
|
||||
//s->deleteLater();
|
||||
//delete o;
|
||||
//eth.dump();
|
||||
//versionCompare("","");
|
||||
//PICloudServer s("127.0.0.1:10101");
|
||||
//s.startThreadedRead();
|
||||
piMSleep(10);
|
||||
|
||||
/*PIMutex m;
|
||||
PIConditionVariable var;
|
||||
|
||||
PIThread::runOnce([&](){
|
||||
piCout << "wait ...";
|
||||
m.lock();
|
||||
var.wait(m);
|
||||
m.unlock();
|
||||
piCout << "wait done";
|
||||
});
|
||||
|
||||
piMSleep(100);
|
||||
var.notifyAll();*/
|
||||
|
||||
PIMathVectorT3d v3({1,2,3});
|
||||
PIMathVectord v(v3);
|
||||
PIMathVectord v2({3,2,1});
|
||||
piCout << v;
|
||||
piCout << v2;
|
||||
PIMathMatrixT22d m = PIMathMatrixT22d::identity();
|
||||
piCout << m;
|
||||
m.rotate(toRad(90.));
|
||||
piCout << m;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,20 +1,26 @@
|
||||
include(DownloadGTest)
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/suppr.txt ${CMAKE_CURRENT_BINARY_DIR} COPYONLY)
|
||||
|
||||
macro(pip_test NAME LIBS)
|
||||
file(GLOB _CPPS "${NAME}/*.cpp")
|
||||
file(GLOB _HDRS "${NAME}/*.h")
|
||||
set(_target pip_${NAME}_test)
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PIP_ROOT_BINARY_DIR}")
|
||||
add_executable(${_target} ${_CPPS} ${_HDRS})
|
||||
if (NOT WIN32 AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
target_compile_options(${_target} PRIVATE -fsanitize=address,undefined)
|
||||
target_link_options(${_target} PRIVATE -fsanitize=address,undefined)
|
||||
target_link_libraries(${_target} asan)
|
||||
endif()
|
||||
target_link_libraries(${_target} pip ${LIBS} gtest_main gmock_main)
|
||||
add_test(NAME ${_target} COMMAND tests)
|
||||
add_custom_target(${_target}_perform ALL COMMAND ${_target})
|
||||
add_custom_target(${_target}_perform ALL
|
||||
COMMAND ${CMAKE_COMMAND} -E env "LSAN_OPTIONS=suppressions=suppr.txt" $<TARGET_FILE:${_target}>)
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY)
|
||||
list(APPEND PIP_TESTS_LIST "${NAME}")
|
||||
set(PIP_TESTS_LIST ${PIP_TESTS_LIST} PARENT_SCOPE)
|
||||
endmacro()
|
||||
|
||||
# Concurrent tests
|
||||
pip_test(concurrent "")
|
||||
pip_test(math "")
|
||||
pip_test(core "")
|
||||
|
||||
@@ -14,9 +14,7 @@ public:
|
||||
|
||||
void wait(PIMutex& lk, const std::function<bool()>& condition) override {
|
||||
isWaitCalled = true;
|
||||
lk.lock();
|
||||
isTrueCondition = condition();
|
||||
lk.unlock();
|
||||
}
|
||||
|
||||
bool waitFor(PIMutex& lk, int timeoutMs) override {
|
||||
@@ -27,10 +25,8 @@ public:
|
||||
|
||||
bool waitFor(PIMutex& lk, int timeoutMs, const std::function<bool()>& condition) override {
|
||||
isWaitForCalled = true;
|
||||
lk.lock();
|
||||
isTrueCondition = condition();
|
||||
timeout = timeoutMs;
|
||||
lk.unlock();
|
||||
return isTrueCondition;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* Minimum wait thread start, switch context or another interthread communication action time. Increase it if tests
|
||||
* write "Start thread timeout reach!" message. You can reduce it if you want increase test performance.
|
||||
*/
|
||||
const int WAIT_THREAD_TIME_MS = 40;
|
||||
const int WAIT_THREAD_TIME_MS = 400;
|
||||
|
||||
const int THREAD_COUNT = 5;
|
||||
|
||||
|
||||
@@ -2,554 +2,542 @@
|
||||
#include "pimathmatrix.h"
|
||||
|
||||
bool cmpSquareMatrixWithValue(PIMathMatrix<double> matrix, double val, int num) {
|
||||
bool b = true;
|
||||
for(int i = 0; i < num; i++) {
|
||||
for(int j = 0; j < num; j++) {
|
||||
if(matrix.element(i, j) != val) {
|
||||
b = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return b;
|
||||
bool b = true;
|
||||
for(int i = 0; i < num; i++) {
|
||||
for(int j = 0; j < num; j++) {
|
||||
if(matrix.element(i, j) != val) {
|
||||
b = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
TEST(PIMathMatrix_Test, identity) {
|
||||
auto matrix = PIMathMatrix<double>::identity(3, 3);
|
||||
for(int i = 0; i < 3; i++) {
|
||||
for(int j = 0; j < 3; j++) {
|
||||
if(i != j) {
|
||||
if(matrix[i][j] != 0.0){
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(matrix[i][i] != 1.0){
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ASSERT_TRUE(true);
|
||||
auto matrix = PIMathMatrix<double>::identity(3, 3);
|
||||
for(int i = 0; i < 3; i++) {
|
||||
for(int j = 0; j < 3; j++) {
|
||||
if(i != j) {
|
||||
if(matrix[i][j] != 0.0){
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(matrix[i][i] != 1.0){
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ASSERT_TRUE(true);
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, element) {
|
||||
auto matrix = PIMathMatrix<double>::identity(3, 3);
|
||||
for(int i = 0; i < 3; i++){
|
||||
for(int j = 0; j < 3; j++){
|
||||
if(i != j){
|
||||
if(matrix[i][j] != 0.0){
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(matrix.element(i,i) != 1.0) {
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ASSERT_TRUE(true);
|
||||
auto matrix = PIMathMatrix<double>::identity(3, 3);
|
||||
for(int i = 0; i < 3; i++){
|
||||
for(int j = 0; j < 3; j++){
|
||||
if(i != j){
|
||||
if(matrix[i][j] != 0.0){
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(matrix.element(i,i) != 1.0) {
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ASSERT_TRUE(true);
|
||||
}
|
||||
|
||||
TEST(PIMathMatrix_Test, matrixRow) {
|
||||
PIMathVector<double> vector;
|
||||
vector.resize(3, 3.0);
|
||||
auto matrix = PIMathMatrix<double>::matrixRow(vector);
|
||||
for(uint i = 0; i < vector.size(); i++) {
|
||||
if(matrix[0][i] != 3.0) {
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
ASSERT_TRUE(true);
|
||||
PIMathVector<double> vector;
|
||||
vector.resize(3, 3.0);
|
||||
auto matrix = PIMathMatrix<double>::matrixRow(vector);
|
||||
for(uint i = 0; i < vector.size(); i++) {
|
||||
if(matrix[0][i] != 3.0) {
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
ASSERT_TRUE(true);
|
||||
}
|
||||
|
||||
TEST(PIMathMatrix_Test, matrixCol) {
|
||||
PIMathVector<double> vector;
|
||||
vector.resize(3, 3.0);
|
||||
auto matrix = PIMathMatrix<double>::matrixCol(vector);
|
||||
for(uint i = 0; i < vector.size(); i++) {
|
||||
if(matrix[i][0] != 3.0) {
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
ASSERT_TRUE(true);
|
||||
PIMathVector<double> vector;
|
||||
vector.resize(3, 3.0);
|
||||
auto matrix = PIMathMatrix<double>::matrixCol(vector);
|
||||
for(uint i = 0; i < vector.size(); i++) {
|
||||
if(matrix[i][0] != 3.0) {
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
ASSERT_TRUE(true);
|
||||
}
|
||||
|
||||
TEST(PIMathMatrix_Test, setCol) {
|
||||
PIMathVector<double> vector;
|
||||
vector.resize(3, 3.0);
|
||||
auto matrix = PIMathMatrix<double>::matrixCol(vector);
|
||||
vector.fill(10.0);
|
||||
matrix.setCol(0, vector);
|
||||
for(uint i = 0; i < vector.size(); i++) {
|
||||
if(matrix[i][0] != 10.0) {
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
ASSERT_TRUE(true);
|
||||
PIMathVector<double> vector;
|
||||
vector.resize(3, 3.0);
|
||||
auto matrix = PIMathMatrix<double>::matrixCol(vector);
|
||||
vector.fill(10.0);
|
||||
matrix.setCol(0, vector);
|
||||
for(uint i = 0; i < vector.size(); i++) {
|
||||
if(matrix[i][0] != 10.0) {
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
ASSERT_TRUE(true);
|
||||
}
|
||||
|
||||
TEST(PIMathMatrix_Test, setRow) {
|
||||
PIMathVector<double> vector;
|
||||
vector.resize(3, 3.0);
|
||||
auto matrix = PIMathMatrix<double>::matrixRow(vector);
|
||||
vector.fill(10.0);
|
||||
matrix.setRow(0, vector);
|
||||
for(uint i = 0; i < vector.size(); i++) {
|
||||
if(matrix[0][i] != 10.0) {
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
ASSERT_TRUE(true);
|
||||
PIMathVector<double> vector;
|
||||
vector.resize(3, 3.0);
|
||||
auto matrix = PIMathMatrix<double>::matrixRow(vector);
|
||||
vector.fill(10.0);
|
||||
matrix.setRow(0, vector);
|
||||
for(uint i = 0; i < vector.size(); i++) {
|
||||
if(matrix[0][i] != 10.0) {
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
ASSERT_TRUE(true);
|
||||
}
|
||||
|
||||
TEST(PIMathMatrix_Test, swapCols) {
|
||||
PIMathMatrix<double> origMatr;
|
||||
PIMathMatrix<double> matrix1;
|
||||
PIMathVector<double> vector;
|
||||
uint i1 = 0; uint i2 = 1;
|
||||
double a1[3], a2[3], a3[3];
|
||||
double b1[3], b2[3], b3[3];
|
||||
vector.resize(3, 3.0);
|
||||
vector.at(0) = 3.0;
|
||||
vector.at(1) = 6.0;
|
||||
vector.at(2) = 8.0;
|
||||
matrix1 = origMatr.identity(3, 3);
|
||||
matrix1.setCol(0, vector);
|
||||
vector.at(0) = 2.0;
|
||||
vector.at(1) = 1.0;
|
||||
vector.at(2) = 4.0;
|
||||
matrix1.setCol(1, vector);
|
||||
vector.at(0) = 6.0;
|
||||
vector.at(1) = 2.0;
|
||||
vector.at(2) = 5.0;
|
||||
matrix1.setCol(2, vector);
|
||||
for(int i = 0; i < 3; i++) {
|
||||
a1[i] = matrix1.element(i, 0);
|
||||
a2[i] = matrix1.element(i, 1);
|
||||
a3[i] = matrix1.element(i, 2);
|
||||
}
|
||||
matrix1.swapCols(i1, i2);
|
||||
for(int i = 0; i < 3; i++) {
|
||||
b1[i] = matrix1.element(i, 0);
|
||||
b2[i] = matrix1.element(i, 1);
|
||||
b3[i] = matrix1.element(i, 2);
|
||||
}
|
||||
ASSERT_TRUE((memcmp(a1, b2, sizeof(b1)) == 0) && (memcmp(a2, b1, sizeof(b1)) == 0) && (memcmp(a3, b3, sizeof(b1)) == 0));
|
||||
PIMathMatrix<double> origMatr;
|
||||
PIMathMatrix<double> matrix1;
|
||||
PIMathVector<double> vector;
|
||||
uint i1 = 0; uint i2 = 1;
|
||||
double a1[3], a2[3], a3[3];
|
||||
double b1[3], b2[3], b3[3];
|
||||
vector.resize(3, 3.0);
|
||||
vector[0] = 3.0;
|
||||
vector[1] = 6.0;
|
||||
vector[2] = 8.0;
|
||||
matrix1 = origMatr.identity(3, 3);
|
||||
matrix1.setCol(0, vector);
|
||||
vector[0] = 2.0;
|
||||
vector[1] = 1.0;
|
||||
vector[2] = 4.0;
|
||||
matrix1.setCol(1, vector);
|
||||
vector[0] = 6.0;
|
||||
vector[1] = 2.0;
|
||||
vector[2] = 5.0;
|
||||
matrix1.setCol(2, vector);
|
||||
for(int i = 0; i < 3; i++) {
|
||||
a1[i] = matrix1.element(i, 0);
|
||||
a2[i] = matrix1.element(i, 1);
|
||||
a3[i] = matrix1.element(i, 2);
|
||||
}
|
||||
matrix1.swapCols(i1, i2);
|
||||
for(int i = 0; i < 3; i++) {
|
||||
b1[i] = matrix1.element(i, 0);
|
||||
b2[i] = matrix1.element(i, 1);
|
||||
b3[i] = matrix1.element(i, 2);
|
||||
}
|
||||
ASSERT_TRUE((memcmp(a1, b2, sizeof(b1)) == 0) && (memcmp(a2, b1, sizeof(b1)) == 0) && (memcmp(a3, b3, sizeof(b1)) == 0));
|
||||
}
|
||||
|
||||
TEST(PIMathMatrix_Test, swapRows) {
|
||||
PIMathMatrix<double> origMatr;
|
||||
PIMathMatrix<double> matrix1;
|
||||
PIMathVector<double> vector;
|
||||
uint i1 = 0; uint i2 = 1;
|
||||
double a1[3], a2[3], a3[3];
|
||||
double b1[3], b2[3], b3[3];
|
||||
vector.resize(3, 3.0);
|
||||
vector.at(0) = 3.0;
|
||||
vector.at(1) = 6.0;
|
||||
vector.at(2) = 8.0;
|
||||
matrix1 = origMatr.identity(3, 3);
|
||||
matrix1.setCol(0, vector);
|
||||
vector.at(0) = 2.0;
|
||||
vector.at(1) = 1.0;
|
||||
vector.at(2) = 4.0;
|
||||
matrix1.setCol(1, vector);
|
||||
vector.at(0) = 6.0;
|
||||
vector.at(1) = 2.0;
|
||||
vector.at(2) = 5.0;
|
||||
matrix1.setCol(2, vector);
|
||||
for(int i = 0; i < 3; i++) {
|
||||
a1[i] = matrix1.element(0, i);
|
||||
a2[i] = matrix1.element(1, i);
|
||||
a3[i] = matrix1.element(2, i);
|
||||
}
|
||||
matrix1.swapRows(i1, i2);
|
||||
for(int i = 0; i < 3; i++) {
|
||||
b1[i] = matrix1.element(0, i);
|
||||
b2[i] = matrix1.element(1, i);
|
||||
b3[i] = matrix1.element(2, i);
|
||||
}
|
||||
ASSERT_TRUE((memcmp(a1, b2, sizeof(b1)) == 0) && (memcmp(a2, b1, sizeof(b1)) == 0) && (memcmp(a3, b3, sizeof(b1)) == 0));
|
||||
PIMathMatrix<double> origMatr;
|
||||
PIMathMatrix<double> matrix1;
|
||||
PIMathVector<double> vector;
|
||||
uint i1 = 0; uint i2 = 1;
|
||||
double a1[3], a2[3], a3[3];
|
||||
double b1[3], b2[3], b3[3];
|
||||
vector.resize(3, 3.0);
|
||||
vector[0] = 3.0;
|
||||
vector[1] = 6.0;
|
||||
vector[2] = 8.0;
|
||||
matrix1 = origMatr.identity(3, 3);
|
||||
matrix1.setCol(0, vector);
|
||||
vector[0] = 2.0;
|
||||
vector[1] = 1.0;
|
||||
vector[2] = 4.0;
|
||||
matrix1.setCol(1, vector);
|
||||
vector[0] = 6.0;
|
||||
vector[1] = 2.0;
|
||||
vector[2] = 5.0;
|
||||
matrix1.setCol(2, vector);
|
||||
for(int i = 0; i < 3; i++) {
|
||||
a1[i] = matrix1.element(0, i);
|
||||
a2[i] = matrix1.element(1, i);
|
||||
a3[i] = matrix1.element(2, i);
|
||||
}
|
||||
matrix1.swapRows(i1, i2);
|
||||
for(int i = 0; i < 3; i++) {
|
||||
b1[i] = matrix1.element(0, i);
|
||||
b2[i] = matrix1.element(1, i);
|
||||
b3[i] = matrix1.element(2, i);
|
||||
}
|
||||
ASSERT_TRUE((memcmp(a1, b2, sizeof(b1)) == 0) && (memcmp(a2, b1, sizeof(b1)) == 0) && (memcmp(a3, b3, sizeof(b1)) == 0));
|
||||
}
|
||||
TEST(PIMathMatrix_Test, fill) {
|
||||
PIMathMatrix<double> matrix(3, 3, 5.0);
|
||||
matrix.fill(7.0);
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(matrix, 7.0, 3));
|
||||
PIMathMatrix<double> matrix(3, 3, 5.0);
|
||||
matrix.fill(7.0);
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(matrix, 7.0, 3));
|
||||
}
|
||||
|
||||
TEST(PIMathMatrix_Test, isSquareTrue) {
|
||||
PIMathMatrix<double> matrix(3, 3, 1.0);
|
||||
ASSERT_TRUE(matrix.isSquare());
|
||||
PIMathMatrix<double> matrix(3, 3, 1.0);
|
||||
ASSERT_TRUE(matrix.isSquare());
|
||||
}
|
||||
|
||||
TEST(PIMathMatrix_Test, isSquareFalse) {
|
||||
PIMathMatrix<double> matrix(2, 4, 1.0);
|
||||
ASSERT_FALSE(matrix.isSquare());
|
||||
PIMathMatrix<double> matrix(2, 4, 1.0);
|
||||
ASSERT_FALSE(matrix.isSquare());
|
||||
}
|
||||
|
||||
TEST(PIMathMatrix_Test, isIdentityTrue) {
|
||||
auto matrix = PIMathMatrix<double>::identity(3, 3);
|
||||
ASSERT_TRUE(matrix.isIdentity());
|
||||
auto matrix = PIMathMatrix<double>::identity(3, 3);
|
||||
ASSERT_TRUE(matrix.isIdentity());
|
||||
}
|
||||
|
||||
TEST(PIMathMatrix_Test, isIdentityFalse) {
|
||||
PIMathMatrix<double> matrix(3, 3, 5.0);
|
||||
ASSERT_FALSE(matrix.isIdentity());
|
||||
PIMathMatrix<double> matrix(3, 3, 5.0);
|
||||
ASSERT_FALSE(matrix.isIdentity());
|
||||
}
|
||||
|
||||
|
||||
TEST(PIMathMatrix_Test, isNullTrue) {
|
||||
PIMathMatrix<double> matrix(3, 3, 0.0);
|
||||
ASSERT_TRUE(matrix.isNull());
|
||||
PIMathMatrix<double> matrix(3, 3, 0.0);
|
||||
ASSERT_TRUE(matrix.isNull());
|
||||
}
|
||||
|
||||
TEST(PIMathMatrix_Test, isNullFalse) {
|
||||
PIMathMatrix<double> matrix(3, 3, 5.0);
|
||||
ASSERT_FALSE(matrix.isNull());
|
||||
PIMathMatrix<double> matrix(3, 3, 5.0);
|
||||
ASSERT_FALSE(matrix.isNull());
|
||||
}
|
||||
|
||||
TEST(PIMathMatrix_Test, isValidTrue) {
|
||||
PIMathMatrix<double> matrix(3, 3, 1.62);
|
||||
ASSERT_TRUE(matrix.isValid());
|
||||
PIMathMatrix<double> matrix(3, 3, 1.62);
|
||||
ASSERT_TRUE(matrix.isValid());
|
||||
}
|
||||
|
||||
TEST(PIMathMatrix_Test, isValidFalse) {
|
||||
PIMathMatrix<double> matrix;
|
||||
ASSERT_FALSE(matrix.isValid());
|
||||
PIMathMatrix<double> matrix;
|
||||
ASSERT_FALSE(matrix.isValid());
|
||||
}
|
||||
|
||||
TEST(PIMathMatrix_Test, operator_Assignment) {
|
||||
PIMathMatrix<double> matrix1(3, 3, 5.72);
|
||||
PIMathMatrix<double> matrix2(3, 3, 7.12);
|
||||
matrix1 = matrix2;
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1, 7.12, 3));
|
||||
PIMathMatrix<double> matrix1(3, 3, 5.72);
|
||||
PIMathMatrix<double> matrix2(3, 3, 7.12);
|
||||
matrix1 = matrix2;
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1, 7.12, 3));
|
||||
}
|
||||
|
||||
TEST(PIMathMatrix_Test, operator_EqualTrue) {
|
||||
PIMathMatrix<double> matrix1(2, 2, 2.0);
|
||||
PIMathMatrix<double> matrix2(2, 2, 2.0);
|
||||
matrix1.element(0, 0) = 5.1;
|
||||
matrix1.element(0, 1) = 1.21;
|
||||
matrix1.element(1, 1) = 0.671;
|
||||
matrix1.element(1, 0) = 2.623;
|
||||
matrix2.element(0, 0) = 5.1;
|
||||
matrix2.element(0, 1) = 1.21;
|
||||
matrix2.element(1, 1) = 0.671;
|
||||
matrix2.element(1, 0) = 2.623;
|
||||
ASSERT_TRUE(matrix1 == matrix2);
|
||||
PIMathMatrix<double> matrix1(2, 2, 2.0);
|
||||
PIMathMatrix<double> matrix2(2, 2, 2.0);
|
||||
matrix1.element(0, 0) = 5.1;
|
||||
matrix1.element(0, 1) = 1.21;
|
||||
matrix1.element(1, 1) = 0.671;
|
||||
matrix1.element(1, 0) = 2.623;
|
||||
matrix2.element(0, 0) = 5.1;
|
||||
matrix2.element(0, 1) = 1.21;
|
||||
matrix2.element(1, 1) = 0.671;
|
||||
matrix2.element(1, 0) = 2.623;
|
||||
ASSERT_TRUE(matrix1 == matrix2);
|
||||
}
|
||||
|
||||
TEST(PIMathMatrix_Test, operator_EqualFalse) {
|
||||
PIMathMatrix<double> matrix1(2, 2, 2.0);
|
||||
PIMathMatrix<double> matrix2(2, 2, 2.0);
|
||||
matrix1.element(0, 0) = 5.1;
|
||||
matrix1.element(0, 1) = 1.21;
|
||||
matrix1.element(1, 1) = 0.671;
|
||||
matrix1.element(1, 0) = 2.623;
|
||||
matrix2.element(0, 0) = 5.1;
|
||||
matrix2.element(0, 1) = 1.21;
|
||||
matrix2.element(1, 1) = 665.671;
|
||||
matrix2.element(1, 0) = 2.623;
|
||||
ASSERT_FALSE(matrix1 == matrix2);
|
||||
PIMathMatrix<double> matrix1(2, 2, 2.0);
|
||||
PIMathMatrix<double> matrix2(2, 2, 2.0);
|
||||
matrix1.element(0, 0) = 5.1;
|
||||
matrix1.element(0, 1) = 1.21;
|
||||
matrix1.element(1, 1) = 0.671;
|
||||
matrix1.element(1, 0) = 2.623;
|
||||
matrix2.element(0, 0) = 5.1;
|
||||
matrix2.element(0, 1) = 1.21;
|
||||
matrix2.element(1, 1) = 665.671;
|
||||
matrix2.element(1, 0) = 2.623;
|
||||
ASSERT_FALSE(matrix1 == matrix2);
|
||||
}
|
||||
|
||||
TEST(PIMathMatrix_Test, operator_Not_EqualTrue) {
|
||||
PIMathMatrix<double> matrix1(2, 2, 2.0);
|
||||
PIMathMatrix<double> matrix2(2, 2, 2.0);
|
||||
matrix1.element(0, 0) = 5.1;
|
||||
matrix1.element(0, 1) = 1.21;
|
||||
matrix1.element(1, 1) = 0.671;
|
||||
matrix1.element(1, 0) = 2.623;
|
||||
matrix2.element(0, 0) = 5.1;
|
||||
matrix2.element(0, 1) = 1.21;
|
||||
matrix2.element(1, 1) = 665.671;
|
||||
matrix2.element(1, 0) = 2.623;
|
||||
ASSERT_TRUE(matrix1 != matrix2);
|
||||
PIMathMatrix<double> matrix1(2, 2, 2.0);
|
||||
PIMathMatrix<double> matrix2(2, 2, 2.0);
|
||||
matrix1.element(0, 0) = 5.1;
|
||||
matrix1.element(0, 1) = 1.21;
|
||||
matrix1.element(1, 1) = 0.671;
|
||||
matrix1.element(1, 0) = 2.623;
|
||||
matrix2.element(0, 0) = 5.1;
|
||||
matrix2.element(0, 1) = 1.21;
|
||||
matrix2.element(1, 1) = 665.671;
|
||||
matrix2.element(1, 0) = 2.623;
|
||||
ASSERT_TRUE(matrix1 != matrix2);
|
||||
}
|
||||
|
||||
TEST(PIMathMatrix_Test, operator_Not_EqualFalse) {
|
||||
PIMathMatrix<double> matrix1(2, 2, 2.0);
|
||||
PIMathMatrix<double> matrix2(2, 2, 2.0);
|
||||
matrix1.element(0, 0) = 5.1;
|
||||
matrix1.element(0, 1) = 1.21;
|
||||
matrix1.element(1, 1) = 0.671;
|
||||
matrix1.element(1, 0) = 2.623;
|
||||
matrix2.element(0, 0) = 5.1;
|
||||
matrix2.element(0, 1) = 1.21;
|
||||
matrix2.element(1, 1) = 0.671;
|
||||
matrix2.element(1, 0) = 2.623;
|
||||
ASSERT_FALSE(matrix1 != matrix2);
|
||||
PIMathMatrix<double> matrix1(2, 2, 2.0);
|
||||
PIMathMatrix<double> matrix2(2, 2, 2.0);
|
||||
matrix1.element(0, 0) = 5.1;
|
||||
matrix1.element(0, 1) = 1.21;
|
||||
matrix1.element(1, 1) = 0.671;
|
||||
matrix1.element(1, 0) = 2.623;
|
||||
matrix2.element(0, 0) = 5.1;
|
||||
matrix2.element(0, 1) = 1.21;
|
||||
matrix2.element(1, 1) = 0.671;
|
||||
matrix2.element(1, 0) = 2.623;
|
||||
ASSERT_FALSE(matrix1 != matrix2);
|
||||
}
|
||||
|
||||
TEST(PIMathMatrix_Test, operator_Addition_Aassignment) {
|
||||
PIMathMatrix<double> matrix1(3, 3, 6.72);
|
||||
PIMathMatrix<double> matrix2(3, 3, 1.0);
|
||||
matrix1 += matrix2;
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1, 7.72, 3));
|
||||
PIMathMatrix<double> matrix1(3, 3, 6.72);
|
||||
PIMathMatrix<double> matrix2(3, 3, 1.0);
|
||||
matrix1 += matrix2;
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1, 7.72, 3));
|
||||
}
|
||||
|
||||
TEST(PIMathMatrix_Test, operator_Subtraction_Assignment) {
|
||||
PIMathMatrix<double> matrix1(3, 3, 1.0);
|
||||
PIMathMatrix<double> matrix2(3, 3, 6.72);
|
||||
matrix1 -= matrix2;
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1, -5.72, 3));
|
||||
PIMathMatrix<double> matrix1(3, 3, 1.0);
|
||||
PIMathMatrix<double> matrix2(3, 3, 6.72);
|
||||
matrix1 -= matrix2;
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1, -5.72, 3));
|
||||
}
|
||||
|
||||
TEST(PIMathMatrix_Test, operator_Multiplication_Assignment) {
|
||||
PIMathMatrix<double> matrix1(3, 3, 6.72);
|
||||
matrix1 *= 2.0;
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1, 13.44, 3));
|
||||
PIMathMatrix<double> matrix1(3, 3, 6.72);
|
||||
matrix1 *= 2.0;
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1, 13.44, 3));
|
||||
}
|
||||
|
||||
TEST(PIMathMatrix_Test, operator_Division_Assignment) {
|
||||
PIMathMatrix<double> matrix1(3, 3, 6.72);
|
||||
matrix1 /= 2.0;
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1, 3.36, 3));
|
||||
PIMathMatrix<double> matrix1(3, 3, 6.72);
|
||||
matrix1 /= 2.0;
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1, 3.36, 3));
|
||||
}
|
||||
|
||||
TEST(PIMathMatrix_Test, operator_Addition) {
|
||||
PIMathMatrix<double> matrix1(3, 3, 6.72);
|
||||
PIMathMatrix<double> matrix2(3, 3, 8.28);
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1 + matrix2, 15.0, 3));
|
||||
PIMathMatrix<double> matrix1(3, 3, 6.72);
|
||||
PIMathMatrix<double> matrix2(3, 3, 8.28);
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1 + matrix2, 15.0, 3));
|
||||
}
|
||||
|
||||
TEST(PIMathMatrix_Test, operator_Subtraction) {
|
||||
PIMathMatrix<double> matrix1(3, 3, 6.0);
|
||||
PIMathMatrix<double> matrix2(3, 3, 5.0);
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1 - matrix2, 1.0, 3));
|
||||
PIMathMatrix<double> matrix1(3, 3, 6.0);
|
||||
PIMathMatrix<double> matrix2(3, 3, 5.0);
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1 - matrix2, 1.0, 3));
|
||||
}
|
||||
|
||||
TEST(PIMathMatrix_Test, operator_Multiplication) {
|
||||
PIMathMatrix<double> matrix1(3, 3, 6.72);
|
||||
PIMathMatrix<double> matrix2(3, 3, 5.0);
|
||||
matrix2 = matrix1*4.0;
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(matrix2, 26.88, 3));
|
||||
PIMathMatrix<double> matrix1(3, 3, 6.72);
|
||||
PIMathMatrix<double> matrix2(3, 3, 5.0);
|
||||
matrix2 = matrix1*4.0;
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(matrix2, 26.88, 3));
|
||||
}
|
||||
TEST(PIMathMatrix_Test, operator_Division) {
|
||||
PIMathMatrix<double> matrix1(3, 3, 6.72);
|
||||
PIMathMatrix<double> matrix2(3, 3, 5.0);
|
||||
matrix2 = matrix1/4.0;
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(matrix2, 1.68, 3));
|
||||
PIMathMatrix<double> matrix1(3, 3, 6.72);
|
||||
PIMathMatrix<double> matrix2(3, 3, 5.0);
|
||||
matrix2 = matrix1/4.0;
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(matrix2, 1.68, 3));
|
||||
}
|
||||
|
||||
TEST(PIMathMatrix_Test, determinantIfSquare) {
|
||||
double d;
|
||||
double i = 59.0;
|
||||
PIMathMatrix<double> matrix(3, 3, 0.0);
|
||||
PIMathVector<double> vector;
|
||||
vector.resize(3, 3.0);
|
||||
vector.at(0) = 3.0;
|
||||
vector.at(1) = 6.0;
|
||||
vector.at(2) = 8.0;
|
||||
matrix.setCol(0, vector);
|
||||
vector.at(0) = 2.0;
|
||||
vector.at(1) = 1.0;
|
||||
vector.at(2) = 4.0;
|
||||
matrix.setCol(1, vector);
|
||||
vector.at(0) = 6.0;
|
||||
vector.at(1) = 2.0;
|
||||
vector.at(2) = 5.0;
|
||||
matrix.setCol(2, vector);
|
||||
d = matrix.determinant();
|
||||
ASSERT_DOUBLE_EQ(d, i);
|
||||
}
|
||||
|
||||
TEST(PIMathMatrix_Test, determinantIfNotSquare) {
|
||||
PIMathMatrix<double> matrix(3, 5, 1.0);
|
||||
matrix.element(1,1) = 5.0;
|
||||
ASSERT_FALSE(matrix.determinant());
|
||||
double d;
|
||||
double i = 59.0;
|
||||
PIMathMatrix<double> matrix(3, 3, 0.0);
|
||||
PIMathVector<double> vector;
|
||||
vector.resize(3, 3.0);
|
||||
vector[0] = 3.0;
|
||||
vector[1] = 6.0;
|
||||
vector[2] = 8.0;
|
||||
matrix.setCol(0, vector);
|
||||
vector[0] = 2.0;
|
||||
vector[1] = 1.0;
|
||||
vector[2] = 4.0;
|
||||
matrix.setCol(1, vector);
|
||||
vector[0] = 6.0;
|
||||
vector[1] = 2.0;
|
||||
vector[2] = 5.0;
|
||||
matrix.setCol(2, vector);
|
||||
d = matrix.determinant();
|
||||
ASSERT_DOUBLE_EQ(d, i);
|
||||
}
|
||||
|
||||
TEST(PIMathMatrix_Test, trace) {
|
||||
PIMathMatrix<double> matrix(3, 3, 0.0);
|
||||
double t;
|
||||
double i = 9.0;
|
||||
PIMathVector<double> vector;
|
||||
vector.resize(3, 3.0);
|
||||
vector.at(0) = 3.0;
|
||||
vector.at(1) = 6.0;
|
||||
vector.at(2) = 8.0;
|
||||
matrix.setCol(0, vector);
|
||||
vector.at(0) = 2.0;
|
||||
vector.at(1) = 1.0;
|
||||
vector.at(2) = 4.0;
|
||||
matrix.setCol(1, vector);
|
||||
vector.at(0) = 6.0;
|
||||
vector.at(1) = 2.0;
|
||||
vector.at(2) = 5.0;
|
||||
matrix.setCol(2, vector);
|
||||
t = matrix.trace();
|
||||
ASSERT_DOUBLE_EQ(t, i);
|
||||
}
|
||||
|
||||
TEST(PIMathMatrix_Test, traceIfNotSquare) {
|
||||
PIMathMatrix<double> matrix(3, 5, 1.0);
|
||||
matrix.element(1,1) = 5.0;
|
||||
ASSERT_FALSE(matrix.trace());
|
||||
PIMathMatrix<double> matrix(3, 3, 0.0);
|
||||
double t;
|
||||
double i = 9.0;
|
||||
PIMathVector<double> vector;
|
||||
vector.resize(3, 3.0);
|
||||
vector[0] = 3.0;
|
||||
vector[1] = 6.0;
|
||||
vector[2] = 8.0;
|
||||
matrix.setCol(0, vector);
|
||||
vector[0] = 2.0;
|
||||
vector[1] = 1.0;
|
||||
vector[2] = 4.0;
|
||||
matrix.setCol(1, vector);
|
||||
vector[0] = 6.0;
|
||||
vector[1] = 2.0;
|
||||
vector[2] = 5.0;
|
||||
matrix.setCol(2, vector);
|
||||
t = matrix.trace();
|
||||
ASSERT_DOUBLE_EQ(t, i);
|
||||
}
|
||||
|
||||
TEST(PIMathMatrix_Test, toUpperTriangular) {
|
||||
PIMathMatrix<double> matrix(3, 3, 0.0);
|
||||
double d1, d2 = 1;
|
||||
int i;
|
||||
PIMathVector<double> vector;
|
||||
vector.resize(3, 3.0);
|
||||
vector.at(0) = 3.0;
|
||||
vector.at(1) = 6.0;
|
||||
vector.at(2) = 8.0;
|
||||
matrix.setCol(0, vector);
|
||||
vector.at(0) = 2.0;
|
||||
vector.at(1) = 1.0;
|
||||
vector.at(2) = 4.0;
|
||||
matrix.setCol(1, vector);
|
||||
vector.at(0) = 6.0;
|
||||
vector.at(1) = 2.0;
|
||||
vector.at(2) = 5.0;
|
||||
matrix.setCol(2, vector);
|
||||
d1 = matrix.determinant();
|
||||
matrix.toUpperTriangular();
|
||||
for(i = 0; i < 3; i++)
|
||||
{
|
||||
d2 = d2 * matrix.element(i, i);
|
||||
}
|
||||
ASSERT_DOUBLE_EQ(d1, d2);
|
||||
PIMathMatrix<double> matrix(3, 3, 0.0);
|
||||
double d1, d2 = 1;
|
||||
int i;
|
||||
PIMathVector<double> vector;
|
||||
vector.resize(3, 3.0);
|
||||
vector[0] = 3.0;
|
||||
vector[1] = 6.0;
|
||||
vector[2] = 8.0;
|
||||
matrix.setCol(0, vector);
|
||||
vector[0] = 2.0;
|
||||
vector[1] = 1.0;
|
||||
vector[2] = 4.0;
|
||||
matrix.setCol(1, vector);
|
||||
vector[0] = 6.0;
|
||||
vector[1] = 2.0;
|
||||
vector[2] = 5.0;
|
||||
matrix.setCol(2, vector);
|
||||
d1 = matrix.determinant();
|
||||
matrix.toUpperTriangular();
|
||||
for(i = 0; i < 3; i++)
|
||||
{
|
||||
d2 = d2 * matrix.element(i, i);
|
||||
}
|
||||
ASSERT_DOUBLE_EQ(d1, d2);
|
||||
}
|
||||
|
||||
TEST(PIMathMatrix_Test, invert) {
|
||||
double d1, d2;
|
||||
PIMathMatrix<double> matrix1(3, 3, 0.0);
|
||||
PIMathMatrix<double> matrix2(3, 3, 0.0);
|
||||
PIMathMatrix<double> matrix3(3, 3, 0.0);
|
||||
PIMathMatrix<double> matrix4(3, 3, 0.0);
|
||||
PIMathVector<double> vector;
|
||||
vector.resize(3, 3.0);
|
||||
vector.at(0) = 3.0;
|
||||
vector.at(1) = 6.0;
|
||||
vector.at(2) = 8.0;
|
||||
matrix1.setCol(0, vector);
|
||||
vector.at(0) = 2.0;
|
||||
vector.at(1) = 1.0;
|
||||
vector.at(2) = 4.0;
|
||||
matrix1.setCol(1, vector);
|
||||
vector.at(0) = 6.0;
|
||||
vector.at(1) = 2.0;
|
||||
vector.at(2) = 5.0;
|
||||
matrix1.setCol(2, vector);
|
||||
d1 = matrix1.determinant();
|
||||
matrix2 = matrix1;
|
||||
matrix2.invert();
|
||||
d2 = matrix2.determinant();
|
||||
matrix4.invert();
|
||||
ASSERT_TRUE((matrix3 == matrix4) && (round((1/d1)*10000)/10000 == round(d2*10000)/10000));
|
||||
double d1, d2;
|
||||
PIMathMatrix<double> matrix1(3, 3, 0.0);
|
||||
PIMathMatrix<double> matrix2(3, 3, 0.0);
|
||||
PIMathMatrix<double> matrix3(3, 3, 0.0);
|
||||
PIMathMatrix<double> matrix4(3, 3, 0.0);
|
||||
PIMathVector<double> vector;
|
||||
vector.resize(3, 3.0);
|
||||
vector[0] = 3.0;
|
||||
vector[1] = 6.0;
|
||||
vector[2] = 8.0;
|
||||
matrix1.setCol(0, vector);
|
||||
vector[0] = 2.0;
|
||||
vector[1] = 1.0;
|
||||
vector[2] = 4.0;
|
||||
matrix1.setCol(1, vector);
|
||||
vector[0] = 6.0;
|
||||
vector[1] = 2.0;
|
||||
vector[2] = 5.0;
|
||||
matrix1.setCol(2, vector);
|
||||
d1 = matrix1.determinant();
|
||||
matrix2 = matrix1;
|
||||
matrix2.invert();
|
||||
d2 = matrix2.determinant();
|
||||
matrix4.invert();
|
||||
ASSERT_TRUE((matrix3 == matrix4) && (round((1/d1)*10000)/10000 == round(d2*10000)/10000));
|
||||
}
|
||||
|
||||
TEST(PIMathMatrix_Test, inverted) {
|
||||
double d1, d2;
|
||||
PIMathMatrix<double> matrix1(3, 3, 0.0);
|
||||
PIMathMatrix<double> matrix2(3, 3, 0.0);
|
||||
PIMathMatrix<double> matrix3(3, 3, 0.0);
|
||||
PIMathMatrix<double> matrix4(3, 3, 0.0);
|
||||
PIMathVector<double> vector;
|
||||
vector.resize(3, 3.0);
|
||||
vector.at(0) = 3.0;
|
||||
vector.at(1) = 6.0;
|
||||
vector.at(2) = 8.0;
|
||||
matrix1.setCol(0, vector);
|
||||
vector.at(0) = 2.0;
|
||||
vector.at(1) = 1.0;
|
||||
vector.at(2) = 4.0;
|
||||
matrix1.setCol(1, vector);
|
||||
vector.at(0) = 6.0;
|
||||
vector.at(1) = 2.0;
|
||||
vector.at(2) = 5.0;
|
||||
matrix1.setCol(2, vector);
|
||||
d1 = matrix1.determinant();
|
||||
matrix2 = matrix1;
|
||||
matrix1 = matrix2.invert();
|
||||
d2 = matrix1.determinant();
|
||||
matrix3 = matrix4.invert();
|
||||
ASSERT_TRUE((matrix3 == matrix4) && (round((1/d1)*10000)/10000 == round(d2*10000)/10000));
|
||||
double d1, d2;
|
||||
PIMathMatrix<double> matrix1(3, 3, 0.0);
|
||||
PIMathMatrix<double> matrix2(3, 3, 0.0);
|
||||
PIMathMatrix<double> matrix3(3, 3, 0.0);
|
||||
PIMathMatrix<double> matrix4(3, 3, 0.0);
|
||||
PIMathVector<double> vector;
|
||||
vector.resize(3, 3.0);
|
||||
vector[0] = 3.0;
|
||||
vector[1] = 6.0;
|
||||
vector[2] = 8.0;
|
||||
matrix1.setCol(0, vector);
|
||||
vector[0] = 2.0;
|
||||
vector[1] = 1.0;
|
||||
vector[2] = 4.0;
|
||||
matrix1.setCol(1, vector);
|
||||
vector[0] = 6.0;
|
||||
vector[1] = 2.0;
|
||||
vector[2] = 5.0;
|
||||
matrix1.setCol(2, vector);
|
||||
d1 = matrix1.determinant();
|
||||
matrix2 = matrix1;
|
||||
matrix1 = matrix2.invert();
|
||||
d2 = matrix1.determinant();
|
||||
matrix3 = matrix4.invert();
|
||||
ASSERT_TRUE((matrix3 == matrix4) && (round((1/d1)*10000)/10000 == round(d2*10000)/10000));
|
||||
}
|
||||
|
||||
TEST(PIMathMatrix_Test, transposed) {
|
||||
PIMathMatrix<double> origMatr;
|
||||
double d1, d2;
|
||||
PIMathMatrix<double> matrix1;
|
||||
PIMathMatrix<double> matrix2;
|
||||
PIMathMatrix<double> matrix3;
|
||||
PIMathVector<double> vector;
|
||||
vector.resize(3, 3.0);
|
||||
vector.at(0) = 3.0;
|
||||
vector.at(1) = 6.0;
|
||||
vector.at(2) = 8.0;
|
||||
matrix1 = origMatr.identity(3, 3);
|
||||
matrix1.setCol(0, vector);
|
||||
vector.at(0) = 2.0;
|
||||
vector.at(1) = 1.0;
|
||||
vector.at(2) = 4.0;
|
||||
matrix1.setCol(1, vector);
|
||||
vector.at(0) = 6.0;
|
||||
vector.at(1) = 2.0;
|
||||
vector.at(2) = 5.0;
|
||||
matrix1.setCol(2, vector);
|
||||
d1 = matrix1.determinant();
|
||||
matrix2 = matrix1.transposed();
|
||||
d2 = matrix2.determinant();
|
||||
matrix3 = matrix2.transposed();
|
||||
ASSERT_TRUE((d1 == d2) && (matrix1 == matrix3));
|
||||
PIMathMatrix<double> origMatr;
|
||||
double d1, d2;
|
||||
PIMathMatrix<double> matrix1;
|
||||
PIMathMatrix<double> matrix2;
|
||||
PIMathMatrix<double> matrix3;
|
||||
PIMathVector<double> vector;
|
||||
vector.resize(3, 3.0);
|
||||
vector[0] = 3.0;
|
||||
vector[1] = 6.0;
|
||||
vector[2] = 8.0;
|
||||
matrix1 = origMatr.identity(3, 3);
|
||||
matrix1.setCol(0, vector);
|
||||
vector[0] = 2.0;
|
||||
vector[1] = 1.0;
|
||||
vector[2] = 4.0;
|
||||
matrix1.setCol(1, vector);
|
||||
vector[0] = 6.0;
|
||||
vector[1] = 2.0;
|
||||
vector[2] = 5.0;
|
||||
matrix1.setCol(2, vector);
|
||||
d1 = matrix1.determinant();
|
||||
matrix2 = matrix1.transposed();
|
||||
d2 = matrix2.determinant();
|
||||
matrix3 = matrix2.transposed();
|
||||
ASSERT_TRUE((d1 == d2) && (matrix1 == matrix3));
|
||||
}
|
||||
|
||||
TEST(PIMathMatrix_Test, matrixMultiplication) {
|
||||
PIMathMatrix<double> matrix1(2, 2, 1.5);
|
||||
PIMathMatrix<double> matrix2(2, 2, 2.5);
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1 * matrix2, 7.5, 2));
|
||||
PIMathMatrix<double> matrix1(2, 2, 1.5);
|
||||
PIMathMatrix<double> matrix2(2, 2, 2.5);
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1 * matrix2, 7.5, 2));
|
||||
}
|
||||
|
||||
TEST(PIMathMatrix_Test, matrixAndVectorMultiplication) {
|
||||
PIMathMatrix<double> matrix1(2, 2, 1.5);
|
||||
PIMathVector<double> vector;
|
||||
vector.resize(2, 2.5);
|
||||
for(uint i = 0; i < 2; i++) {
|
||||
if((matrix1 * vector)[i] != 7.5) {
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
ASSERT_TRUE(true);
|
||||
PIMathMatrix<double> matrix1(2, 2, 1.5);
|
||||
PIMathVector<double> vector;
|
||||
vector.resize(2, 2.5);
|
||||
for(uint i = 0; i < 2; i++) {
|
||||
if((matrix1 * vector)[i] != 7.5) {
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
ASSERT_TRUE(true);
|
||||
}
|
||||
|
||||
TEST(PIMathMatrix_Test, vectorAndMatrixMultiplication) {
|
||||
PIMathMatrix<double> matrix1(2, 2, 1.5);
|
||||
PIMathVector<double> vector;
|
||||
vector.resize(2, 2.5);
|
||||
for(uint i = 0; i < 2; i++) {
|
||||
if((vector * matrix1)[i] != 7.5) {
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
ASSERT_TRUE(true);
|
||||
PIMathMatrix<double> matrix1(2, 2, 1.5);
|
||||
PIMathVector<double> vector;
|
||||
vector.resize(2, 2.5);
|
||||
for(uint i = 0; i < 2; i++) {
|
||||
if((vector * matrix1)[i] != 7.5) {
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
ASSERT_TRUE(true);
|
||||
}
|
||||
|
||||
TEST(PIMathMatrix_Test, valAndMatrixMultiplication) {
|
||||
PIMathMatrix<double> matrix1(3, 3, 1.5);
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(25.0*matrix1, 37.5, 3));
|
||||
PIMathMatrix<double> matrix1(3, 3, 1.5);
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(25.0*matrix1, 37.5, 3));
|
||||
}
|
||||
|
||||
TEST(PIMathMatrix_Test, hermitian) {
|
||||
complex<double> val;
|
||||
complex<double> res;
|
||||
val.imag(1.0);
|
||||
val.real(1.0);
|
||||
PIMathMatrix<complex<double>> matrix(3, 3, val);
|
||||
res.imag(-1.0);
|
||||
res.real(1.0);
|
||||
auto matr = hermitian(matrix);
|
||||
for(uint i = 0; i < 3; i++) {
|
||||
for(uint j = 0; j < 3; j++) {
|
||||
if(matr.element(i, j) != res) {
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
ASSERT_TRUE(true);
|
||||
complex<double> val;
|
||||
complex<double> res;
|
||||
val.imag(1.0);
|
||||
val.real(1.0);
|
||||
PIMathMatrix<complex<double>> matrix(3, 3, val);
|
||||
res.imag(-1.0);
|
||||
res.real(1.0);
|
||||
auto matr = hermitian(matrix);
|
||||
for(uint i = 0; i < 3; i++) {
|
||||
for(uint j = 0; j < 3; j++) {
|
||||
if(matr.element(i, j) != res) {
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
ASSERT_TRUE(true);
|
||||
}
|
||||
|
||||
@@ -5,558 +5,485 @@ const uint rows = 3;
|
||||
const uint cols = 3;
|
||||
|
||||
bool cmpSquareMatrixWithValue(PIMathMatrixT<rows, cols, double> matrix, double val, int num) {
|
||||
bool b = true;
|
||||
for(int i = 0; i < num; i++) {
|
||||
for(int j = 0; j < num; j++) {
|
||||
if(matrix.at(i, j) != val) {
|
||||
b = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return b;
|
||||
bool b = true;
|
||||
for(int i = 0; i < num; i++) {
|
||||
for(int j = 0; j < num; j++) {
|
||||
if(matrix.at(i, j) != val) {
|
||||
b = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, identity) {
|
||||
auto matrix = PIMathMatrixT<rows, cols, double>::identity();
|
||||
for(int i = 0; i < 3; i++){
|
||||
for(int j = 0; j < 3; j++){
|
||||
if(i != j){
|
||||
if(matrix[i][j] != 0.0){
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(matrix[i][i] != 1.0){
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ASSERT_TRUE(true);
|
||||
auto matrix = PIMathMatrixT<rows, cols, double>::identity();
|
||||
for(int i = 0; i < 3; i++){
|
||||
for(int j = 0; j < 3; j++){
|
||||
if(i != j){
|
||||
if(matrix[i][j] != 0.0){
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(matrix[i][i] != 1.0){
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ASSERT_TRUE(true);
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, at) {
|
||||
auto matrix1 = PIMathMatrixT<rows, cols, double>::identity();
|
||||
for(uint i = 0; i < rows; i++) {
|
||||
if(matrix1.at(i,i) != 1.0) {
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
ASSERT_TRUE(true);
|
||||
auto matrix1 = PIMathMatrixT<rows, cols, double>::identity();
|
||||
for(uint i = 0; i < rows; i++) {
|
||||
if(matrix1.at(i,i) != 1.0) {
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
ASSERT_TRUE(true);
|
||||
}
|
||||
TEST(PIMathMatrixT_Test, filled) {
|
||||
auto matr = PIMathMatrixT<rows, cols, double>::filled(1.0);
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(matr, 1.0, rows));
|
||||
auto matr = PIMathMatrixT<rows, cols, double>(1.0);
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(matr, 1.0, rows));
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, cols) {
|
||||
PIMathMatrixT<rows, cols, double> matr;
|
||||
ASSERT_EQ(cols,matr.cols());
|
||||
PIMathMatrixT<rows, cols, double> matr;
|
||||
ASSERT_EQ(cols,matr.cols());
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, rows) {
|
||||
PIMathMatrixT<rows, cols, double> matr;
|
||||
ASSERT_EQ(rows,matr.rows());
|
||||
PIMathMatrixT<rows, cols, double> matr;
|
||||
ASSERT_EQ(rows,matr.rows());
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, col) {
|
||||
PIMathMatrixT<rows, cols, double> matr;
|
||||
PIMathVectorT<rows, double> vect;
|
||||
uint g = 2;
|
||||
matr.at(0,0) = 3;
|
||||
matr.at(0,1) = 6;
|
||||
matr.at(0,2) = 8;
|
||||
matr.at(1,0) = 2;
|
||||
matr.at(1,1) = 1;
|
||||
matr.at(1,2) = 4;
|
||||
matr.at(2,0) = 6;
|
||||
matr.at(2,1) = 2;
|
||||
matr.at(2,2) = 5;
|
||||
vect = matr.col(g);
|
||||
for(uint i = 0; i < matr.cols(); i++) {
|
||||
if(matr.at(i, g) != vect.at(i)) {
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
ASSERT_TRUE(true);
|
||||
PIMathMatrixT<rows, cols, double> matr;
|
||||
PIMathVectorT<rows, double> vect;
|
||||
uint g = 2;
|
||||
matr.element(0,0) = 3;
|
||||
matr.element(0,1) = 6;
|
||||
matr.element(0,2) = 8;
|
||||
matr.element(1,0) = 2;
|
||||
matr.element(1,1) = 1;
|
||||
matr.element(1,2) = 4;
|
||||
matr.element(2,0) = 6;
|
||||
matr.element(2,1) = 2;
|
||||
matr.element(2,2) = 5;
|
||||
vect = matr.col(g);
|
||||
for(uint i = 0; i < matr.cols(); i++) {
|
||||
if(matr.element(i, g) != vect[i]) {
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
ASSERT_TRUE(true);
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, row) {
|
||||
PIMathMatrixT<rows, cols, double> matr;
|
||||
PIMathVectorT<rows, double> vect;
|
||||
uint g = 2;
|
||||
matr.at(0,0) = 3;
|
||||
matr.at(0,1) = 6;
|
||||
matr.at(0,2) = 8;
|
||||
matr.at(1,0) = 2;
|
||||
matr.at(1,1) = 1;
|
||||
matr.at(1,2) = 4;
|
||||
matr.at(2,0) = 6;
|
||||
matr.at(2,1) = 2;
|
||||
matr.at(2,2) = 5;
|
||||
vect = matr.row(g);
|
||||
for(uint i = 0; i < matr.rows(); i++) {
|
||||
if(matr.at(g, i) != vect.at(i)) {
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
ASSERT_TRUE(true);
|
||||
PIMathMatrixT<rows, cols, double> matr;
|
||||
PIMathVectorT<rows, double> vect;
|
||||
uint g = 2;
|
||||
matr.element(0,0) = 3;
|
||||
matr.element(0,1) = 6;
|
||||
matr.element(0,2) = 8;
|
||||
matr.element(1,0) = 2;
|
||||
matr.element(1,1) = 1;
|
||||
matr.element(1,2) = 4;
|
||||
matr.element(2,0) = 6;
|
||||
matr.element(2,1) = 2;
|
||||
matr.element(2,2) = 5;
|
||||
vect = matr.row(g);
|
||||
for(uint i = 0; i < matr.rows(); i++) {
|
||||
if(matr.element(g, i) != vect[i]) {
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
ASSERT_TRUE(true);
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, setCol) {
|
||||
PIMathMatrixT<rows, cols, double> matr;
|
||||
PIMathVectorT<rows, double> vect;
|
||||
vect.at(0) = 1.0;
|
||||
vect.at(1) = 3.0;
|
||||
vect.at(2) = 5.0;
|
||||
uint g = 1;
|
||||
matr.setCol(g, vect);
|
||||
for(uint i = 0; i < vect.size(); i++) {
|
||||
if(matr.at(i, g) != vect.at(i)) {
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
ASSERT_TRUE(true);
|
||||
PIMathMatrixT<rows, cols, double> matr;
|
||||
PIMathVectorT<rows, double> vect;
|
||||
vect[0] = 1.0;
|
||||
vect[1] = 3.0;
|
||||
vect[2] = 5.0;
|
||||
uint g = 1;
|
||||
matr.setCol(g, vect);
|
||||
for(uint i = 0; i < vect.size(); i++) {
|
||||
if(matr.element(i, g) != vect[i]) {
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
ASSERT_TRUE(true);
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, setRow) {
|
||||
PIMathMatrixT<rows, cols, double> matr;
|
||||
PIMathVectorT<rows, double> vect;
|
||||
vect.at(0) = 1.0;
|
||||
vect.at(1) = 3.0;
|
||||
vect.at(2) = 5.0;
|
||||
uint g = 1;
|
||||
matr.setRow(g, vect);
|
||||
for(uint i = 0; i < vect.size(); i++) {
|
||||
if(matr.at(g,i) != vect.at(i)) {
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
ASSERT_TRUE(true);
|
||||
PIMathMatrixT<rows, cols, double> matr;
|
||||
PIMathVectorT<rows, double> vect;
|
||||
vect[0] = 1.0;
|
||||
vect[1] = 3.0;
|
||||
vect[2] = 5.0;
|
||||
uint g = 1;
|
||||
matr.setRow(g, vect);
|
||||
for(uint i = 0; i < vect.size(); i++) {
|
||||
if(matr.element(g,i) != vect[i]) {
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
ASSERT_TRUE(true);
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, swapCols) {
|
||||
PIMathMatrixT<rows, cols, double> matr;
|
||||
int g1 = 1, g2 = 2;
|
||||
matr.at(0,0) = 3;
|
||||
matr.at(0,1) = 6;
|
||||
matr.at(0,2) = 8;
|
||||
matr.at(1,0) = 2;
|
||||
matr.at(1,1) = 1;
|
||||
matr.at(1,2) = 4;
|
||||
matr.at(2,0) = 6;
|
||||
matr.at(2,1) = 2;
|
||||
matr.at(2,2) = 5;
|
||||
const PIMathVectorT<rows, double> before_Vect1 = matr.col(g1);
|
||||
const PIMathVectorT<rows, double> before_Vect2 = matr.col(g2);
|
||||
matr.swapCols(g1, g2);
|
||||
const PIMathVectorT<rows, double> after_Vect1 = matr.col(g1);
|
||||
const PIMathVectorT<rows, double> after_Vect2 = matr.col(g2);
|
||||
if((before_Vect1 == after_Vect2) && (before_Vect2 == after_Vect1)) {
|
||||
ASSERT_TRUE(true);
|
||||
}
|
||||
else {
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
PIMathMatrixT<rows, cols, double> matr;
|
||||
int g1 = 1, g2 = 2;
|
||||
matr.element(0,0) = 3;
|
||||
matr.element(0,1) = 6;
|
||||
matr.element(0,2) = 8;
|
||||
matr.element(1,0) = 2;
|
||||
matr.element(1,1) = 1;
|
||||
matr.element(1,2) = 4;
|
||||
matr.element(2,0) = 6;
|
||||
matr.element(2,1) = 2;
|
||||
matr.element(2,2) = 5;
|
||||
const PIMathVectorT<rows, double> before_Vect1 = matr.col(g1);
|
||||
const PIMathVectorT<rows, double> before_Vect2 = matr.col(g2);
|
||||
matr.swapCols(g1, g2);
|
||||
const PIMathVectorT<rows, double> after_Vect1 = matr.col(g1);
|
||||
const PIMathVectorT<rows, double> after_Vect2 = matr.col(g2);
|
||||
if((before_Vect1 == after_Vect2) && (before_Vect2 == after_Vect1)) {
|
||||
ASSERT_TRUE(true);
|
||||
}
|
||||
else {
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, swapRows) {
|
||||
PIMathMatrixT<rows, cols, double> matr;
|
||||
int g1 = 1, g2 = 2;
|
||||
matr.at(0,0) = 3;
|
||||
matr.at(0,1) = 6;
|
||||
matr.at(0,2) = 8;
|
||||
matr.at(1,0) = 2;
|
||||
matr.at(1,1) = 1;
|
||||
matr.at(1,2) = 4;
|
||||
matr.at(2,0) = 6;
|
||||
matr.at(2,1) = 2;
|
||||
matr.at(2,2) = 5;
|
||||
const PIMathVectorT<rows, double> before_Vect1 = matr.row(g1);
|
||||
const PIMathVectorT<rows, double> before_Vect2 = matr.row(g2);
|
||||
matr.swapRows(g1, g2);
|
||||
const PIMathVectorT<rows, double> after_Vect1 = matr.row(g1);
|
||||
const PIMathVectorT<rows, double> after_Vect2 = matr.row(g2);
|
||||
if((before_Vect1 == after_Vect2) && (before_Vect2 == after_Vect1)) {
|
||||
ASSERT_TRUE(true);
|
||||
}
|
||||
else {
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
PIMathMatrixT<rows, cols, double> matr;
|
||||
int g1 = 1, g2 = 2;
|
||||
matr.element(0,0) = 3;
|
||||
matr.element(0,1) = 6;
|
||||
matr.element(0,2) = 8;
|
||||
matr.element(1,0) = 2;
|
||||
matr.element(1,1) = 1;
|
||||
matr.element(1,2) = 4;
|
||||
matr.element(2,0) = 6;
|
||||
matr.element(2,1) = 2;
|
||||
matr.element(2,2) = 5;
|
||||
const PIMathVectorT<rows, double> before_Vect1 = matr.row(g1);
|
||||
const PIMathVectorT<rows, double> before_Vect2 = matr.row(g2);
|
||||
matr.swapRows(g1, g2);
|
||||
const PIMathVectorT<rows, double> after_Vect1 = matr.row(g1);
|
||||
const PIMathVectorT<rows, double> after_Vect2 = matr.row(g2);
|
||||
if((before_Vect1 == after_Vect2) && (before_Vect2 == after_Vect1)) {
|
||||
ASSERT_TRUE(true);
|
||||
}
|
||||
else {
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, fill) {
|
||||
PIMathMatrixT<rows, cols, double> matr;
|
||||
PIMathMatrixT<rows, cols, double> matrix1;
|
||||
double g = 1.0;
|
||||
matr.fill(g);
|
||||
for(uint i = 0; i < cols; i++) {
|
||||
for(uint j = 0; j < rows; j++) {
|
||||
matrix1.at(j,i) = g;
|
||||
}
|
||||
}
|
||||
ASSERT_TRUE(matr == matrix1);
|
||||
PIMathMatrixT<rows, cols, double> matr;
|
||||
PIMathMatrixT<rows, cols, double> matrix1;
|
||||
double g = 1.0;
|
||||
matr.fill(g);
|
||||
for(uint i = 0; i < cols; i++) {
|
||||
for(uint j = 0; j < rows; j++) {
|
||||
matrix1.element(j,i) = g;
|
||||
}
|
||||
}
|
||||
ASSERT_TRUE(matr == matrix1);
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, isSquareTrue) {
|
||||
PIMathMatrixT<rows, cols, double> matrix1;
|
||||
ASSERT_TRUE(matrix1.isSquare());
|
||||
PIMathMatrixT<rows, cols, double> matrix1;
|
||||
ASSERT_TRUE(matrix1.isSquare());
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, isSquareFalse) {
|
||||
const uint new_Cols = 4;
|
||||
PIMathMatrixT<rows, new_Cols, double> matrix2;
|
||||
ASSERT_FALSE(matrix2.isSquare());
|
||||
const uint new_Cols = 4;
|
||||
PIMathMatrixT<rows, new_Cols, double> matrix2;
|
||||
ASSERT_FALSE(matrix2.isSquare());
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, isIdentityTrue) {
|
||||
auto matrix1 = PIMathMatrixT<rows, cols, double>::identity();
|
||||
ASSERT_TRUE(matrix1.isIdentity());
|
||||
auto matrix1 = PIMathMatrixT<rows, cols, double>::identity();
|
||||
ASSERT_TRUE(matrix1.isIdentity());
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, isIdentityFalse) {
|
||||
auto matrix1 = PIMathMatrixT<rows, cols, double>::filled(2.5);
|
||||
ASSERT_FALSE(matrix1.isIdentity());
|
||||
auto matrix1 = PIMathMatrixT<rows, cols, double>(2.5);
|
||||
ASSERT_FALSE(matrix1.isIdentity());
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, isNullTrue) {
|
||||
PIMathMatrixT<rows, cols, double> matrix1;
|
||||
ASSERT_TRUE(matrix1.isNull());
|
||||
PIMathMatrixT<rows, cols, double> matrix1;
|
||||
ASSERT_TRUE(matrix1.isNull());
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, isNullFalse) {
|
||||
auto matrix1 = PIMathMatrixT<rows, cols, double>::identity();
|
||||
ASSERT_FALSE(matrix1.isNull());
|
||||
auto matrix1 = PIMathMatrixT<rows, cols, double>::identity();
|
||||
ASSERT_FALSE(matrix1.isNull());
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, operator_Assignment) {
|
||||
PIMathMatrixT<rows, cols, double> matrix1;
|
||||
auto matrix2 = PIMathMatrixT<rows, cols, double>::filled(6.72);
|
||||
matrix1 = matrix2;
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1, 6.72, rows));
|
||||
PIMathMatrixT<rows, cols, double> matrix1;
|
||||
auto matrix2 = PIMathMatrixT<rows, cols, double>(6.72);
|
||||
matrix1 = matrix2;
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1, 6.72, rows));
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, operator_EqualTrue) {
|
||||
PIMathMatrixT<rows, cols, double> matrix1;
|
||||
PIMathMatrixT<rows, cols, double> matrix2;
|
||||
matrix1.at(0, 0) = 5.1;
|
||||
matrix1.at(0, 1) = 1.21;
|
||||
matrix1.at(1, 1) = 0.671;
|
||||
matrix1.at(1, 0) = 2.623;
|
||||
matrix2.at(0, 0) = 5.1;
|
||||
matrix2.at(0, 1) = 1.21;
|
||||
matrix2.at(1, 1) = 0.671;
|
||||
matrix2.at(1, 0) = 2.623;
|
||||
ASSERT_TRUE(matrix1 == matrix2);
|
||||
PIMathMatrixT<rows, cols, double> matrix1;
|
||||
PIMathMatrixT<rows, cols, double> matrix2;
|
||||
matrix1.element(0, 0) = 5.1;
|
||||
matrix1.element(0, 1) = 1.21;
|
||||
matrix1.element(1, 1) = 0.671;
|
||||
matrix1.element(1, 0) = 2.623;
|
||||
matrix2.element(0, 0) = 5.1;
|
||||
matrix2.element(0, 1) = 1.21;
|
||||
matrix2.element(1, 1) = 0.671;
|
||||
matrix2.element(1, 0) = 2.623;
|
||||
ASSERT_TRUE(matrix1 == matrix2);
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, operator_EqualFalse) {
|
||||
PIMathMatrixT<rows, cols, double> matrix1;
|
||||
PIMathMatrixT<rows, cols, double> matrix2;
|
||||
matrix1.at(0, 0) = 5.1;
|
||||
matrix1.at(0, 1) = 1.21;
|
||||
matrix1.at(1, 1) = 0.671;
|
||||
matrix1.at(1, 0) = 2.623;
|
||||
matrix2.at(0, 0) = 5.1;
|
||||
matrix2.at(0, 1) = 1.21;
|
||||
matrix2.at(1, 1) = 665.671;
|
||||
matrix2.at(1, 0) = 2.623;
|
||||
ASSERT_FALSE(matrix1 == matrix2);
|
||||
PIMathMatrixT<rows, cols, double> matrix1;
|
||||
PIMathMatrixT<rows, cols, double> matrix2;
|
||||
matrix1.element(0, 0) = 5.1;
|
||||
matrix1.element(0, 1) = 1.21;
|
||||
matrix1.element(1, 1) = 0.671;
|
||||
matrix1.element(1, 0) = 2.623;
|
||||
matrix2.element(0, 0) = 5.1;
|
||||
matrix2.element(0, 1) = 1.21;
|
||||
matrix2.element(1, 1) = 665.671;
|
||||
matrix2.element(1, 0) = 2.623;
|
||||
ASSERT_FALSE(matrix1 == matrix2);
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, operator_Not_EqualTrue) {
|
||||
PIMathMatrixT<rows, cols, double> matrix1;
|
||||
PIMathMatrixT<rows, cols, double> matrix2;
|
||||
matrix1.at(0, 0) = 5.1;
|
||||
matrix1.at(0, 1) = 1.21;
|
||||
matrix1.at(1, 1) = 0.671;
|
||||
matrix1.at(1, 0) = 2.623;
|
||||
matrix2.at(0, 0) = 5.1;
|
||||
matrix2.at(0, 1) = 1.21;
|
||||
matrix2.at(1, 1) = 665.671;
|
||||
matrix2.at(1, 0) = 2.623;
|
||||
ASSERT_TRUE(matrix1 != matrix2);
|
||||
PIMathMatrixT<rows, cols, double> matrix1;
|
||||
PIMathMatrixT<rows, cols, double> matrix2;
|
||||
matrix1.element(0, 0) = 5.1;
|
||||
matrix1.element(0, 1) = 1.21;
|
||||
matrix1.element(1, 1) = 0.671;
|
||||
matrix1.element(1, 0) = 2.623;
|
||||
matrix2.element(0, 0) = 5.1;
|
||||
matrix2.element(0, 1) = 1.21;
|
||||
matrix2.element(1, 1) = 665.671;
|
||||
matrix2.element(1, 0) = 2.623;
|
||||
ASSERT_TRUE(matrix1 != matrix2);
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, operator_Not_EqualFalse) {
|
||||
PIMathMatrixT<rows, cols, double> matrix1;
|
||||
PIMathMatrixT<rows, cols, double> matrix2;
|
||||
matrix1.at(0, 0) = 5.1;
|
||||
matrix1.at(0, 1) = 1.21;
|
||||
matrix1.at(1, 1) = 0.671;
|
||||
matrix1.at(1, 0) = 2.623;
|
||||
matrix2.at(0, 0) = 5.1;
|
||||
matrix2.at(0, 1) = 1.21;
|
||||
matrix2.at(1, 1) = 0.671;
|
||||
matrix2.at(1, 0) = 2.623;
|
||||
ASSERT_FALSE(matrix1 != matrix2);
|
||||
PIMathMatrixT<rows, cols, double> matrix1;
|
||||
PIMathMatrixT<rows, cols, double> matrix2;
|
||||
matrix1.element(0, 0) = 5.1;
|
||||
matrix1.element(0, 1) = 1.21;
|
||||
matrix1.element(1, 1) = 0.671;
|
||||
matrix1.element(1, 0) = 2.623;
|
||||
matrix2.element(0, 0) = 5.1;
|
||||
matrix2.element(0, 1) = 1.21;
|
||||
matrix2.element(1, 1) = 0.671;
|
||||
matrix2.element(1, 0) = 2.623;
|
||||
ASSERT_FALSE(matrix1 != matrix2);
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, operator_Addition_Assignment) {
|
||||
auto matrix1 = PIMathMatrixT<rows, cols, double>::filled(6.72) ;
|
||||
auto matrix2 = PIMathMatrixT<rows, cols, double>::filled(1.0) ;
|
||||
matrix1 += matrix2;
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1, 7.72, rows));
|
||||
auto matrix1 = PIMathMatrixT<rows, cols, double>(6.72) ;
|
||||
auto matrix2 = PIMathMatrixT<rows, cols, double>(1.0) ;
|
||||
matrix1 += matrix2;
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1, 7.72, rows));
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, operator_Subtraction_Assignment) {
|
||||
auto matrix1 = PIMathMatrixT<rows, cols, double>::filled(1.0);
|
||||
auto matrix2 = PIMathMatrixT<rows, cols, double>::filled(6.72);
|
||||
matrix1 -= matrix2;
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1, -5.72, rows));
|
||||
auto matrix1 = PIMathMatrixT<rows, cols, double>(1.0);
|
||||
auto matrix2 = PIMathMatrixT<rows, cols, double>(6.72);
|
||||
matrix1 -= matrix2;
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1, -5.72, rows));
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, operator_Multiplication_Assignment) {
|
||||
auto matrix1 = PIMathMatrixT<rows, cols, double>::filled(6.72);
|
||||
matrix1 *= 2.0;
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1, 13.44, rows));
|
||||
auto matrix1 = PIMathMatrixT<rows, cols, double>(6.72);
|
||||
matrix1 *= 2.0;
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1, 13.44, rows));
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, operator_Division_Assignment) {
|
||||
auto matrix1 = PIMathMatrixT<rows, cols, double>::filled(6.72);
|
||||
matrix1 /= 2.0;
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1, 3.36, rows));
|
||||
auto matrix1 = PIMathMatrixT<rows, cols, double>(6.72);
|
||||
matrix1 /= 2.0;
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1, 3.36, rows));
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, operator_Addition) {
|
||||
auto matrix1 = PIMathMatrixT<rows, cols, double>::filled(6.72);
|
||||
auto matrix2 = PIMathMatrixT<rows, cols, double>::filled(8.28);
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1 + matrix2, 15.0, rows));
|
||||
auto matrix1 = PIMathMatrixT<rows, cols, double>(6.72);
|
||||
auto matrix2 = PIMathMatrixT<rows, cols, double>(8.28);
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1 + matrix2, 15.0, rows));
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, operator_Subtraction) {
|
||||
auto matrix1 = PIMathMatrixT<rows, cols, double>::filled(6.0);
|
||||
auto matrix2 = PIMathMatrixT<rows, cols, double>::filled(5.0);
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1 - matrix2, 1.0, rows));
|
||||
auto matrix1 = PIMathMatrixT<rows, cols, double>(6.0);
|
||||
auto matrix2 = PIMathMatrixT<rows, cols, double>(5.0);
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1 - matrix2, 1.0, rows));
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, operator_Multiplication) {
|
||||
auto matrix1 = PIMathMatrixT<rows, cols, double>::filled(6.72);
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1 * 4.0, 26.88, rows));
|
||||
auto matrix1 = PIMathMatrixT<rows, cols, double>(6.72);
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1 * 4.0, 26.88, rows));
|
||||
}
|
||||
TEST(PIMathMatrixT_Test, operator_Division) {
|
||||
auto matrix1 = PIMathMatrixT<rows, cols, double>::filled(6.72);
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1 / 4.0, 1.68, rows));
|
||||
auto matrix1 = PIMathMatrixT<rows, cols, double>(6.72);
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1 / 4.0, 1.68, rows));
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, determinantIfSquare) {
|
||||
double d;
|
||||
double i = 59.0;
|
||||
PIMathMatrixT<rows, cols, double> matr;
|
||||
matr.at(0,0) = 3;
|
||||
matr.at(0,1) = 6;
|
||||
matr.at(0,2) = 8;
|
||||
matr.at(1,0) = 2;
|
||||
matr.at(1,1) = 1;
|
||||
matr.at(1,2) = 4;
|
||||
matr.at(2,0) = 6;
|
||||
matr.at(2,1) = 2;
|
||||
matr.at(2,2) = 5;
|
||||
d = matr.determinant();
|
||||
ASSERT_DOUBLE_EQ(i, d);
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, determinantIfNotSquare) {
|
||||
PIMathMatrixT<rows, 5u, double> matr;
|
||||
matr.at(0,0) = 3;
|
||||
matr.at(0,1) = 6;
|
||||
matr.at(0,2) = 8;
|
||||
matr.at(1,0) = 2;
|
||||
matr.at(1,1) = 1;
|
||||
matr.at(1,2) = 4;
|
||||
matr.at(2,0) = 6;
|
||||
matr.at(2,1) = 2;
|
||||
matr.at(2,2) = 5;
|
||||
ASSERT_FALSE(matr.determinant());
|
||||
double d;
|
||||
double i = 59.0;
|
||||
PIMathMatrixT<rows, cols, double> matr;
|
||||
matr.element(0,0) = 3;
|
||||
matr.element(0,1) = 6;
|
||||
matr.element(0,2) = 8;
|
||||
matr.element(1,0) = 2;
|
||||
matr.element(1,1) = 1;
|
||||
matr.element(1,2) = 4;
|
||||
matr.element(2,0) = 6;
|
||||
matr.element(2,1) = 2;
|
||||
matr.element(2,2) = 5;
|
||||
d = matr.determinant();
|
||||
ASSERT_DOUBLE_EQ(i, d);
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, invert) {
|
||||
PIMathMatrixT<rows, cols, double> matrix1;
|
||||
PIMathMatrixT<rows, cols, double> matrix2;
|
||||
PIMathMatrixT<rows, cols, double> matrix3;
|
||||
PIMathMatrixT<rows, cols, double> matr;
|
||||
double d1, d2;
|
||||
matr.at(0,0) = 3;
|
||||
matr.at(0,1) = 6;
|
||||
matr.at(0,2) = 8;
|
||||
matr.at(1,0) = 2;
|
||||
matr.at(1,1) = 1;
|
||||
matr.at(1,2) = 4;
|
||||
matr.at(2,0) = 6;
|
||||
matr.at(2,1) = 2;
|
||||
matr.at(2,2) = 5;
|
||||
matrix2 = matr;
|
||||
matr.invert();
|
||||
d1 = matr.determinant();
|
||||
d2 = matrix2.determinant();
|
||||
matrix3 = matrix1;
|
||||
matrix1.invert();
|
||||
ASSERT_TRUE((matrix1 == matrix3) && (d1 == 1/d2));
|
||||
PIMathMatrixT<rows, cols, double> matrix1;
|
||||
PIMathMatrixT<rows, cols, double> matrix2;
|
||||
PIMathMatrixT<rows, cols, double> matrix3;
|
||||
PIMathMatrixT<rows, cols, double> matr;
|
||||
double d1, d2;
|
||||
matr.element(0,0) = 3;
|
||||
matr.element(0,1) = 6;
|
||||
matr.element(0,2) = 8;
|
||||
matr.element(1,0) = 2;
|
||||
matr.element(1,1) = 1;
|
||||
matr.element(1,2) = 4;
|
||||
matr.element(2,0) = 6;
|
||||
matr.element(2,1) = 2;
|
||||
matr.element(2,2) = 5;
|
||||
matrix2 = matr;
|
||||
matr.invert();
|
||||
d1 = matr.determinant();
|
||||
d2 = matrix2.determinant();
|
||||
matrix3 = matrix1;
|
||||
matrix1.invert();
|
||||
ASSERT_TRUE((matrix1 == matrix3) && (d1 == 1/d2));
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, inverted) {
|
||||
PIMathMatrixT<rows, cols, double> matrix1;
|
||||
PIMathMatrixT<rows, cols, double> matrix2;
|
||||
PIMathMatrixT<rows, cols, double> matrix3;
|
||||
PIMathMatrixT<rows, cols, double> matr;
|
||||
double d1, d2;
|
||||
matrix1 = matr.identity();
|
||||
matr.at(0,0) = 3;
|
||||
matr.at(0,1) = 6;
|
||||
matr.at(0,2) = 8;
|
||||
matr.at(1,0) = 2;
|
||||
matr.at(1,1) = 1;
|
||||
matr.at(1,2) = 4;
|
||||
matr.at(2,0) = 6;
|
||||
matr.at(2,1) = 2;
|
||||
matr.at(2,2) = 5;
|
||||
matrix2 = matr.inverted();
|
||||
d1 = matr.determinant();
|
||||
d2 = matrix2.determinant();
|
||||
matrix3 = matrix1.inverted();
|
||||
ASSERT_TRUE((matrix1 == matrix3) && (round((1/d1)*10000)/10000 == round(d2*10000)/10000));
|
||||
PIMathMatrixT<rows, cols, double> matrix1;
|
||||
PIMathMatrixT<rows, cols, double> matrix2;
|
||||
PIMathMatrixT<rows, cols, double> matrix3;
|
||||
PIMathMatrixT<rows, cols, double> matr;
|
||||
double d1, d2;
|
||||
matrix1 = matr.identity();
|
||||
matr.element(0,0) = 3;
|
||||
matr.element(0,1) = 6;
|
||||
matr.element(0,2) = 8;
|
||||
matr.element(1,0) = 2;
|
||||
matr.element(1,1) = 1;
|
||||
matr.element(1,2) = 4;
|
||||
matr.element(2,0) = 6;
|
||||
matr.element(2,1) = 2;
|
||||
matr.element(2,2) = 5;
|
||||
matrix2 = matr.inverted();
|
||||
d1 = matr.determinant();
|
||||
d2 = matrix2.determinant();
|
||||
matrix3 = matrix1.inverted();
|
||||
ASSERT_TRUE((matrix1 == matrix3) && (round((1/d1)*10000)/10000 == round(d2*10000)/10000));
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, toUpperTriangular) {
|
||||
PIMathMatrixT<rows, cols, double> matrix;
|
||||
double d1, d2 = 1;
|
||||
PIMathMatrixT<rows, cols, double> matr;
|
||||
matr.at(0,0) = 3;
|
||||
matr.at(0,1) = 6;
|
||||
matr.at(0,2) = 8;
|
||||
matr.at(1,0) = 2;
|
||||
matr.at(1,1) = 1;
|
||||
matr.at(1,2) = 4;
|
||||
matr.at(2,0) = 6;
|
||||
matr.at(2,1) = 2;
|
||||
matr.at(2,2) = 5;
|
||||
matrix = matr.toUpperTriangular();
|
||||
d1 = matrix.determinant();
|
||||
for(uint i = 0; i < cols; i++)
|
||||
{
|
||||
d2 = d2*matrix.at(i,i);
|
||||
}
|
||||
ASSERT_DOUBLE_EQ(d1, d2);
|
||||
PIMathMatrixT<rows, cols, double> matrix;
|
||||
double d1, d2 = 1;
|
||||
PIMathMatrixT<rows, cols, double> matr;
|
||||
matr.element(0,0) = 3;
|
||||
matr.element(0,1) = 6;
|
||||
matr.element(0,2) = 8;
|
||||
matr.element(1,0) = 2;
|
||||
matr.element(1,1) = 1;
|
||||
matr.element(1,2) = 4;
|
||||
matr.element(2,0) = 6;
|
||||
matr.element(2,1) = 2;
|
||||
matr.element(2,2) = 5;
|
||||
matrix = matr.toUpperTriangular();
|
||||
d1 = matrix.determinant();
|
||||
for(uint i = 0; i < cols; i++)
|
||||
{
|
||||
d2 = d2*matrix.at(i,i);
|
||||
}
|
||||
ASSERT_DOUBLE_EQ(d1, d2);
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, transposed) {
|
||||
PIMathMatrixT<rows, cols, double> matrix1;
|
||||
PIMathMatrixT<rows, cols, double> matrix2;
|
||||
PIMathMatrixT<rows, cols, double> matr;
|
||||
double d1, d2;
|
||||
matr.at(0,0) = 3;
|
||||
matr.at(0,1) = 6;
|
||||
matr.at(0,2) = 8;
|
||||
matr.at(1,0) = 2;
|
||||
matr.at(1,1) = 1;
|
||||
matr.at(1,2) = 4;
|
||||
matr.at(2,0) = 6;
|
||||
matr.at(2,1) = 2;
|
||||
matr.at(2,2) = 5;
|
||||
d1 = matr.determinant();
|
||||
matrix1 = matr.transposed();
|
||||
d2 = matrix1.determinant();
|
||||
matrix2 = matrix1.transposed();
|
||||
ASSERT_TRUE((d1 == d2) && (matr == matrix2));
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, scaleX_two) {
|
||||
double factor = 5.64;
|
||||
PIMathMatrixT<2u, 2u, double> matrix = PIMathMatrixT<2u, 2u, double>::scaleX(factor);
|
||||
ASSERT_TRUE((1.0 == matrix.at(1u,1u)) && (factor == matrix.at(0u,0u)));
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, scaleY_two) {
|
||||
double factor = 5.64;
|
||||
PIMathMatrixT<2u, 2u, double> matrix = PIMathMatrixT<2u, 2u, double>::scaleY(factor);
|
||||
ASSERT_TRUE((factor == matrix.at(1u,1u)) && (1.0 == matrix.at(0u,0u)));
|
||||
PIMathMatrixT<rows, cols, double> matrix1;
|
||||
PIMathMatrixT<rows, cols, double> matrix2;
|
||||
PIMathMatrixT<rows, cols, double> matr;
|
||||
double d1, d2;
|
||||
matr.element(0,0) = 3;
|
||||
matr.element(0,1) = 6;
|
||||
matr.element(0,2) = 8;
|
||||
matr.element(1,0) = 2;
|
||||
matr.element(1,1) = 1;
|
||||
matr.element(1,2) = 4;
|
||||
matr.element(2,0) = 6;
|
||||
matr.element(2,1) = 2;
|
||||
matr.element(2,2) = 5;
|
||||
d1 = matr.determinant();
|
||||
matrix1 = matr.transposed();
|
||||
d2 = matrix1.determinant();
|
||||
matrix2 = matrix1.transposed();
|
||||
ASSERT_TRUE((d1 == d2) && (matr == matrix2));
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, rotation_2x2) {
|
||||
double angle = 1.0;
|
||||
PIMathMatrixT<2u, 2u, double> matrix = PIMathMatrixT<2u, 2u, double>::rotation(angle);
|
||||
double c = cos(angle);
|
||||
double s = sin(angle);
|
||||
ASSERT_TRUE((c == matrix.at(1u,1u)) && (c == matrix.at(0u,0u)) && (-s == matrix.at(0u,1u)) && (s == matrix.at(1u,0u)));
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, rotation_3x3) {
|
||||
double angle = 1.0;
|
||||
PIMathMatrixT<3u, 3u, double> matrix = PIMathMatrixT<3u, 3u, double>::rotation(angle);
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(matrix, 0.0, rows));
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, rotationX) {
|
||||
double angle = 1.0;
|
||||
double c = cos(angle);
|
||||
double s = sin(angle);
|
||||
PIMathMatrixT<3u, 3u, double> matrix = PIMathMatrixT<3u, 3u, double>::rotationX(angle);
|
||||
ASSERT_TRUE((1.0 == matrix.at(0u,0u)) && (c == matrix.at(1u,1u)) && (c == matrix.at(2u,2u)) && (s == matrix.at(2u,1u)) && (-s == matrix.at(1u,2u)));
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, rotationY) {
|
||||
double angle = 1.0;
|
||||
double c = cos(angle);
|
||||
double s = sin(angle);
|
||||
PIMathMatrixT<3u, 3u, double> matrix = PIMathMatrixT<3u, 3u, double>::rotationY(angle);
|
||||
ASSERT_TRUE((1.0 == matrix.at(1u,1u)) && (c == matrix.at(0u,0u)) && (c == matrix.at(2u,2u)) && (s == matrix.at(0u,2u)) && (-s == matrix.at(2u,0u)));
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, rotationZ) {
|
||||
double angle = 1.0;
|
||||
double c = cos(angle);
|
||||
double s = sin(angle);
|
||||
PIMathMatrixT<3u, 3u, double> matrix = PIMathMatrixT<3u, 3u, double>::rotationZ(angle);
|
||||
ASSERT_TRUE((1.0 == matrix.at(2u,2u)) && (c == matrix.at(0u,0u)) && (c == matrix.at(1u,1u)) && (s == matrix.at(1u,0u)) && (-s == matrix.at(0u,1u)));
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, scaleX_three) {
|
||||
double factor = 23.65;
|
||||
PIMathMatrixT<3u, 3u, double> matrix = PIMathMatrixT<3u, 3u, double>::scaleX(factor);
|
||||
ASSERT_TRUE((1.0 == matrix.at(2u,2u)) && (factor == matrix.at(0u,0u)) && (1.0 == matrix.at(1u,1u)));
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, scaleY_three) {
|
||||
double factor = 23.65;
|
||||
PIMathMatrixT<3u, 3u, double> matrix = PIMathMatrixT<3u, 3u, double>::scaleY(factor);
|
||||
ASSERT_TRUE((1.0 == matrix.at(2u,2u)) && (1.0 == matrix.at(0u,0u)) && (factor == matrix.at(1u,1u)));
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, scaleZ_three) {
|
||||
double factor = 23.65;
|
||||
PIMathMatrixT<3u, 3u, double> matrix = PIMathMatrixT<3u, 3u, double>::scaleZ(factor);
|
||||
ASSERT_TRUE((factor == matrix.at(2u,2u)) && (1.0 == matrix.at(0u,0u)) && (1.0 == matrix.at(1u,1u)));
|
||||
double angle = 1.0;
|
||||
auto matrix = PIMathMatrixT<2u, 2u, double>::identity();
|
||||
matrix.rotate(angle);
|
||||
double c = cos(angle);
|
||||
double s = sin(angle);
|
||||
ASSERT_TRUE((c == matrix.at(1u,1u)) && (c == matrix.at(0u,0u)) && (-s == matrix.at(0u,1u)) && (s == matrix.at(1u,0u)));
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, matrixMultiplication)
|
||||
{
|
||||
auto matrix1 = PIMathMatrixT<rows, cols, double>::filled(1.5);
|
||||
auto matrix2 = PIMathMatrixT<rows, cols, double>::filled(2.5);
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1 * matrix2, 11.25, 3));
|
||||
auto matrix1 = PIMathMatrixT<rows, cols, double>(1.5);
|
||||
auto matrix2 = PIMathMatrixT<rows, cols, double>(2.5);
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1 * matrix2, 11.25, 3));
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, matrixAndVectorMultiplication) {
|
||||
auto matrix1 = PIMathMatrixT<rows, cols, double>::filled(1.5);
|
||||
auto vector = PIMathVectorT<rows, double>::filled(2.5);
|
||||
for(uint i = 0; i < 2; i++) {
|
||||
if((matrix1 * vector)[i] != 11.25) {
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
ASSERT_TRUE(true);
|
||||
auto matrix1 = PIMathMatrixT<rows, cols, double>(1.5);
|
||||
auto vector = PIMathVectorT<rows, double>(2.5);
|
||||
for(uint i = 0; i < 2; i++) {
|
||||
if((matrix1 * vector)[i] != 11.25) {
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
ASSERT_TRUE(true);
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, vectorAndMatrixMultiplication) {
|
||||
auto matrix1 = PIMathMatrixT<rows, cols, double>::filled(1.5);
|
||||
auto vector = PIMathVectorT<rows, double>::filled(2.5);
|
||||
for(uint i = 0; i < 2; i++) {
|
||||
if((vector * matrix1)[i] != 11.25) {
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
auto matrix1 = PIMathMatrixT<rows, cols, double>(1.5);
|
||||
auto vector = PIMathVectorT<rows, double>(2.5);
|
||||
for(uint i = 0; i < 2; i++) {
|
||||
if((vector * matrix1)[i] != 11.25) {
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, valAndMatrixMultiplication) {
|
||||
auto matrix1 = PIMathMatrixT<rows, cols, double>::filled(1.5);
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(25.0*matrix1, 37.5, 3));
|
||||
auto matrix1 = PIMathMatrixT<rows, cols, double>(1.5);
|
||||
ASSERT_TRUE(cmpSquareMatrixWithValue(25.0*matrix1, 37.5, 3));
|
||||
}
|
||||
|
||||
84
tests/math/testpivector2d.cpp
Normal file
84
tests/math/testpivector2d.cpp
Normal file
@@ -0,0 +1,84 @@
|
||||
#include "gtest/gtest.h"
|
||||
#include "pivector2d.h"
|
||||
|
||||
int ROWS_COUNT_INIT = 31;
|
||||
int ROWS_COUNT_INCREASE = 41;
|
||||
int ROWS_COUNT_REDUCE = 22;
|
||||
|
||||
int COLS_COUNT_INIT = 34;
|
||||
int COLS_COUNT_INCREASE = 44;
|
||||
int COLS_COUNT_REDUCE = 13;
|
||||
|
||||
void assert_fill_with(PIVector2D<int> vec, int rows, int cols) {
|
||||
for(int r = 0; r < rows; r++) {
|
||||
for(int c = 0; c < cols; c++) {
|
||||
ASSERT_EQ(vec.element(r, c), r * COLS_COUNT_INIT + c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Vector2D : public ::testing::Test {
|
||||
protected:
|
||||
PIVector2D<int> vec = PIVector2D<int>(ROWS_COUNT_INIT, COLS_COUNT_INIT);
|
||||
|
||||
void SetUp() override {
|
||||
for (int r = 0; r < ROWS_COUNT_INIT; ++r) {
|
||||
for (int c = 0; c < COLS_COUNT_INIT; ++c) {
|
||||
vec.element(r, c) = r * COLS_COUNT_INIT + c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void resize_reduce_is_data_stay_consistent(int newRowsCount, int newColsCount) {
|
||||
vec.resize(newRowsCount, newColsCount, 0);
|
||||
assert_fill_with(vec, newRowsCount, newColsCount);
|
||||
}
|
||||
|
||||
void resize_increase_is_data_stay_consistent(int newRowsCount, int newColsCount) {
|
||||
vec.resize(newRowsCount, newColsCount, 0);
|
||||
assert_fill_with(vec, ROWS_COUNT_INIT, COLS_COUNT_INIT);
|
||||
|
||||
for (int r = 0; r < newRowsCount; ++r) {
|
||||
for (int c = 0; c < newColsCount; ++c) {
|
||||
if (r < ROWS_COUNT_INIT || c < COLS_COUNT_INIT) continue;
|
||||
ASSERT_EQ(vec.element(r, c), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(Vector2D, resize_is_increase_col_count) {
|
||||
vec.resize(ROWS_COUNT_INIT, COLS_COUNT_INCREASE, 0);
|
||||
ASSERT_EQ(vec.cols(), COLS_COUNT_INCREASE);
|
||||
}
|
||||
|
||||
TEST_F(Vector2D, resize_is_reduce_col_count) {
|
||||
vec.resize(ROWS_COUNT_INIT, COLS_COUNT_REDUCE, 0);
|
||||
ASSERT_EQ(vec.cols(), COLS_COUNT_REDUCE);
|
||||
}
|
||||
|
||||
TEST_F(Vector2D, resize_is_increase_rows_count) {
|
||||
vec.resize(ROWS_COUNT_INCREASE, COLS_COUNT_INIT, 0);
|
||||
ASSERT_EQ(vec.rows(), ROWS_COUNT_INCREASE);
|
||||
}
|
||||
|
||||
TEST_F(Vector2D, resize_is_reduce_rows_count) {
|
||||
vec.resize(ROWS_COUNT_REDUCE, COLS_COUNT_INIT, 0);
|
||||
ASSERT_EQ(vec.rows(), ROWS_COUNT_REDUCE);
|
||||
}
|
||||
|
||||
TEST_F(Vector2D, resize_increase_both_is_data_stay_consistent) {
|
||||
resize_increase_is_data_stay_consistent(ROWS_COUNT_INCREASE, COLS_COUNT_INCREASE);
|
||||
}
|
||||
|
||||
TEST_F(Vector2D, resize_reduce_cols_is_data_stay_consistent) {
|
||||
resize_reduce_is_data_stay_consistent(ROWS_COUNT_INIT, COLS_COUNT_REDUCE);
|
||||
}
|
||||
|
||||
TEST_F(Vector2D, resize_reduce_rows_is_data_stay_consistent) {
|
||||
resize_reduce_is_data_stay_consistent(ROWS_COUNT_REDUCE, COLS_COUNT_INIT);
|
||||
}
|
||||
|
||||
TEST_F(Vector2D, resize_reduce_both_is_data_stay_consistent) {
|
||||
resize_reduce_is_data_stay_consistent(ROWS_COUNT_REDUCE, COLS_COUNT_REDUCE);
|
||||
}
|
||||
2
tests/suppr.txt
Normal file
2
tests/suppr.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
leak:ConditionVariable::SetUp
|
||||
leak:ConditionLock_
|
||||
@@ -325,7 +325,7 @@ void makeGetterValue(PIFile & f, const PICodeParser::Entity * e) {
|
||||
piForeachC (PICodeParser::Member & m, e->members) {
|
||||
if (m.is_type_ptr || m.isBitfield() || !m.dims.isEmpty() || (m.visibility != PICodeParser::Public))
|
||||
continue;
|
||||
f << "\tif (strcmp(name, \"" << m.name << "\") == 0) {ret << o->" << m.name << "; return ret;}\n";
|
||||
f << "\tif (strcmp(name, \"" << m.name << "\") == 0) {serialize(ret, o->" << m.name << "); return ret;}\n";
|
||||
}
|
||||
f << "\treturn ret;\n}\n";
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ void usage() {
|
||||
"[-p <qt_plugins>] [-s <search_path>] [--ignore <libs>] [-S <styles>] "
|
||||
"[-l <ldd>] [-D <dpkg>] [--dpkg-workdir <d>] [-L <readelf> | -W <objdump> | -M <otool>] "
|
||||
"[--name-tool <pathS>] [-d <depth>] [-q <qtdir>] [-a <add_libs>] [-S <styles>] "
|
||||
"[-P <platforms>] [--qt-plugins <d>] -o <out_path> <file> [<file2> ...]\"" << NewLine;
|
||||
"[-P <platforms>] [--qt-plugins <d>] [--qt-modules <l>] -o <out_path> <file> [<file2> ...]\"" << NewLine;
|
||||
piCout << Green << Bold << "Details:";
|
||||
piCout << Bold << "Debug control";
|
||||
piCout << "-h, --help " << Green << "- display this message and exit";
|
||||
@@ -92,10 +92,11 @@ void usage() {
|
||||
piCout << "-S <styles> " << Green << "- set Qt styles (e.g. \"oxygen,breeze\"), default \"*\"";
|
||||
piCout << "-P <platforms> " << Green << "- set Qt platforms (e.g. \"win,mini\"), default by host system";
|
||||
piCout << "--qt-plugins <d> " << Green << "- set Qt plugins description";
|
||||
piCout << "--qt-modules <list>" << Green << "- additional Qt modules, may be separated by \"" DELIM "\" (e.g. \"Sql" DELIM "Xml\")";
|
||||
piCout << "";
|
||||
piCout << Bold << "Output control";
|
||||
piCout << "-o <out_path> " << Green << "- path for libraries copy to";
|
||||
piCout << "-p <qt_plugins> " << Green << "- path for Qt plugins, default \"<out_path>/plugins\"";
|
||||
piCout << "-p <qt_plugins> " << Green << "- path for Qt plugins, default \"<out_path>\"";
|
||||
piCout << "--dependencies " << Green << "- search dependencies by <dpkg>, print them and copy missing libraries";
|
||||
piCout << "--prefix <text> " << Green << "- print <text> before dependencies";
|
||||
piCout << "";
|
||||
@@ -127,9 +128,10 @@ QtDep qt_deps[] = {
|
||||
|
||||
|
||||
int depth = 8;
|
||||
bool fake = false, is_ldd = true, is_deps = false, need_qt = false;
|
||||
bool fake = false, is_ldd = true, is_deps = false, need_qt = false, make_qt_format = true;
|
||||
PIString ldd, readelf, objdump, otool, dpkg, nametool, strip, out_dir, qt_dir, out_plugins_dir, dpkg_workdir;
|
||||
PIStringList styles, lib_dirs, add_libs, platforms, sqldrivers, input_files, plugin_libs;
|
||||
PIString qt_pref, qt_suff;
|
||||
PIStringList styles, lib_dirs, add_libs, platforms, sqldrivers, input_files, plugin_libs, qt_add_libs;
|
||||
PISet<PIString> all_libs, miss_libs, all_deps, frameworks, framework_libs, miss_frameworks, qt_plugins, ignore_libs;
|
||||
PIMap<PIString, PIStringList> qt_filters;
|
||||
|
||||
@@ -181,17 +183,22 @@ PIString execute(const PIString & cmd) {
|
||||
|
||||
|
||||
void checkQtLib(PIString lib) {
|
||||
if (lib.startsWith("lib")) lib.cutLeft(3);
|
||||
if (lib.startsWith("qt5")) lib.cutLeft(3);
|
||||
if (lib.startsWith("qt")) lib.cutLeft(2);
|
||||
if (lib.find(".")) lib = lib.left(lib.find("."));
|
||||
//piCout << "checkQt" << lib;
|
||||
PIString pref, suff;
|
||||
if (lib.startsWith("lib")) {pref += "lib"; lib.cutLeft(3);}
|
||||
if (lib.startsWith("qt5")) {pref += "Qt5"; lib.cutLeft(3);}
|
||||
if (lib.startsWith("qt" )) {pref += "Qt" ; lib.cutLeft(2);}
|
||||
if (lib.find('.') >= 0) {suff = lib.right(lib.size_s() - lib.find('.')); lib = lib.left(lib.find('.'));}
|
||||
for (int i = 0; ; ++i) {
|
||||
if (qt_deps[i].lib.isEmpty()) break;
|
||||
if (qt_deps[i].lib == lib) {
|
||||
qt_plugins << qt_deps[i].plugins;
|
||||
//piCout << "add qt plugins" << qt_deps[i].plugins << "now" << qt_plugins;
|
||||
need_qt = true;
|
||||
if (make_qt_format) {
|
||||
make_qt_format = false;
|
||||
qt_pref = pref;
|
||||
qt_suff = suff;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -484,6 +491,7 @@ int main(int argc, char * argv[]) {
|
||||
cli.addArgument("Styles", true);
|
||||
cli.addArgument("Platforms", true);
|
||||
cli.addArgument("qt-plugins", PIChar('\0'), true);
|
||||
cli.addArgument("qt-modules", PIChar('\0'), true);
|
||||
cli.addArgument("ldd", true);
|
||||
cli.addArgument("Lreadelf", true);
|
||||
cli.addArgument("Wobjdump", true);
|
||||
@@ -590,6 +598,9 @@ int main(int argc, char * argv[]) {
|
||||
qt_filters["platforms"] = platforms;
|
||||
qt_filters["styles" ] = styles ;
|
||||
|
||||
qt_add_libs = cli.argumentValue("qt-modules").split(DELIM);
|
||||
need_qt = !qt_add_libs.isEmpty();
|
||||
|
||||
auto it = qt_filters.makeIterator();
|
||||
while (it.next())
|
||||
it.valueRef().forEachInplace([](PIString i)->PIString{
|
||||
@@ -616,8 +627,15 @@ int main(int argc, char * argv[]) {
|
||||
}
|
||||
});
|
||||
//piCout << files;
|
||||
if (depth > 0)
|
||||
if (depth > 0) {
|
||||
input_files.forEach([&](const PIString & f){procLdd(f);});
|
||||
qt_add_libs.forEach([&](const PIString & f){
|
||||
PIString l = findLib(qt_pref + f + qt_suff);
|
||||
if (l.isEmpty()) return;
|
||||
procLdd(l, true);
|
||||
checkQtLib(f.toLowerCase());
|
||||
});
|
||||
}
|
||||
piForeach (PIString & s, add_libs) {
|
||||
if (s.isEmpty()) continue;
|
||||
PIString alib = findLib(s);
|
||||
|
||||
Reference in New Issue
Block a user