1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2025-01-18 19:47:15 +01:00

Migrated the host module to C++ exceptions as well.

Also enabled the latest C++ revision in the project.
Replaced the Random library with the one provided by C++11.
Implemented a simple AES256 encryption class.
Various other fixes and improvements.
This commit is contained in:
Sandu Liviu Catalin 2016-03-10 05:57:13 +02:00
parent 3162221e7f
commit 70e5f0ba21
124 changed files with 14873 additions and 14062 deletions

407
cbp/ModMMDB.cbp Normal file
View File

@ -0,0 +1,407 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<CodeBlocks_project_file>
<FileVersion major="1" minor="6" />
<Project>
<Option title="Mod MMDB" />
<Option pch_mode="2" />
<Option compiler="gcc" />
<Build>
<Target title="Win32 Debug Dynamic">
<Option output="../bin/win32-d/mod_mmdb32" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="0" extension_auto="1" />
<Option working_dir="../bin/win32-d/" />
<Option object_output="../obj/mingw32-d/" />
<Option type="3" />
<Option compiler="gcc" />
<Compiler>
<Add option="-m32" />
<Add option="-g" />
<Add option="-D_DEBUG" />
<Add directory="../config/mingw32" />
</Compiler>
<Linker>
<Add option="-m32" />
<Add library="Ws2_32" />
<Add directory="../lib/mingw32-d" />
</Linker>
<ExtraCommands>
<Add after='cmd /c copy /Y &quot;$(PROJECT_DIR)$(TARGET_OUTPUT_FILE)&quot; &quot;$(PROJECT_DIR)..\bin\plugins\$(TARGET_OUTPUT_BASENAME).dll&quot;' />
</ExtraCommands>
</Target>
<Target title="Win32 Release Dynamic">
<Option output="../bin/win32/mod_mmdb32" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="0" extension_auto="1" />
<Option working_dir="../bin/win32/" />
<Option object_output="../obj/mingw32/" />
<Option type="3" />
<Option compiler="gcc" />
<Compiler>
<Add option="-O3" />
<Add option="-m32" />
<Add option="-DNDEBUG" />
<Add directory="../config/mingw32" />
</Compiler>
<Linker>
<Add option="-s" />
<Add option="-m32" />
<Add library="Ws2_32" />
<Add directory="../lib/mingw32" />
</Linker>
<ExtraCommands>
<Add after='cmd /c copy /Y &quot;$(PROJECT_DIR)$(TARGET_OUTPUT_FILE)&quot; &quot;$(PROJECT_DIR)..\bin\plugins\$(TARGET_OUTPUT_BASENAME).dll&quot;' />
</ExtraCommands>
</Target>
<Target title="Win64 Debug Dynamic">
<Option output="../bin/win64-d/mod_mmdb64" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="0" extension_auto="1" />
<Option working_dir="../bin/win64-d/" />
<Option object_output="../obj/mingw64-d/" />
<Option type="3" />
<Option compiler="gcc" />
<Compiler>
<Add option="-m64" />
<Add option="-g" />
<Add option="-D_DEBUG" />
<Add option="-D_SQ64" />
<Add directory="../config/mingw64" />
</Compiler>
<Linker>
<Add option="-m64" />
<Add library="Ws2_32" />
<Add directory="../lib/mingw64-d" />
</Linker>
<ExtraCommands>
<Add after='cmd /c copy /Y &quot;$(PROJECT_DIR)$(TARGET_OUTPUT_FILE)&quot; &quot;$(PROJECT_DIR)..\bin\plugins\$(TARGET_OUTPUT_BASENAME).dll&quot;' />
</ExtraCommands>
</Target>
<Target title="Win64 Release Dynamic">
<Option output="../bin/win64/mod_mmdb64" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="0" extension_auto="1" />
<Option working_dir="../bin/win64/" />
<Option object_output="../obj/mingw64/" />
<Option type="3" />
<Option compiler="gcc" />
<Compiler>
<Add option="-O3" />
<Add option="-m64" />
<Add option="-DNDEBUG" />
<Add option="-D_SQ64" />
<Add directory="../config/mingw64" />
</Compiler>
<Linker>
<Add option="-s" />
<Add option="-m64" />
<Add library="Ws2_32" />
<Add directory="../lib/mingw64" />
</Linker>
<ExtraCommands>
<Add after='cmd /c copy /Y &quot;$(PROJECT_DIR)$(TARGET_OUTPUT_FILE)&quot; &quot;$(PROJECT_DIR)..\bin\plugins\$(TARGET_OUTPUT_BASENAME).dll&quot;' />
</ExtraCommands>
</Target>
<Target title="Linux32 Debug Dynamic">
<Option output="../bin/linux32-d/mod_mmdb32" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="0" extension_auto="1" />
<Option working_dir="../bin/linux32-d/" />
<Option object_output="../obj/gcc32-d/" />
<Option type="3" />
<Option compiler="gcc" />
<Compiler>
<Add option="-m32" />
<Add option="-g" />
<Add option="-fPIC" />
<Add option="-D_DEBUG" />
<Add directory="../config/gcc32" />
</Compiler>
<Linker>
<Add option="-m32" />
<Add directory="../lib/gcc32-d" />
</Linker>
</Target>
<Target title="Linux32 Release Dynamic">
<Option output="../bin/linux32/mod_mmdb32" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="0" extension_auto="1" />
<Option working_dir="../bin/linux32/" />
<Option object_output="../obj/gcc32/" />
<Option type="3" />
<Option compiler="gcc" />
<Compiler>
<Add option="-O3" />
<Add option="-m32" />
<Add option="-fPIC" />
<Add option="-DNDEBUG" />
<Add directory="../config/gcc32" />
</Compiler>
<Linker>
<Add option="-s" />
<Add option="-m32" />
<Add directory="../lib/gcc32" />
</Linker>
</Target>
<Target title="Linux64 Debug Dynamic">
<Option output="../bin/linux64-d/mod_mmdb64" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="0" extension_auto="1" />
<Option working_dir="../bin/linux64-d/" />
<Option object_output="../obj/gcc64-d/" />
<Option type="3" />
<Option compiler="gcc" />
<Compiler>
<Add option="-m64" />
<Add option="-g" />
<Add option="-fPIC" />
<Add option="-D_DEBUG" />
<Add option="-D_SQ64" />
<Add directory="../config/gcc64" />
</Compiler>
<Linker>
<Add option="-m64" />
<Add directory="../lib/gcc64-d" />
</Linker>
</Target>
<Target title="Linux64 Release Dynamic">
<Option output="../bin/linux64/mod_mmdb64" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="0" extension_auto="1" />
<Option working_dir="../bin/linux64/" />
<Option object_output="../obj/gcc64/" />
<Option type="3" />
<Option compiler="gcc" />
<Compiler>
<Add option="-O3" />
<Add option="-m64" />
<Add option="-fPIC" />
<Add option="-DNDEBUG" />
<Add option="-D_SQ64" />
<Add directory="../config/gcc64" />
</Compiler>
<Linker>
<Add option="-s" />
<Add option="-m64" />
<Add directory="../lib/gcc64" />
</Linker>
</Target>
<Target title="Win32 Debug Standalone">
<Option output="../bin/win32-d/mod_mmdb32" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="0" extension_auto="1" />
<Option working_dir="../bin/win32-d/" />
<Option object_output="../obj/mingw32-d/" />
<Option type="3" />
<Option compiler="gcc" />
<Compiler>
<Add option="-m32" />
<Add option="-g" />
<Add option="-static-libgcc" />
<Add option="-static-libstdc++" />
<Add option="-enable-static" />
<Add option="-D_DEBUG" />
<Add directory="../config/mingw32" />
</Compiler>
<Linker>
<Add option="-m32" />
<Add option="-static" />
<Add library="Ws2_32" />
<Add directory="../lib/mingw32-d" />
</Linker>
<ExtraCommands>
<Add after='cmd /c copy /Y &quot;$(PROJECT_DIR)$(TARGET_OUTPUT_FILE)&quot; &quot;$(PROJECT_DIR)..\bin\plugins\$(TARGET_OUTPUT_BASENAME).dll&quot;' />
</ExtraCommands>
</Target>
<Target title="Win32 Release Standalone">
<Option output="../bin/win32/mod_mmdb32" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="0" extension_auto="1" />
<Option working_dir="../bin/win32/" />
<Option object_output="../obj/mingw32/" />
<Option type="3" />
<Option compiler="gcc" />
<Compiler>
<Add option="-O3" />
<Add option="-m32" />
<Add option="-static-libgcc" />
<Add option="-static-libstdc++" />
<Add option="-enable-static" />
<Add option="-DNDEBUG" />
<Add directory="../config/mingw32" />
</Compiler>
<Linker>
<Add option="-s" />
<Add option="-m32" />
<Add option="-static" />
<Add library="Ws2_32" />
<Add directory="../lib/mingw32" />
</Linker>
<ExtraCommands>
<Add after='cmd /c copy /Y &quot;$(PROJECT_DIR)$(TARGET_OUTPUT_FILE)&quot; &quot;$(PROJECT_DIR)..\bin\plugins\$(TARGET_OUTPUT_BASENAME).dll&quot;' />
</ExtraCommands>
</Target>
<Target title="Win64 Debug Standalone">
<Option output="../bin/win64-d/mod_mmdb64" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="0" extension_auto="1" />
<Option working_dir="../bin/win64-d/" />
<Option object_output="../obj/mingw64-d/" />
<Option type="3" />
<Option compiler="gcc" />
<Compiler>
<Add option="-m64" />
<Add option="-g" />
<Add option="-static-libgcc" />
<Add option="-static-libstdc++" />
<Add option="-enable-static" />
<Add option="-D_DEBUG" />
<Add option="-D_SQ64" />
<Add directory="../config/mingw64" />
</Compiler>
<Linker>
<Add option="-m64" />
<Add option="-static" />
<Add library="Ws2_32" />
<Add directory="../lib/mingw64-d" />
</Linker>
<ExtraCommands>
<Add after='cmd /c copy /Y &quot;$(PROJECT_DIR)$(TARGET_OUTPUT_FILE)&quot; &quot;$(PROJECT_DIR)..\bin\plugins\$(TARGET_OUTPUT_BASENAME).dll&quot;' />
</ExtraCommands>
</Target>
<Target title="Win64 Release Standalone">
<Option output="../bin/win64/mod_mmdb64" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="0" extension_auto="1" />
<Option working_dir="../bin/win64/" />
<Option object_output="../obj/mingw64/" />
<Option type="3" />
<Option compiler="gcc" />
<Compiler>
<Add option="-O3" />
<Add option="-m64" />
<Add option="-static-libgcc" />
<Add option="-static-libstdc++" />
<Add option="-enable-static" />
<Add option="-DNDEBUG" />
<Add option="-D_SQ64" />
<Add directory="../config/mingw64" />
</Compiler>
<Linker>
<Add option="-s" />
<Add option="-m64" />
<Add option="-static" />
<Add library="Ws2_32" />
<Add directory="../lib/mingw64" />
</Linker>
<ExtraCommands>
<Add after='cmd /c copy /Y &quot;$(PROJECT_DIR)$(TARGET_OUTPUT_FILE)&quot; &quot;$(PROJECT_DIR)..\bin\plugins\$(TARGET_OUTPUT_BASENAME).dll&quot;' />
</ExtraCommands>
</Target>
<Target title="Linux32 Debug Standalone">
<Option output="../bin/linux32-d/mod_mmdb32" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="0" extension_auto="1" />
<Option working_dir="../bin/linux32-d/" />
<Option object_output="../obj/gcc32-d/" />
<Option type="3" />
<Option compiler="gcc" />
<Compiler>
<Add option="-m32" />
<Add option="-g" />
<Add option="-static-libgcc" />
<Add option="-static-libstdc++" />
<Add option="-enable-static" />
<Add option="-fPIC" />
<Add option="-D_DEBUG" />
<Add directory="../config/gcc32" />
</Compiler>
<Linker>
<Add option="-m32" />
<Add option="-Bstatic" />
<Add directory="../lib/gcc32-d" />
</Linker>
</Target>
<Target title="Linux32 Release Standalone">
<Option output="../bin/linux32/mod_mmdb32" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="0" extension_auto="1" />
<Option working_dir="../bin/linux32/" />
<Option object_output="../obj/gcc32/" />
<Option type="3" />
<Option compiler="gcc" />
<Compiler>
<Add option="-O3" />
<Add option="-m32" />
<Add option="-static-libgcc" />
<Add option="-static-libstdc++" />
<Add option="-enable-static" />
<Add option="-fPIC" />
<Add option="-DNDEBUG" />
<Add directory="../config/gcc32" />
</Compiler>
<Linker>
<Add option="-s" />
<Add option="-m32" />
<Add option="-Bstatic" />
<Add directory="../lib/gcc32" />
</Linker>
</Target>
<Target title="Linux64 Debug Standalone">
<Option output="../bin/linux64-d/mod_mmdb64" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="0" extension_auto="1" />
<Option working_dir="../bin/linux64-d/" />
<Option object_output="../obj/gcc64-d/" />
<Option type="3" />
<Option compiler="gcc" />
<Compiler>
<Add option="-m64" />
<Add option="-g" />
<Add option="-static-libgcc" />
<Add option="-static-libstdc++" />
<Add option="-enable-static" />
<Add option="-fPIC" />
<Add option="-D_DEBUG" />
<Add option="-D_SQ64" />
<Add directory="../config/gcc64" />
</Compiler>
<Linker>
<Add option="-m64" />
<Add option="-Bstatic" />
<Add directory="../lib/gcc64-d" />
</Linker>
</Target>
<Target title="Linux64 Release Standalone">
<Option output="../bin/linux64/mod_mmdb64" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="0" extension_auto="1" />
<Option working_dir="../bin/linux64/" />
<Option object_output="../obj/gcc64/" />
<Option type="3" />
<Option compiler="gcc" />
<Compiler>
<Add option="-O3" />
<Add option="-m64" />
<Add option="-static-libgcc" />
<Add option="-static-libstdc++" />
<Add option="-enable-static" />
<Add option="-fPIC" />
<Add option="-DNDEBUG" />
<Add option="-D_SQ64" />
<Add directory="../config/gcc64" />
</Compiler>
<Linker>
<Add option="-s" />
<Add option="-m64" />
<Add option="-Bstatic" />
<Add directory="../lib/gcc64" />
</Linker>
</Target>
</Build>
<Compiler>
<Add option="-Wextra" />
<Add option="-Wall" />
<Add option="-std=c++14" />
<Add option="-DSQMOD_PLUGIN_API" />
<Add option="-DSCRAT_USE_EXCEPTIONS" />
<Add option="-DSCRAT_USE_CXX11_OPTIMIZATIONS" />
<Add directory="../modules/mmdb" />
<Add directory="../shared" />
<Add directory="../include" />
<Add directory="../config/common" />
<Add directory="../external/MaxmindDB" />
</Compiler>
<Unit filename="../external/MaxmindDB/maxminddb.c">
<Option compilerVar="CC" />
<Option compiler="gcc" use="1" buildCommand="$compiler -Wno-unused-parameter -Wno-sign-compare $options $includes -c $file -o $object" />
</Unit>
<Unit filename="../modules/mmdb/Common.cpp" />
<Unit filename="../modules/mmdb/Common.hpp" />
<Unit filename="../modules/mmdb/Database.cpp" />
<Unit filename="../modules/mmdb/Database.hpp" />
<Unit filename="../modules/mmdb/EntryDataList.cpp" />
<Unit filename="../modules/mmdb/EntryDataList.hpp" />
<Unit filename="../modules/mmdb/LookupResult.cpp" />
<Unit filename="../modules/mmdb/LookupResult.hpp" />
<Unit filename="../modules/mmdb/Module.cpp" />
<Unit filename="../modules/mmdb/Module.hpp" />
<Unit filename="../modules/mmdb/SockAddr.cpp" />
<Unit filename="../modules/mmdb/SockAddr.hpp" />
<Unit filename="../shared/SqMod.cpp" />
<Extensions>
<code_completion />
<envvars />
<debugger />
<lib_finder disable_auto="1" />
</Extensions>
</Project>
</CodeBlocks_project_file>

View File

@ -362,6 +362,9 @@
<Compiler>
<Add option="-Wextra" />
<Add option="-Wall" />
<Add option="-std=c++14" />
<Add option="-DSCRAT_USE_EXCEPTIONS" />
<Add option="-DSCRAT_USE_CXX11_OPTIMIZATIONS" />
<Add directory="../source" />
<Add directory="../shared" />
<Add directory="../include" />
@ -372,6 +375,7 @@
<Linker>
<Add library="squirrel" />
</Linker>
<Unit filename="../external/Common/aes256.cpp" />
<Unit filename="../external/Hash/crc32.cpp" />
<Unit filename="../external/Hash/crc32.h" />
<Unit filename="../external/Hash/digest.cpp" />
@ -387,7 +391,6 @@
<Unit filename="../external/Hash/sha256.h" />
<Unit filename="../external/Hash/sha3.cpp" />
<Unit filename="../external/Hash/sha3.h" />
<Unit filename="../external/RandomLib/Random.cpp" />
<Unit filename="../source/Base/AABB.cpp" />
<Unit filename="../source/Base/AABB.hpp" />
<Unit filename="../source/Base/Buffer.cpp" />
@ -438,14 +441,14 @@
<Unit filename="../source/Entity/Vehicle.cpp" />
<Unit filename="../source/Entity/Vehicle.hpp" />
<Unit filename="../source/Exports.cpp" />
<Unit filename="../source/Library/Crypt.cpp" />
<Unit filename="../source/Library/Crypt.hpp" />
<Unit filename="../source/Library/Datetime.cpp" />
<Unit filename="../source/Library/Datetime.hpp" />
<Unit filename="../source/Library/FileIO.cpp" />
<Unit filename="../source/Library/FileIO.hpp" />
<Unit filename="../source/Library/Format.cpp" />
<Unit filename="../source/Library/Format.hpp" />
<Unit filename="../source/Library/Hashing.cpp" />
<Unit filename="../source/Library/Hashing.hpp" />
<Unit filename="../source/Library/Math.cpp" />
<Unit filename="../source/Library/Math.hpp" />
<Unit filename="../source/Library/Numeric.cpp" />

View File

@ -149,6 +149,7 @@
</Build>
<Compiler>
<Add option="-Wall" />
<Add option="-std=c++14" />
<Add directory="../include" />
<Add directory="../sandbox" />
<Add directory="../source" />
@ -160,6 +161,7 @@
<Linker>
<Add library="squirrel" />
</Linker>
<Unit filename="../external/Common/aes256.cpp" />
<Unit filename="../sandbox/main.cpp" />
<Extensions>
<code_completion />

View File

@ -8,6 +8,7 @@
<Project filename="ModIRC.cbp" />
<Project filename="ModXML.cbp" />
<Project filename="ModSQLite.cbp" />
<Project filename="ModMMDB.cbp" />
<Project filename="ModSample.cbp" />
</Workspace>
</CodeBlocks_workspace_file>

View File

@ -0,0 +1,193 @@
/* include/maxminddb_config.h. Generated from maxminddb_config.h.in by configure. */
#ifndef MAXMINDDB_CONFIG_H
#define MAXMINDDB_CONFIG_H
/* Define to 1 if you have the <arpa/inet.h> header file. */
#define HAVE_ARPA_INET_H 1
/* Define to 1 if you have the <assert.h> header file. */
#define HAVE_ASSERT_H 1
/* Define to 1 if the system has the type `boolean'. */
/* #undef HAVE_BOOLEAN */
/* Define to 1 if you have the <dlfcn.h> header file. */
#define HAVE_DLFCN_H 1
/* Define to 1 if you have the <fcntl.h> header file. */
#define HAVE_FCNTL_H 1
/* Define to 1 if you have the `getpagesize' function. */
#define HAVE_GETPAGESIZE 1
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define to 1 if you have the <libgen.h> header file. */
#define HAVE_LIBGEN_H 1
/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
to 0 otherwise. */
#define HAVE_MALLOC 1
/* Define to 1 if you have the <math.h> header file. */
#define HAVE_MATH_H 1
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define to 1 if you have a working `mmap' system call. */
#define HAVE_MMAP 1
/* Define to 1 if you have the <netdb.h> header file. */
#define HAVE_NETDB_H 1
/* Define to 1 if you have the <netinet/in.h> header file. */
#define HAVE_NETINET_IN_H 1
/* Has an open_memstream() function */
#define HAVE_OPEN_MEMSTREAM 1
/* Define to 1 if you have the <stdarg.h> header file. */
#define HAVE_STDARG_H 1
/* Define to 1 if you have the <stdbool.h> header file. */
#define HAVE_STDBOOL_H 1
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdio.h> header file. */
#define HAVE_STDIO_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the <sys/mman.h> header file. */
#define HAVE_SYS_MMAN_H 1
/* Define to 1 if you have the <sys/param.h> header file. */
#define HAVE_SYS_PARAM_H 1
/* Define to 1 if you have the <sys/socket.h> header file. */
#define HAVE_SYS_SOCKET_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/time.h> header file. */
#define HAVE_SYS_TIME_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#define LT_OBJDIR ".libs/"
/* Missing the unsigned __int128 type */
#define MMDB_UINT128_IS_BYTE_ARRAY 1
/* int128 types are available with __attribute__((mode(TI))) */
/* #undef MMDB_UINT128_USING_MODE */
/* Name of package */
#define PACKAGE "libmaxminddb"
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "support@maxmind.com"
/* Define to the full name of this package. */
#define PACKAGE_NAME "libmaxminddb"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "libmaxminddb 1.1.4"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "libmaxminddb"
/* Define to the home page for this package. */
#define PACKAGE_URL ""
/* Define to the version of this package. */
#define PACKAGE_VERSION "1.1.4"
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Version number of package */
#define VERSION "1.1.4"
/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
#define below would cause a syntax error. */
/* #undef _UINT32_T */
/* Define for Solaris 2.5.1 so the uint64_t typedef from <sys/synch.h>,
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
#define below would cause a syntax error. */
/* #undef _UINT64_T */
/* Define for Solaris 2.5.1 so the uint8_t typedef from <sys/synch.h>,
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
#define below would cause a syntax error. */
/* #undef _UINT8_T */
/* Define to rpl_malloc if the replacement function should be used. */
/* #undef malloc */
/* Define to `long int' if <sys/types.h> does not define. */
/* #undef off_t */
/* Define to the equivalent of the C99 'restrict' keyword, or to
nothing if this is not supported. Do not define if restrict is
supported directly. */
#define restrict __restrict
/* Work around a bug in Sun C++: it does not support _Restrict or
__restrict__, even though the corresponding Sun C compiler ends up with
"#define restrict _Restrict" or "#define restrict __restrict__" in the
previous line. Perhaps some future version of Sun C++ will work with
restrict; if so, hopefully it defines __RESTRICT like Sun C does. */
#if defined __SUNPRO_CC && !defined __RESTRICT
# define _Restrict
# define __restrict__
#endif
/* Define to `unsigned int' if <sys/types.h> does not define. */
/* #undef size_t */
/* Define to `int' if <sys/types.h> does not define. */
/* #undef ssize_t */
/* Define to the type of an unsigned integer type of width exactly 32 bits if
such a type exists and the standard includes do not define it. */
/* #undef uint32_t */
/* Define to the type of an unsigned integer type of width exactly 64 bits if
such a type exists and the standard includes do not define it. */
/* #undef uint64_t */
/* Define to the type of an unsigned integer type of width exactly 8 bits if
such a type exists and the standard includes do not define it. */
/* #undef uint8_t */
#ifndef MMDB_UINT128_USING_MODE
/* Define as 1 if we we use unsigned int __atribute__ ((__mode__(TI))) for uint128 values */
#define MMDB_UINT128_USING_MODE 0
#endif
#ifndef MMDB_UINT128_IS_BYTE_ARRAY
/* Define as 1 if we don't have an unsigned __int128 type */
#define MMDB_UINT128_IS_BYTE_ARRAY 0
#endif
#endif /* MAXMINDDB_CONFIG_H */

407
external/Common/aes256.cpp vendored Normal file
View File

@ -0,0 +1,407 @@
/*
* Byte-oriented AES-256 implementation.
* All lookup tables replaced with 'on the fly' calculations.
*
* Copyright (c) 2007-2011 Ilya O. Levin, http://www.literatecode.com
* Other contributors: Hal Finney
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "aes256.h"
#ifdef __cplusplus
extern "C" {
#endif
#define FD(x) (((x) >> 1) ^ (((x) & 1) ? 0x8d : 0))
#define BACK_TO_TABLES
static uint8_t rj_xtime(uint8_t);
static void aes_subBytes(uint8_t *);
static void aes_subBytes_inv(uint8_t *);
static void aes_addRoundKey(uint8_t *, uint8_t *);
static void aes_addRoundKey_cpy(uint8_t *, uint8_t *, uint8_t *);
static void aes_shiftRows(uint8_t *);
static void aes_shiftRows_inv(uint8_t *);
static void aes_mixColumns(uint8_t *);
static void aes_mixColumns_inv(uint8_t *);
static void aes_expandEncKey(uint8_t *, uint8_t *);
static void aes_expandDecKey(uint8_t *, uint8_t *);
#ifndef BACK_TO_TABLES
static uint8_t gf_alog(uint8_t);
static uint8_t gf_log(uint8_t);
static uint8_t gf_mulinv(uint8_t);
static uint8_t rj_sbox(uint8_t);
static uint8_t rj_sbox_inv(uint8_t);
#endif
#ifdef BACK_TO_TABLES
static const uint8_t sbox[256] =
{
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
};
static const uint8_t sboxinv[256] =
{
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38,
0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d,
0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2,
0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,
0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda,
0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a,
0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,
0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea,
0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85,
0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20,
0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31,
0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,
0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0,
0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26,
0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
};
#define rj_sbox(x) sbox[(x)]
#define rj_sbox_inv(x) sboxinv[(x)]
#else /* tableless subroutines */
/* -------------------------------------------------------------------------- */
static uint8_t gf_alog(uint8_t x) // calculate anti-logarithm gen 3
{
uint8_t y = 1, i;
for (i = 0; i < x; i++) y ^= rj_xtime(y);
return y;
} /* gf_alog */
/* -------------------------------------------------------------------------- */
static uint8_t gf_log(uint8_t x) // calculate logarithm gen 3
{
uint8_t y, i = 0;
if (x)
for (i = 1, y = 1; i > 0; i++ )
{
y ^= rj_xtime(y);
if (y == x) break;
}
return i;
} /* gf_log */
/* -------------------------------------------------------------------------- */
static uint8_t gf_mulinv(uint8_t x) // calculate multiplicative inverse
{
return (x) ? gf_alog(255 - gf_log(x)) : 0;
} /* gf_mulinv */
/* -------------------------------------------------------------------------- */
static uint8_t rj_sbox(uint8_t x)
{
uint8_t y, sb;
sb = y = gf_mulinv(x);
y = (uint8_t)(y << 1) | (y >> 7), sb ^= y;
y = (uint8_t)(y << 1) | (y >> 7), sb ^= y;
y = (uint8_t)(y << 1) | (y >> 7), sb ^= y;
y = (uint8_t)(y << 1) | (y >> 7), sb ^= y;
return (sb ^ 0x63);
} /* rj_sbox */
/* -------------------------------------------------------------------------- */
static uint8_t rj_sbox_inv(uint8_t x)
{
uint8_t y, sb;
y = x ^ 0x63;
sb = y = (uint8_t)(y << 1) | (y >> 7);
y = (uint8_t)(y << 2) | (y >> 6);
sb ^= y;
y = (uint8_t)(y << 3) | (y >> 5);
sb ^= y;
return gf_mulinv(sb);
} /* rj_sbox_inv */
#endif
/* -------------------------------------------------------------------------- */
static uint8_t rj_xtime(uint8_t x)
{
uint8_t y = (uint8_t)(x << 1);
return (x & 0x80) ? (y ^ 0x1b) : y;
} /* rj_xtime */
/* -------------------------------------------------------------------------- */
static void aes_subBytes(uint8_t *buf)
{
register uint8_t i = 16;
while (i--) buf[i] = rj_sbox(buf[i]);
} /* aes_subBytes */
/* -------------------------------------------------------------------------- */
static void aes_subBytes_inv(uint8_t *buf)
{
register uint8_t i = 16;
while (i--) buf[i] = rj_sbox_inv(buf[i]);
} /* aes_subBytes_inv */
/* -------------------------------------------------------------------------- */
static void aes_addRoundKey(uint8_t *buf, uint8_t *key)
{
register uint8_t i = 16;
while (i--) buf[i] ^= key[i];
} /* aes_addRoundKey */
/* -------------------------------------------------------------------------- */
static void aes_addRoundKey_cpy(uint8_t *buf, uint8_t *key, uint8_t *cpk)
{
register uint8_t i = 16;
while (i--) buf[i] ^= (cpk[i] = key[i]), cpk[16 + i] = key[16 + i];
} /* aes_addRoundKey_cpy */
/* -------------------------------------------------------------------------- */
static void aes_shiftRows(uint8_t *buf)
{
register uint8_t i, j; /* to make it potentially parallelable :) */
i = buf[1], buf[1] = buf[5], buf[5] = buf[9], buf[9] = buf[13], buf[13] = i;
i = buf[10], buf[10] = buf[2], buf[2] = i;
j = buf[3], buf[3] = buf[15], buf[15] = buf[11], buf[11] = buf[7], buf[7] = j;
j = buf[14], buf[14] = buf[6], buf[6] = j;
} /* aes_shiftRows */
/* -------------------------------------------------------------------------- */
static void aes_shiftRows_inv(uint8_t *buf)
{
register uint8_t i, j; /* same as above :) */
i = buf[1], buf[1] = buf[13], buf[13] = buf[9], buf[9] = buf[5], buf[5] = i;
i = buf[2], buf[2] = buf[10], buf[10] = i;
j = buf[3], buf[3] = buf[7], buf[7] = buf[11], buf[11] = buf[15], buf[15] = j;
j = buf[6], buf[6] = buf[14], buf[14] = j;
} /* aes_shiftRows_inv */
/* -------------------------------------------------------------------------- */
static void aes_mixColumns(uint8_t *buf)
{
register uint8_t i, a, b, c, d, e;
for (i = 0; i < 16; i += 4)
{
a = buf[i];
b = buf[i + 1];
c = buf[i + 2];
d = buf[i + 3];
e = a ^ b ^ c ^ d;
buf[i] ^= e ^ rj_xtime(a ^ b);
buf[i + 1] ^= e ^ rj_xtime(b ^ c);
buf[i + 2] ^= e ^ rj_xtime(c ^ d);
buf[i + 3] ^= e ^ rj_xtime(d ^ a);
}
} /* aes_mixColumns */
/* -------------------------------------------------------------------------- */
void aes_mixColumns_inv(uint8_t *buf)
{
register uint8_t i, a, b, c, d, e, x, y, z;
for (i = 0; i < 16; i += 4)
{
a = buf[i];
b = buf[i + 1];
c = buf[i + 2];
d = buf[i + 3];
e = a ^ b ^ c ^ d;
z = rj_xtime(e);
x = e ^ rj_xtime(rj_xtime(z ^ a ^ c));
y = e ^ rj_xtime(rj_xtime(z ^ b ^ d));
buf[i] ^= x ^ rj_xtime(a ^ b);
buf[i + 1] ^= y ^ rj_xtime(b ^ c);
buf[i + 2] ^= x ^ rj_xtime(c ^ d);
buf[i + 3] ^= y ^ rj_xtime(d ^ a);
}
} /* aes_mixColumns_inv */
/* -------------------------------------------------------------------------- */
static void aes_expandEncKey(uint8_t *k, uint8_t *rc)
{
register uint8_t i;
k[0] ^= rj_sbox(k[29]) ^ (*rc);
k[1] ^= rj_sbox(k[30]);
k[2] ^= rj_sbox(k[31]);
k[3] ^= rj_sbox(k[28]);
*rc = rj_xtime( *rc);
for(i = 4; i < 16; i += 4) k[i] ^= k[i - 4], k[i + 1] ^= k[i - 3],
k[i + 2] ^= k[i - 2], k[i + 3] ^= k[i - 1];
k[16] ^= rj_sbox(k[12]);
k[17] ^= rj_sbox(k[13]);
k[18] ^= rj_sbox(k[14]);
k[19] ^= rj_sbox(k[15]);
for(i = 20; i < 32; i += 4) k[i] ^= k[i - 4], k[i + 1] ^= k[i - 3],
k[i + 2] ^= k[i - 2], k[i + 3] ^= k[i - 1];
} /* aes_expandEncKey */
/* -------------------------------------------------------------------------- */
void aes_expandDecKey(uint8_t *k, uint8_t *rc)
{
uint8_t i;
for(i = 28; i > 16; i -= 4) k[i + 0] ^= k[i - 4], k[i + 1] ^= k[i - 3],
k[i + 2] ^= k[i - 2], k[i + 3] ^= k[i - 1];
k[16] ^= rj_sbox(k[12]);
k[17] ^= rj_sbox(k[13]);
k[18] ^= rj_sbox(k[14]);
k[19] ^= rj_sbox(k[15]);
for(i = 12; i > 0; i -= 4) k[i + 0] ^= k[i - 4], k[i + 1] ^= k[i - 3],
k[i + 2] ^= k[i - 2], k[i + 3] ^= k[i - 1];
*rc = FD(*rc);
k[0] ^= rj_sbox(k[29]) ^ (*rc);
k[1] ^= rj_sbox(k[30]);
k[2] ^= rj_sbox(k[31]);
k[3] ^= rj_sbox(k[28]);
} /* aes_expandDecKey */
/* -------------------------------------------------------------------------- */
void aes256_init(aes256_context *ctx, uint8_t *k)
{
uint8_t rcon = 1;
register uint8_t i;
for (i = 0; i < sizeof(ctx->key); i++) ctx->enckey[i] = ctx->deckey[i] = k[i];
for (i = 8; --i;) aes_expandEncKey(ctx->deckey, &rcon);
} /* aes256_init */
/* -------------------------------------------------------------------------- */
void aes256_done(aes256_context *ctx)
{
register uint8_t i;
for (i = 0; i < sizeof(ctx->key); i++)
ctx->key[i] = ctx->enckey[i] = ctx->deckey[i] = 0;
} /* aes256_done */
/* -------------------------------------------------------------------------- */
void aes256_encrypt_ecb(aes256_context *ctx, uint8_t *buf)
{
uint8_t i, rcon;
aes_addRoundKey_cpy(buf, ctx->enckey, ctx->key);
for(i = 1, rcon = 1; i < 14; ++i)
{
aes_subBytes(buf);
aes_shiftRows(buf);
aes_mixColumns(buf);
if( i & 1 ) aes_addRoundKey( buf, &ctx->key[16]);
else aes_expandEncKey(ctx->key, &rcon), aes_addRoundKey(buf, ctx->key);
}
aes_subBytes(buf);
aes_shiftRows(buf);
aes_expandEncKey(ctx->key, &rcon);
aes_addRoundKey(buf, ctx->key);
} /* aes256_encrypt */
/* -------------------------------------------------------------------------- */
void aes256_decrypt_ecb(aes256_context *ctx, uint8_t *buf)
{
uint8_t i, rcon;
aes_addRoundKey_cpy(buf, ctx->deckey, ctx->key);
aes_shiftRows_inv(buf);
aes_subBytes_inv(buf);
for (i = 14, rcon = 0x80; --i;)
{
if( ( i & 1 ) )
{
aes_expandDecKey(ctx->key, &rcon);
aes_addRoundKey(buf, &ctx->key[16]);
}
else aes_addRoundKey(buf, ctx->key);
aes_mixColumns_inv(buf);
aes_shiftRows_inv(buf);
aes_subBytes_inv(buf);
}
aes_addRoundKey( buf, ctx->key);
} /* aes256_decrypt */
#ifdef __cplusplus
}
#endif

202
external/MaxmindDB/LICENSE vendored Normal file
View File

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -0,0 +1,167 @@
#include <stdlib.h>
#include <string.h>
/* *INDENT-OFF* */
/* The memmem, strdup, and strndup functions were all copied from the
* FreeBSD source, along with the relevant copyright notice.
*
* It'd be nicer to simply use the functions available on the system if they
* exist, but there doesn't seem to be a good way to detect them without also
* defining things like _GNU_SOURCE, which we want to avoid, because then we
* end up _accidentally_ using GNU features without noticing, which then
* breaks on systems like OSX.
*
* C is fun! */
/* Applies to memmem implementation */
/*-
* Copyright (c) 2005 Pascal Gloor <pascal.gloor@spale.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
static void *
mmdb_memmem(const void *l, size_t l_len, const void *s, size_t s_len)
{
register char *cur, *last;
const char *cl = (const char *)l;
const char *cs = (const char *)s;
/* we need something to compare */
if (l_len == 0 || s_len == 0)
return NULL;
/* "s" must be smaller or equal to "l" */
if (l_len < s_len)
return NULL;
/* special case where s_len == 1 */
if (s_len == 1)
return memchr(l, (int)*cs, l_len);
/* the last position where its possible to find "s" in "l" */
last = (char *)cl + l_len - s_len;
for (cur = (char *)cl; cur <= last; cur++)
if (cur[0] == cs[0] && memcmp(cur, cs, s_len) == 0)
return cur;
return NULL;
}
/* Applies to strnlen implementation */
/*-
* Copyright (c) 2009 David Schultz <das@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
static size_t
mmdb_strnlen(const char *s, size_t maxlen)
{
size_t len;
for (len = 0; len < maxlen; len++, s++) {
if (!*s)
break;
}
return (len);
}
/* Applies to strdup and strndup implementation */
/*
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
static char *
mmdb_strdup(const char *str)
{
size_t len;
char *copy;
len = strlen(str) + 1;
if ((copy = malloc(len)) == NULL)
return (NULL);
memcpy(copy, str, len);
return (copy);
}
static char *
mmdb_strndup(const char *str, size_t n)
{
size_t len;
char *copy;
len = mmdb_strnlen(str, n);
if ((copy = malloc(len + 1)) == NULL)
return (NULL);
memcpy(copy, str, len);
copy[len] = '\0';
return (copy);
}
/* *INDENT-ON* */

2045
external/MaxmindDB/maxminddb.c vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,23 +0,0 @@
This license applies to RandomLib, versions 1.2 and later.
Copyright (c) 2006-2013, Charles Karney
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

File diff suppressed because it is too large Load Diff

View File

@ -1,13 +0,0 @@
#define RANDOMLIB_VERSION_STRING "Unconfigured"
#define RANDOMLIB_VERSION_MAJOR -1
#define RANDOMLIB_VERSION_MINOR -1
#define RANDOMLIB_VERSION_PATCH -1
// Define HAVE_SSE2 to be 1 if Intel/AMD CPU with SSE2 support
/* #undef HAVE_SSE2 */
// Define HAVE_ALTIVEC to be 1 if Power PC CPU with AltiVec support
/* #undef HAVE_ALTIVEC */
// Undefine HAVE_LONG_DOUBLE if this type is unknown to the compiler
#define HAVE_LONG_DOUBLE 1

View File

@ -1,432 +0,0 @@
/**
* \file DiscreteNormal.hpp
* \brief Header for DiscreteNormal
*
* Sample exactly from the discrete normal distribution.
*
* Copyright (c) Charles Karney (2013) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* http://randomlib.sourceforge.net/
**********************************************************************/
#if !defined(RANDOMLIB_DISCRETENORMAL_HPP)
#define RANDOMLIB_DISCRETENORMAL_HPP 1
#include <vector>
#include <limits>
namespace RandomLib {
/**
* \brief The discrete normal distribution.
*
* Sample integers \e i with probability proportional to
* \f[
* \exp\biggl[-\frac12\biggl(\frac{i-\mu}{\sigma}\biggr)^2\biggr],
* \f]
* where &sigma; and &mu; are given as rationals (the ratio of two integers).
* The sampling is exact (provided that the random generator is ideal). For
* example
* \code
#include <iostream>
#include <RandomLib/Random.hpp>
#include <RandomLib/DiscreteNormal.hpp>
int main() {
RandomLib::Random r; // Create r
r.Reseed(); // and give it a unique seed
int sigma_num = 7, sigma_den = 1, mu_num = 1, mu_den = 3;
RandomLib::DiscreteNormal<int> d(sigma_num, sigma_den,
mu_num, mu_den);
for (int i = 0; i < 100; ++i)
std::cout << d(r) << "\n";
}
\endcode
* prints out 100 samples with &sigma; = 7 and &mu; = 1/3.
*
* The algorithm is much the same as for ExactNormal; for details see
* - C. F. F. Karney, <i>Sampling exactly from the normal distribution</i>,
* http://arxiv.org/abs/1303.6257 (Mar. 2013).
* .
* That algorithm samples the integer part of the result \e k, samples \e x
* in [0,1], and (unless rejected) returns <i>s</i>(\e k + \e x), where \e s
* = &plusmn;1. For the discrete case, we sample \e x in [0,1) such that
* \f[
* s(k + x) = (i - \mu)/\sigma,
* \f]
* or
* \f[
* x = s(i - \mu)/\sigma - k
* \f]
* The value of \e i which results in the smallest \e x &ge; 0 is
* \f[
* i_0 = s\lceil k \sigma + s \mu\rceil
* \f]
* so sample
* \f[
* i = i_0 + sj
* \f]
* where \e j is uniformly distributed in [0, &lceil;&sigma;&rceil;). The
* corresponding value of \e x is
* \f[
* \begin{aligned}
* x &= \bigl(si_0 - (k\sigma + s\mu)\bigr)/\sigma + j/\sigma\\
* &= x_0 + j/\sigma,\\
* x_0 &= \bigl(\lceil k \sigma + s \mu\rceil -
* (k \sigma + s \mu)\bigr)/\sigma.
* \end{aligned}
* \f]
* After \e x is sampled in this way, it should be rejected if \e x &ge; 1
* (this is counted with the next larger value of \e k) or if \e x = 0, \e k
* = 0, and \e s = &minus;1 (to avoid double counting the origin). If \e x
* is accepted (in Step 4 of the ExactNormal algorithm), then return \e i.
*
* When &sigma; and &mu; are given as rationals, all the arithmetic outlined
* above can be carried out exactly. The basic rejection techniques used by
* ExactNormal are exact. Thus the result of this discrete form of the
* algorithm is also exact.
*
* RandomLib provides two classes to sample from this distribution:
* - DiscreteNormal which is tuned for speed on a typical general purpose
* computer. This assumes that random samples can be generated relatively
* quickly.
* - DiscreteNormalAlt, which is a prototype for what might be needed on a
* small device used for cryptography which is using a hardware generator
* for obtaining truly random bits. This assumption here is that the
* random bits are relatively expensive to obtain.
* .
* The basic algorithm is the same in the two cases. The main advantages of
* this method are:
* - exact sampling (provided that the source of random numbers is ideal),
* - no need to cut off the tails of the distribution,
* - a short program involving simple integer operations only,
* - no dependence on external libraries (except to generate random bits),
* - no large tables of constants needed,
* - minimal time to set up for a new &sigma; and &mu; (roughly comparable to
* the time it takes to generate one sample),
* - only about 5&ndash;20 times slower than standard routines to sample from
* a normal distribution using plain double-precision arithmetic.
* - DiscreteNormalAlt exhibits ideal scaling for the consumption of random
* bits, namely a constant + log<sub>2</sub>&sigma;, for large &sigma;,
* where the constant is about 31.
* .
* The possible drawbacks of this method are:
* - &sigma; and &mu; are restricted to rational numbers with sufficiently
* small numerators and denominators to avoid overflow (this is unlikely to
* be a severe restriction especially if the template parameter IntType is
* set to <code>long long</code>),
* - the running time is unbounded (but not in any practical sense),
* - the memory consumption is unbounded (but not in any practical sense),
* - the toll, about 30 bits, is considerably worse than that obtained using
* the Knuth-Yao algorithm, for which the toll is no more than 2 (but this
* requires a large table which is expensive to compute and requires a lot
* of memory to store).
*
* This class uses a mutable private vector. So a single DiscreteNormal
* object cannot safely be used by multiple threads. In a multi-processing
* environment, each thread should use a thread-specific DiscreteNormal
* object.
*
* Some timing results for IntType = int, &mu; = 0, and 10<sup>8</sup>
* samples (time = time per sample, including setup time, rv = mean number of
* random variables per sample)
* - &sigma; = 10, time = 219 ns, rv = 17.52
* - &sigma; = 32, time = 223 ns, rv = 17.82
* - &sigma; = 1000, time = 225 ns, rv = 17.95
* - &sigma; = 160000, time = 226 ns, rv = 17.95
*
* @tparam IntType the integer type to use (default int).
**********************************************************************/
template<typename IntType = int> class DiscreteNormal {
public:
/**
* Constructor.
*
* @param[in] sigma_num the numerator of &sigma;.
* @param[in] sigma_den the denominator of &sigma; (default 1).
* @param[in] mu_num the numerator of &mu; (default 0).
* @param[in] mu_den the denominator of &mu; (default 1).
*
* The constructor creates a DiscreteNormal objects for sampling with
* specific values of &sigma; and &mu;. This may throw an exception if the
* parameters are such that overflow is possible. Internally &sigma; and
* &mu; are expressed with a common denominator, so it may be possible to
* avoid overflow by picking the fractions of these quantities so that \e
* sigma_den and \e mu_den have many common factors.
**********************************************************************/
DiscreteNormal(IntType sigma_num, IntType sigma_den = 1,
IntType mu_num = 0, IntType mu_den = 1);
/**
* Return a sample.
*
* @tparam Random the type of the random generator.
* @param[in,out] r a random generator.
* @return discrete normal integer.
**********************************************************************/
template<class Random>
IntType operator()(Random& r) const;
private:
/**
* sigma = _sig / _d, mu = _imu + _mu / _d, _isig = floor(sigma)
**********************************************************************/
IntType _sig, _mu, _d, _isig, _imu;
typedef unsigned short word;
/**
* Holds as much of intermediate uniform deviates as needed.
**********************************************************************/
mutable std::vector<word> _v;
mutable unsigned _m, _l;
/**
* Increment on size of _v.
**********************************************************************/
static const unsigned alloc_incr = 16;
// ceil(n/d) for d > 0
static IntType iceil(IntType n, IntType d);
// abs(n) needed because Visual Studio's std::abs has problems
static IntType iabs(IntType n);
static IntType gcd(IntType u, IntType v);
// After x = LeadingDigit(p), p/_sig = (x + p'/_sig)/b where p and p' are
// in [0, _sig) and b = 1 + max(word).
word LeadingDigit(IntType& p) const;
/**
* Implement outcomes for choosing with prob (\e x + 2\e k) / (2\e k + 2);
* return:
* - 1 (succeed unconditionally) with prob (\e m &minus; 2) / \e m,
* - 0 (succeed with probability x) with prob 1 / \e m,
* - &minus;1 (fail unconditionally) with prob 1 / \e m.
**********************************************************************/
template<class Random> static int Choose(Random& r, int m);
// Compute v' < v. If true set v = v'.
template<class Random> bool less_than(Random& r) const;
// Compute v < (x + p/_sig)/base (updating v)
template<class Random> bool less_than(Random& r, word x, IntType p) const;
// true with prob (x + p/_sig)/base
template<class Random> bool bernoulli(Random& r, word x, IntType p) const;
/**
* Return true with probability exp(&minus;1/2).
**********************************************************************/
template<class Random> bool ExpProbH(Random& r) const;
/**
* Return true with probability exp(&minus;<i>n</i>/2).
**********************************************************************/
template<class Random> bool ExpProb(Random& r, int n) const;
/**
* Return \e n with probability exp(&minus;<i>n</i>/2)
* (1&minus;exp(&minus;1/2)).
**********************************************************************/
template<class Random> int ExpProbN(Random& r) const;
/**
* Algorithm B: true with prob exp(-x * (2*k + x) / (2*k + 2)) where
* x = (x0 + xn / _sig)/b.
**********************************************************************/
template<class Random>
bool B(Random& r, int k, word x0, IntType xn) const;
};
template<typename IntType> DiscreteNormal<IntType>::DiscreteNormal
(IntType sigma_num, IntType sigma_den,
IntType mu_num, IntType mu_den)
: _v(std::vector<word>(alloc_incr)), _m(0), _l(alloc_incr) {
STATIC_ASSERT(std::numeric_limits<IntType>::is_integer,
"DiscreteNormal: invalid integer type IntType");
STATIC_ASSERT(std::numeric_limits<IntType>::is_signed,
"DiscreteNormal: IntType must be a signed type");
STATIC_ASSERT(!std::numeric_limits<word>::is_signed,
"DiscreteNormal: word must be an unsigned type");
STATIC_ASSERT(std::numeric_limits<IntType>::digits + 1 >=
std::numeric_limits<word>::digits,
"DiscreteNormal: IntType must be at least as wide as word");
if (!( sigma_num > 0 && sigma_den > 0 && mu_den > 0 ))
throw RandomErr("DiscreteNormal: need sigma > 0");
_imu = mu_num / mu_den;
if (_imu == (std::numeric_limits<IntType>::min)())
throw RandomErr("DiscreteNormal: abs(mu) too large");
mu_num -= _imu * mu_den;
IntType l;
l = gcd(sigma_num, sigma_den); sigma_num /= l; sigma_den /= l;
l = gcd(mu_num, mu_den); mu_num /= l; mu_den /= l;
_isig = iceil(sigma_num, sigma_den);
l = gcd(sigma_den, mu_den);
_sig = sigma_num * (mu_den / l);
_mu = mu_num * (sigma_den / l);
_d = sigma_den * (mu_den / l);
// The rest of the constructor tests for possible overflow
// Check for overflow in computing member variables
IntType maxint = (std::numeric_limits<IntType>::max)();
if (!( mu_den / l <= maxint / sigma_num &&
mu_num <= maxint / (sigma_den / l) &&
mu_den / l <= maxint / sigma_den ))
throw RandomErr("DiscreteNormal: sigma or mu overflow");
// The probability that k = kmax is about 10^-543.
int kmax = 50;
// Check that max plausible result fits in an IntType, i.e.,
// _isig * (kmax + 1) + abs(_imu) does not lead to overflow.
if (!( kmax + 1 <= maxint / _isig &&
_isig * (kmax + 1) <= maxint - iabs(_imu) ))
throw RandomErr("DiscreteNormal: possible overflow a");
// Check xn0 = _sig * k + s * _mu;
if (!( kmax <= maxint / _sig &&
_sig * kmax <= maxint - iabs(_mu) ))
throw RandomErr("DiscreteNormal: possible overflow b");
// Check for overflow in LeadingDigit
// p << bits, p = _sig - 1, bits = 8
if (!( _sig <= (maxint >> 8) ))
throw RandomErr("DiscreteNormal: overflow in LeadingDigit");
}
template<typename IntType> template<class Random>
IntType DiscreteNormal<IntType>::operator()(Random& r) const {
for (;;) {
int k = ExpProbN(r);
if (!ExpProb(r, k * (k - 1))) continue;
IntType
s = r.Boolean() ? -1 : 1,
xn = _sig * IntType(k) + s * _mu,
i = iceil(xn, _d) + r.template Integer<IntType>(_isig);
xn = i * _d - xn;
if (xn >= _sig || (k == 0 && s < 0 && xn <= 0)) continue;
if (xn > 0) {
word x0 = LeadingDigit(xn); // Find first digit in expansion in words
int h = k + 1; while (h-- && B(r, k, x0, xn));
if (!(h < 0)) continue;
}
return s * i + _imu;
}
}
template<typename IntType>
IntType DiscreteNormal<IntType>::iceil(IntType n, IntType d)
{ IntType k = n / d; return k + (k * d < n ? 1 : 0); }
template<typename IntType> IntType DiscreteNormal<IntType>::iabs(IntType n)
{ return n < 0 ? -n : n; }
template<typename IntType>
IntType DiscreteNormal<IntType>::gcd(IntType u, IntType v) {
// Knuth, TAOCP, vol 2, 4.5.2, Algorithm A
u = iabs(u); v = iabs(v);
while (v > 0) { IntType r = u % v; u = v; v = r; }
return u;
}
template<typename IntType> typename DiscreteNormal<IntType>::word
DiscreteNormal<IntType>::LeadingDigit(IntType& p) const {
static const unsigned bits = 8;
static const unsigned num = std::numeric_limits<word>::digits / bits;
STATIC_ASSERT(bits * num == std::numeric_limits<word>::digits,
"Number of digits in word must be multiple of 8");
word s = 0;
for (unsigned c = num; c--;) {
p <<= bits; s <<= bits;
word d = word(p / _sig);
s += d;
p -= IntType(d) * _sig;
}
return s;
}
template<typename IntType> template<class Random>
int DiscreteNormal<IntType>::Choose(Random& r, int m) {
int k = r.template Integer<int>(m);
return k == 0 ? 0 : (k == 1 ? -1 : 1);
}
template<typename IntType> template<class Random>
bool DiscreteNormal<IntType>::less_than(Random& r) const {
for (unsigned j = 0; ; ++j) {
if (j == _m) {
// Need more bits in the old V
if (_l == _m) _v.resize(_l += alloc_incr);
_v[_m++] = r.template Integer<word>();
}
word w = r.template Integer<word>();
if (w > _v[j])
return false; // New V is bigger, so exit
else if (w < _v[j]) {
_v[j] = w; // New V is smaller, update _v
_m = j + 1; // adjusting its size
return true; // and generate the next V
}
// Else w == _v[j] and we need to check the next word
}
}
template<typename IntType> template<class Random>
bool DiscreteNormal<IntType>::less_than(Random& r, word x, IntType p) const {
if (_m == 0) _v[_m++] = r.template Integer<word>();
if (_v[0] != x) return _v[0] < x;
for (unsigned j = 1; ; ++j) {
if (p == 0) return false;
if (j == _m) {
if (_l == _m) _v.resize(_l += alloc_incr);
_v[_m++] = r.template Integer<word>();
}
x = LeadingDigit(p);
if (_v[j] != x) return _v[j] < x;
}
}
template<typename IntType> template<class Random>
bool DiscreteNormal<IntType>::bernoulli(Random& r, word x, IntType p) const {
word w = r.template Integer<word>();
if (w != x) return w < x;
for (;;) {
if (p == 0) return false;
x = LeadingDigit(p);
w = r.template Integer<word>();
if (w != x) return w < x;
}
}
template<typename IntType> template<class Random>
bool DiscreteNormal<IntType>::ExpProbH(Random& r) const {
static const word half = word(1) << (std::numeric_limits<word>::digits - 1);
_m = 0;
if ((_v[_m++] = r.template Integer<word>()) & half) return true;
// Here _v < 1/2. Now loop finding decreasing V. Exit when first
// increasing one is found.
for (unsigned s = 0; ; s ^= 1) { // Parity of loop count
if (!less_than(r)) return s != 0u;
}
}
template<typename IntType> template<class Random>
bool DiscreteNormal<IntType>::ExpProb(Random& r, int n) const {
while (n-- > 0) { if (!ExpProbH(r)) return false; }
return true;
}
template<typename IntType> template<class Random>
int DiscreteNormal<IntType>::ExpProbN(Random& r) const {
int n = 0;
while (ExpProbH(r)) ++n;
return n;
}
template<typename IntType> template<class Random>
bool DiscreteNormal<IntType>::B(Random& r, int k, word x0, IntType xn)
const {
int n = 0, h = 2 * k + 2, f;
_m = 0;
for (;; ++n) {
if ( ((f = k ? 0 : Choose(r, h)) < 0) ||
!(n ? less_than(r) : less_than(r, x0, xn)) ||
((f = k ? Choose(r, h) : f) < 0) ||
(f == 0 && !bernoulli(r, x0, xn)) ) break;
}
return (n % 2) == 0;
}
} // namespace RandomLib
#endif // RANDOMLIB_DISCRETENORMAL_HPP

View File

@ -1,328 +0,0 @@
/**
* \file DiscreteNormalAlt.hpp
* \brief Header for DiscreteNormalAlt
*
* Sample exactly from the discrete normal distribution (alternate version).
*
* Copyright (c) Charles Karney (2013) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* http://randomlib.sourceforge.net/
**********************************************************************/
#if !defined(RANDOMLIB_DISCRETENORMALALT_HPP)
#define RANDOMLIB_DISCRETENORMALALT_HPP 1
#include <RandomLib/RandomNumber.hpp>
#include <RandomLib/UniformInteger.hpp>
#include <limits>
namespace RandomLib {
/**
* \brief The discrete normal distribution (alternate version).
*
* Sample integers \e i with probability proportional to
* \f[
* \exp\biggl[-\frac12\biggl(\frac{i-\mu}{\sigma}\biggr)^2\biggr],
* \f]
* where &sigma; and &mu; are given as rationals (the ratio of two integers).
* The sampling is exact (provided that the random generator is ideal). The
* results of this class are UniformInteger objects which represent a
* contiguous range which is a power of 2<sup>\e bits</sup>. This can be
* narrowed down to a specific integer as follows
* \code
#include <iostream>
#include <RandomLib/Random.hpp>
#include <RandomLib/UniformInteger.hpp>
#include <RandomLib/DiscreteNormalAlt.hpp>
int main() {
RandomLib::Random r; // Create r
r.Reseed(); // and give it a unique seed
int sigma_num = 7, sigma_den = 1, mu_num = 1, mu_den = 3;
RandomLib::DiscreteNormalAlt<int,1> d(sigma_num, sigma_den,
mu_num, mu_den);
for (int i = 0; i < 100; ++i) {
RandomLib::UniformInteger<int,1> u = d(r);
std::cout << u << " = ";
std::cout << u(r) << "\n";
}
}
\endcode
* prints out 100 samples with &sigma; = 7 and &mu; = 1/3; the samples are
* first given as a range and then <code>u(r)</code> is used to obtain a
* specific integer. In some applications, it might be possible to avoid
* sampling all the additional digits to get to a specific integer. (An
* example would be drawing a sample which satisfies an inequality.) This
* version is slower (by a factor of about 4 for \e bits = 1) than
* DiscreteNormal on a conventional computer, but may be faster when random
* bits are generated by a slow hardware device.
*
* The basic algorithm is the same as for DiscreteNormal. However randomness
* in metered out \e bits random bits at a time. The algorithm uses the
* least random bits (and is slowest!) when \e bits = 1. This rationing of
* random bits also applies to sampling \e j in the expression
* \f[
* x = x_0 + j/\sigma.
* \f]
* Rather than sampling a definite value for \e j, which then might be
* rejected, \e j is sampled using UniformInteger. UniformInteger uses
* Lumbroso's method from sampling an integer uniformly in [0, \e m) using at
* most 2 + log<sub>2</sub>\e m bits on average (for \e bits = 1). However
* when a UniformInteger object is first constructed it samples at most 3
* bits (on average) to obtain a range for \e j which is power of 2. This
* allows the algorithm to achieve ideal scaling in the limit of large
* &sigma; consuming constant + log<sub>2</sub>&sigma; bits on average. In
* addition it can deliver the resuls in the form of a UniformInteger
* consuming a constant number of bits on average (and then about
* log<sub>2</sub>&sigma; additional bits are required to convert the
* UniformInteger into an integer sample). The consumption of random bits
* (for \e bits = 1) is summarized here \verbatim
min mean max
bits for UniformInteger result 30.4 34.3 35.7
bits for integer result - log2(sigma) 28.8 31.2 32.5
toll 26.8 29.1 30.4 \endverbatim
* These results are averaged over many samples. The "min" results apply
* when &sigma; is a power of 2; the "max" results apply when &sigma; is
* slightly more than a power of two; the "mean" results are averaged over
* &sigma;. The toll is the excess number of bits over the entropy of the
* distribution, which is log<sub>2</sub>(2&pi;\e e)/2 +
* log<sub>2</sub>&sigma; (for &sigma; large).
*
* The data for the first two lines in the table above are taken for the blue
* and red lines in the figure below where the abscissa is the fractional
* part of log<sub>2</sub>&sigma;
* \image html
* discrete-bits.png "Random bits to sample from discrete normal distribution"
*
* This class uses a mutable RandomNumber objects. So a single
* DiscreteNormalAlt object cannot safely be used by multiple threads. In a
* multi-processing environment, each thread should use a thread-specific
* DiscreteNormalAlt object.
*
* @tparam IntType the integer type to use (default int).
**********************************************************************/
template<typename IntType = int, int bits = 1> class DiscreteNormalAlt {
public:
/**
* Constructor.
*
* @param[in] sigma_num the numerator of &sigma;.
* @param[in] sigma_den the denominator of &sigma; (default 1).
* @param[in] mu_num the numerator of &mu; (default 0).
* @param[in] mu_den the denominator of &mu; (default 1).
*
* This may throw an exception is the parameters are such that overflow is
* possible.
**********************************************************************/
DiscreteNormalAlt(IntType sigma_num, IntType sigma_den = 1,
IntType mu_num = 0, IntType mu_den = 1);
/**
* Return a sample.
*
* @tparam Random the type of the random generator.
* @param[in,out] r a random generator.
* @return discrete normal sample in the form of a UniformInteger object.
**********************************************************************/
template<class Random>
UniformInteger<IntType, bits> operator()(Random& r) const;
private:
/**
* sigma = _sig / _d, mu = _imu + _mu / _d, _isig = ceil(sigma)
**********************************************************************/
IntType _sig, _mu, _d, _isig, _imu;
mutable RandomNumber<bits> _p;
mutable RandomNumber<bits> _q;
// ceil(n/d) for d > 0
static IntType iceil(IntType n, IntType d);
// abs(n) needed because Visual Studio's std::abs has problems
static IntType iabs(IntType n);
static IntType gcd(IntType u, IntType v);
/**
* Implement outcomes for choosing with prob (\e x + 2\e k) / (2\e k + 2);
* return:
* - 1 (succeed unconditionally) with prob (\e m &minus; 2) / \e m,
* - 0 (succeed with probability x) with prob 1 / \e m,
* - &minus;1 (fail unconditionally) with prob 1 / \e m.
**********************************************************************/
template<class Random> static int Choose(Random& r, int m);
/**
* Return true with probability exp(&minus;1/2).
**********************************************************************/
template<class Random> bool ExpProbH(Random& r) const;
/**
* Return true with probability exp(&minus;<i>n</i>/2).
**********************************************************************/
template<class Random> bool ExpProb(Random& r, int n) const;
/**
* Return \e n with probability exp(&minus;<i>n</i>/2)
* (1&minus;exp(&minus;1/2)).
**********************************************************************/
template<class Random> int ExpProbN(Random& r) const;
/**
* Algorithm B: true with prob exp(-x * (2*k + x) / (2*k + 2)) where
* x = (xn0 + _d * j) / _sig
**********************************************************************/
template<class Random>
bool B(Random& r, int k, IntType xn0, UniformInteger<IntType, bits>& j)
const;
};
template<typename IntType, int bits>
DiscreteNormalAlt<IntType, bits>::DiscreteNormalAlt
(IntType sigma_num, IntType sigma_den, IntType mu_num, IntType mu_den) {
STATIC_ASSERT(std::numeric_limits<IntType>::is_integer,
"DiscreteNormalAlt: invalid integer type IntType");
STATIC_ASSERT(std::numeric_limits<IntType>::is_signed,
"DiscreteNormalAlt: IntType must be a signed type");
if (!( sigma_num > 0 && sigma_den > 0 && mu_den > 0 ))
throw RandomErr("DiscreteNormalAlt: need sigma > 0");
_imu = mu_num / mu_den;
if (_imu == (std::numeric_limits<IntType>::min)())
throw RandomErr("DiscreteNormalAlt: abs(mu) too large");
mu_num -= _imu * mu_den;
IntType l;
l = gcd(sigma_num, sigma_den); sigma_num /= l; sigma_den /= l;
l = gcd(mu_num, mu_den); mu_num /= l; mu_den /= l;
_isig = iceil(sigma_num, sigma_den);
l = gcd(sigma_den, mu_den);
_sig = sigma_num * (mu_den / l);
_mu = mu_num * (sigma_den / l);
_d = sigma_den * (mu_den / l);
// The rest of the constructor tests for possible overflow
// Check for overflow in computing member variables
IntType maxint = (std::numeric_limits<IntType>::max)();
if (!( mu_den / l <= maxint / sigma_num &&
iabs(mu_num) <= maxint / (sigma_den / l) &&
mu_den / l <= maxint / sigma_den ))
throw RandomErr("DiscreteNormalAlt: sigma or mu overflow");
if (!UniformInteger<IntType, bits>::Check(_isig, _d))
throw RandomErr("DiscreteNormalAlt: overflow in UniformInteger");
// The probability that k = kmax is about 10^-543.
int kmax = 50;
// Check that max plausible result fits in an IntType, i.e.,
// _isig * (kmax + 1) + abs(_imu) does not lead to overflow.
if (!( kmax + 1 <= maxint / _isig &&
_isig * (kmax + 1) <= maxint - iabs(_imu) ))
throw RandomErr("DiscreteNormalAlt: possible overflow a");
// Check xn0 = _sig * k + s * _mu;
if (!( kmax <= maxint / _sig &&
_sig * kmax <= maxint - iabs(_mu) ))
throw RandomErr("DiscreteNormalAlt: possible overflow b");
// Check for overflow in RandomNumber::LessThan(..., UniformInteger& j)
// p0 * b, p0 = arg2 = xn0 = _d - 1
// c *= b, c = arg3 = _d
// digit(D, k) * q, digit(D, k) = b - 1, q = arg4 = _sig
if (!( _d <= maxint >> bits ))
throw std::runtime_error("DiscreteNormalAlt: overflow in RandomNumber a");
if (!( (IntType(1) << bits) - 1 <= maxint / _sig ))
throw std::runtime_error("DiscreteNormalAlt: overflow in RandomNumber b");
}
template<typename IntType, int bits> template<class Random>
UniformInteger<IntType, bits>
DiscreteNormalAlt<IntType, bits>::operator()(Random& r) const {
for (;;) {
int k = ExpProbN(r);
if (!ExpProb(r, k * (k - 1))) continue;
UniformInteger<IntType, bits> j(r, _isig);
IntType
s = r.Boolean() ? -1 : 1,
xn0 = _sig * IntType(k) + s * _mu,
i0 = iceil(xn0, _d); // i = i0 + j
xn0 = i0 * _d - xn0; // xn = xn0 + _d * j
if (!j.LessThan(r, _sig - xn0, _d) ||
(k == 0 && s < 0 && !j.GreaterThan(r, -xn0, _d))) continue;
int h = k + 1; while (h-- && B(r, k, xn0, j));
if (!(h < 0)) continue;
j.Add(i0 + s * _imu);
if (s < 0) j.Negate();
return j;
}
}
template<typename IntType, int bits>
IntType DiscreteNormalAlt<IntType, bits>::iceil(IntType n, IntType d)
{ IntType k = n / d; return k + (k * d < n ? 1 : 0); }
template<typename IntType, int bits>
IntType DiscreteNormalAlt<IntType, bits>::iabs(IntType n)
{ return n < 0 ? -n : n; }
template<typename IntType, int bits>
IntType DiscreteNormalAlt<IntType, bits>::gcd(IntType u, IntType v) {
// Knuth, TAOCP, vol 2, 4.5.2, Algorithm A
u = iabs(u); v = iabs(v);
while (v > 0) { IntType r = u % v; u = v; v = r; }
return u;
}
template<typename IntType, int bits> template<class Random>
int DiscreteNormalAlt<IntType, bits>::Choose(Random& r, int m) {
// Limit base to 2^15 to avoid integer overflow
const int b = bits > 15 ? 15 : bits;
const unsigned mask = (1u << b) - 1;
int n1 = m - 2, n2 = m - 1;
// Evaluate u < n/m where u is a random real number in [0,1). Write u =
// (d + u') / 2^b where d is a random integer in [0,2^b) and u' is in
// [0,1). Then u < n/m becomes u' < n'/m where n' = 2^b * n - d * m and
// exit if n' <= 0 (false) or n' >= m (true).
for (;;) {
int d = (mask & RandomNumber<bits>::RandomDigit(r)) * m;
n1 = (std::max)((n1 << b) - d, 0);
if (n1 >= m) return 1;
n2 = (std::min)((n2 << b) - d, m);
if (n2 <= 0) return -1;
if (n1 == 0 && n2 == m) return 0;
}
}
template<typename IntType, int bits> template<class Random>
bool DiscreteNormalAlt<IntType, bits>::ExpProbH(Random& r) const {
_p.Init();
if (_p.Digit(r, 0) >> (bits - 1)) return true;
for (;;) {
_q.Init(); if (!_q.LessThan(r, _p)) return false;
_p.Init(); if (!_p.LessThan(r, _q)) return true;
}
}
template<typename IntType, int bits> template<class Random>
bool DiscreteNormalAlt<IntType, bits>::ExpProb(Random& r, int n) const {
while (n-- > 0) { if (!ExpProbH(r)) return false; }
return true;
}
template<typename IntType, int bits> template<class Random>
int DiscreteNormalAlt<IntType, bits>::ExpProbN(Random& r) const {
int n = 0;
while (ExpProbH(r)) ++n;
return n;
}
template<typename IntType, int bits> template<class Random> bool
DiscreteNormalAlt<IntType, bits>::B(Random& r, int k, IntType xn0,
UniformInteger<IntType, bits>& j)
const {
int n = 0, m = 2 * k + 2, f;
for (;; ++n) {
if ( ((f = k ? 0 : Choose(r, m)) < 0) ||
(_q.Init(),
!(n ? _q.LessThan(r, _p) : _q.LessThan(r, xn0, _d, _sig, j))) ||
((f = k ? Choose(r, m) : f) < 0) ||
(f == 0 && (_p.Init(), !_p.LessThan(r, xn0, _d, _sig, j))) )
break;
_p.swap(_q); // an efficient way of doing p = q
}
return (n % 2) == 0;
}
} // namespace RandomLib
#endif // RANDOMLIB_DISCRETENORMALALT_HPP

View File

@ -1,241 +0,0 @@
/**
* \file ExactExponential.hpp
* \brief Header for ExactExponential
*
* Sample exactly from an exponential distribution.
*
* Copyright (c) Charles Karney (2006-2012) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* http://randomlib.sourceforge.net/
**********************************************************************/
#if !defined(RANDOMLIB_EXACTEXPONENTIAL_HPP)
#define RANDOMLIB_EXACTEXPONENTIAL_HPP 1
#include <RandomLib/RandomNumber.hpp>
#if defined(_MSC_VER)
// Squelch warnings about constant conditional expressions
# pragma warning (push)
# pragma warning (disable: 4127)
#endif
namespace RandomLib {
/**
* \brief Sample exactly from an exponential distribution.
*
* Sample \e x &ge; 0 from exp(&minus;\e x). See:
* - J. von Neumann, Various Techniques used in Connection with Random
* Digits, J. Res. Nat. Bur. Stand., Appl. Math. Ser. 12, 36--38
* (1951), reprinted in Collected Works, Vol. 5, 768--770 (Pergammon,
* 1963).
* - M. Abramowitz and I. A. Stegun, Handbook of Mathematical Functions
* (National Bureau of Standards, 1964), Sec. 26.8.6.c(2).
* - G. E. Forsythe, Von Neumann's Comparison Method for Random Sampling from
* Normal and Other Distributions, Math. Comp. 26, 817--826 (1972).
* - D. E. Knuth, TAOCP, Vol 2, Sec 3.4.1.C.3.
* - D. E. Knuth and A. C. Yao, The Complexity of Nonuniform Random Number
* Generation, in "Algorithms and Complexity" (Academic Press, 1976),
* pp. 357--428.
* - P. Flajolet and N. Saheb, The Complexity of Generating an
* Exponentially Distributed Variate, J. Algorithms 7, 463--488 (1986).
*
* The following code illustrates the basic method given by von Neumann:
* \code
// Return a random number x >= 0 distributed with probability exp(-x).
double ExpDist(RandomLib::Random& r) {
for (unsigned k = 0; ; ++k) {
double x = r.Fixed(), // executed 1/(1-exp(-1)) times on average
p = x, q;
do {
q = r.Fixed(); // executed exp(x)*cosh(x) times on average
if (!(q < p)) return k + x;
p = r.Fixed(); // executed exp(x)*sinh(x) times on average
} while (p < q);
}
}
\endcode
* This returns a result consuming exp(1)/(1 &minus; exp(-1)) = 4.30 random
* numbers on average. (Von Neumann incorrectly states that the method takes
* (1 + exp(1))/(1 &minus; exp(-1)) = 5.88 random numbers on average.)
* Because of the finite precision of Random::Fixed(), the code snippet above
* only approximates exp(&minus;\e x). Instead, it returns \e x with
* probability \e h(1 &minus; \e h)<sup><i>x</i>/<i>h</i></sup> for \e x = \e
* ih, \e h = 2<sup>&minus;53</sup>, and integer \e i &ge; 0.
*
* The above is precisely von Neumann's method. Abramowitz and Stegun
* consider a variant: sample uniform variants until the first is less than
* the sum of the rest. Forsythe converts the < ranking for the runs to &le;
* which makes the analysis of the discrete case more difficult. He also
* drops the "trick" by which the integer part of the deviate is given by the
* number of rejections when finding the fractional part.
*
* Von Neumann says of his method: "The machine has in effect computed a
* logarithm by performing only discriminations on the relative magnitude of
* numbers in (0,1). It is a sad fact of life, however, that under the
* particular conditions of the Eniac it was slightly quicker to use a
* truncated power series for log(1&minus;\e T) than to carry out all the
* discriminations."
*
* Here the code is modified to make it more efficient:
* \code
// Return a random number x >= 0 distributed with probability exp(-x).
double ExpDist(RandomLib::Random& r) {
for (unsigned k = 0; ; ++k) {
double x = r.Fixed(); // executed 1/(1-exp(-1/2)) times on average
if (x >= 0.5) continue;
double p = x, q;
do {
q = r.Fixed(); // executed exp(x)*cosh(x) times on average
if (!(q < p)) return 0.5 * k + x;
p = r.Fixed(); // executed exp(x)*sinh(x) times on average
} while (p < q);
}
}
\endcode
* In addition, the method is extended to use infinite precision uniform
* deviates implemented by RandomNumber and returning \e exact results for
* the exponential distribution. This is possible because only comparisons
* are done in the method. The template parameter \e bits specifies the
* number of bits in the base used for RandomNumber (i.e., base =
* 2<sup><i>bits</i></sup>).
*
* For example the following samples from an exponential distribution and
* prints various representations of the result.
* \code
#include <RandomLib/RandomNumber.hpp>
#include <RandomLib/ExactExponential.hpp>
RandomLib::Random r;
const int bits = 1;
RandomLib::ExactExponential<bits> edist;
for (size_t i = 0; i < 10; ++i) {
RandomLib::RandomNumber<bits> x = edist(r); // Sample
std::pair<double, double> z = x.Range();
std::cout << x << " = " // Print in binary with ellipsis
<< "(" << z.first << "," << z.second << ")"; // Print range
double v = x.Value<double>(r); // Round exactly to nearest double
std::cout << " = " << v << "\n";
}
\endcode
* Here's a possible result: \verbatim
0.0111... = (0.4375,0.5) = 0.474126
10.000... = (2,2.125) = 2.05196
1.00... = (1,1.25) = 1.05766
0.010... = (0.25,0.375) = 0.318289
10.1... = (2.5,3) = 2.8732
0.0... = (0,0.5) = 0.30753
0.101... = (0.625,0.75) = 0.697654
0.00... = (0,0.25) = 0.0969214
0.0... = (0,0.5) = 0.194053
0.11... = (0.75,1) = 0.867946 \endverbatim
* First number is in binary with ... indicating an infinite sequence of
* random bits. Second number gives the corresponding interval. Third
* number is the result of filling in the missing bits and rounding exactly
* to the nearest representable double.
*
* This class uses some mutable RandomNumber objects. So a single
* ExactExponential object cannot safely be used by multiple threads. In a
* multi-processing environment, each thread should use a thread-specific
* ExactExponential object. In addition, these should be invoked with
* thread-specific random generator objects.
*
* @tparam bits the number of bits in each digit.
**********************************************************************/
template<int bits = 1> class ExactExponential {
public:
/**
* Return a random deviate with an exponential distribution, exp(&minus;\e
* x) for \e x &ge; 0. Requires 7.232 bits per invocation for \e bits = 1.
* The average number of bits in the fraction = 1.743. The relative
* frequency of the results for the fractional part with \e bits = 1 is
* shown by the histogram
* \image html exphist.png
* The base of each rectangle gives the range represented by the
* corresponding binary number and the area is proportional to its
* frequency. A PDF version of this figure is given
* <a href="exphist.pdf">here</a>. This allows the figure to be magnified
* to show the rectangles for all binary numbers up to 9 bits. Note that
* this histogram was generated using an earlier version of
* ExactExponential (thru version 1.3) that implements von Neumann's
* original method. The histogram generated with the current version of
* ExactExponential is the same as this figure for \e u in [0, 1/2]. The
* histogram for \e u in [1/2, 1] is obtained by shifting and scaling the
* part for \e u in [0, 1/2] to fit under the exponential curve.
*
* Another way of assessing the efficiency of the algorithm is thru the
* mean value of the balance = (number of random bits consumed) &minus;
* (number of bits in the result). If we code the result in mixed Knuth
* and Yao's unary-binary notation (integer is given in unary, followed by
* "0" as a separator, followed by the fraction in binary), then the mean
* balance is 3.906. (Flajolet and Saheb analyzed the algorithm based on
* the original von Neumann method and showed that the balance is 5.680 in
* that case.)
*
* For \e bits large, the mean number of random digits is exp(1/2)/(1
* &minus; exp(&minus;1/2)) = 4.19 (versus 4.30 digits for the original
* method).
*
* @tparam Random the type of the random generator.
* @param[in,out] r a random generator.
* @return the random sample.
**********************************************************************/
template<class Random> RandomNumber<bits> operator()(Random& r) const;
private:
/**
* Return true with probability exp(&minus;\e p) for \e p in (0,1/2).
**********************************************************************/
template<class Random> bool
ExpFraction(Random& r, RandomNumber<bits>& p) const;
mutable RandomNumber<bits> _x;
mutable RandomNumber<bits> _v;
mutable RandomNumber<bits> _w;
};
template<int bits> template<class Random> RandomNumber<bits>
ExactExponential<bits>::operator()(Random& r) const {
// A simple rejection method gives the 1/2 fractional part. The number of
// rejections gives the multiples of 1/2.
//
// bits: used fract un-bin balance double
// original stats: 9.31615 2.05429 3.63628 5.67987 61.59456
// new stats: 7.23226 1.74305 3.32500 3.90725 59.82198
//
// The difference between un-bin and fract is exp(1)/(exp(1)-1) = 1.58198
_x.Init();
int k = 0;
while (!ExpFraction(r, _x)) { // Executed 1/(1 - exp(-1/2)) on average
++k;
_x.Init();
}
if (k & 1) _x.RawDigit(0) += 1U << (bits - 1);
_x.AddInteger(k >> 1);
return _x;
}
template<int bits> template<class Random> bool
ExactExponential<bits>::ExpFraction(Random& r, RandomNumber<bits>& p)
const {
// The early bale out
if (p.Digit(r, 0) >> (bits - 1)) return false;
// Implement the von Neumann algorithm
_w.Init();
if (!_w.LessThan(r, p)) // if (w < p)
return true;
while (true) { // Unroll loop to avoid copying RandomNumber
_v.Init(); // v = r.Fixed();
if (!_v.LessThan(r, _w)) // if (v < w)
return false;
_w.Init(); // w = r.Fixed();
if (!_w.LessThan(r, _v)) // if (w < v)
return true;
}
}
} // namespace RandomLib
#if defined(_MSC_VER)
# pragma warning (pop)
#endif
#endif // RANDOMLIB_EXACTEXPONENTIAL_HPP

View File

@ -1,417 +0,0 @@
/**
* \file ExactNormal.hpp
* \brief Header for ExactNormal
*
* Sample exactly from a normal distribution.
*
* Copyright (c) Charles Karney (2011-2012) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* http://randomlib.sourceforge.net/
**********************************************************************/
#if !defined(RANDOMLIB_EXACTNORMAL_HPP)
#define RANDOMLIB_EXACTNORMAL_HPP 1
#include <RandomLib/RandomNumber.hpp>
#include <algorithm> // for max/min
#if defined(_MSC_VER)
// Squelch warnings about constant conditional expressions
# pragma warning (push)
# pragma warning (disable: 4127)
#endif
namespace RandomLib {
/**
* \brief Sample exactly from a normal distribution.
*
* Sample \e x from exp(&minus;<i>x</i><sup>2</sup>/2) / sqrt(2&pi;). For
* background, see:
* - J. von Neumann, Various Techniques used in Connection with Random
* Digits, J. Res. Nat. Bur. Stand., Appl. Math. Ser. 12, 36--38
* (1951), reprinted in Collected Works, Vol. 5, 768--770 (Pergammon,
* 1963).
* - D. E. Knuth and A. C. Yao, The Complexity of Nonuniform Random Number
* Generation, in "Algorithms and Complexity" (Academic Press, 1976),
* pp. 357--428.
* - P. Flajolet and N. Saheb, The Complexity of Generating an Exponentially
* Distributed Variate, J. Algorithms 7, 463--488 (1986).
*
* The algorithm is given in
* - C. F. F. Karney, <i>Sampling exactly from the normal distribution</i>,
* http://arxiv.org/abs/1303.6257 (Mar. 2013).
* .
* In brief, the algorithm is:
* -# Select an integer \e k &ge; 0 with probability
* exp(&minus;<i>k</i>/2) (1&minus;exp(&minus;1/2)).
* -# Accept with probability
* exp(&minus; \e k (\e k &minus; 1) / 2); otherwise, reject and start
* over at step 1.
* -# Sample a random number \e x uniformly from [0,1).
* -# Accept with probability exp(&minus; \e x (\e x + 2\e k) / 2);
* otherwise, reject and start over at step 1.
* -# Set \e x = \e k + \e x.
* -# With probability 1/2, negate \e x.
* -# Return \e x.
* .
* It is easy to show that this algorithm returns samples from the normal
* distribution with zero mean and unit variance. Futhermore, all these
* steps can be carried out exactly as follows:
* - Step 1:
* - \e k = 0;
* - while (ExpProb(&minus;1/2)) increment \e k by 1.
* - Step 2:
* - \e n = \e k (\e k &minus; 1) / 2;
* - while (\e n > 0)
* { if (!ExpProb(&minus;1/2)) go to step 1; decrement \e n by 1; }
* - Step 4:
* - repeat \e k + 1 times:
* if (!ExpProb(&minus; \e x (\e x + 2\e k) / (2\e k + 2))) go to step 1.
* .
* Here, ExpProb(&minus;\e p) returns true with probability exp(&minus;\e p).
* With \e p = 1/2 (steps 1 and 2), this is implemented with von Neumann's
* rejection technique:
* - Generate a sequence of random numbers <i>U</i><sub><i>i</i></sub> and
* find the greatest \e n such that 1/2 > <i>U</i><sub>1</sub> >
* <i>U</i><sub>2</sub> > . . . > <i>U</i><sub><i>n</i></sub>. (The
* resulting value of \e n may be 0.)
* - If \e n is even, accept and return true; otherwise (\e n odd), reject
* and return false.
* .
* For \e p = \e x (\e x + 2\e k) / (2\e k + 2) (step 4), we generalize von
* Neumann's procedure as follows:
* - Generate two sequences of random numbers <i>U</i><sub><i>i</i></sub>
* and <i>V</i><sub><i>i</i></sub> and find the greatest \e n such that
* both the following conditions hold
* - \e x > <i>U</i><sub>1</sub> > <i>U</i><sub>2</sub> > . . . >
* <i>U</i><sub><i>n</i></sub>;
* - <i>V</i><sub><i>i</i></sub> &lt; (\e x + 2 \e k) / (2 \e k + 2) for
* all \e i in [1, \e n].
* .
* (The resulting value of \e n may be 0.)
* - If \e n is even, accept (return true); otherwise (\e n odd), reject
* (return false).
* .
* Here, instead of testing <i>V</i><sub><i>i</i></sub> &lt; (\e x + 2 \e k)
* / (2 \e k + 2), we carry out the following tests:
* - return true, with probability 2 \e k / (2 \e k + 2);
* - return false, with probability 1 / (2 \e k + 2);
* - otherwise (also with probability 1 / (2 \e k + 2)),
* return \e x > <i>V</i><sub><i>i</i></sub>.
* .
* The resulting method now entails evaluation of simple fractional
* probabilities (e.g., 1 / (2 \e k + 2)), or comparing random numbers (e.g.,
* <i>U</i><sub>1</sub> > <i>U</i><sub>2</sub>). These may be carried out
* exactly with a finite mean running time.
*
* With \e bits = 1, this consumes 30.1 digits on average and the result has
* 1.19 digits in the fraction. It takes about 676 ns to generate a result
* (1460 ns, including the time to round it to a double). With bits = 32, it
* takes 437 ns to generate a result (621 ns, including the time to round it
* to a double). In contrast, NormalDistribution takes about 44 ns to
* generate a double result.
*
* Another way of assessing the efficiency of the algorithm is thru the mean
* value of the balance = (number of random bits consumed) &minus; (number of
* bits in the result). If we code the result in Knuth & Yao's unary-binary
* notation, then the mean balance is 26.6.
*
* For example the following samples from a normal exponential distribution
* and prints various representations of the result.
* \code
#include <RandomLib/RandomNumber.hpp>
#include <RandomLib/ExactNormal.hpp>
RandomLib::Random r;
const int bits = 1;
RandomLib::ExactNormal<bits> ndist;
for (size_t i = 0; i < 10; ++i) {
RandomLib::RandomNumber<bits> x = ndist(r); // Sample
std::pair<double, double> z = x.Range();
std::cout << x << " = " // Print in binary with ellipsis
<< "(" << z.first << "," << z.second << ")"; // Print range
double v = x.Value<double>(r); // Round exactly to nearest double
std::cout << " = " << v << "\n";
}
\endcode
* Here's a possible result: \verbatim
-1.00... = (-1.25,-1) = -1.02142
-0.... = (-1,0) = -0.319708
0.... = (0,1) = 0.618735
-0.0... = (-0.5,0) = -0.396591
0.0... = (0,0.5) = 0.20362
0.0... = (0,0.5) = 0.375662
-1.111... = (-2,-1.875) = -1.88295
-1.10... = (-1.75,-1.5) = -1.68088
-0.... = (-1,0) = -0.577547
-0.... = (-1,0) = -0.890553
\endverbatim
* First number is in binary with ... indicating an infinite sequence of
* random bits. Second number gives the corresponding interval. Third
* number is the result of filling in the missing bits and rounding exactly
* to the nearest representable double.
*
* This class uses some mutable RandomNumber objects. So a single
* ExactNormal object cannot safely be used by multiple threads. In a
* multi-processing environment, each thread should use a thread-specific
* ExactNormal object. In addition, these should be invoked with
* thread-specific random generator objects.
*
* @tparam bits the number of bits in each digit.
**********************************************************************/
template<int bits = 1> class ExactNormal {
public:
/**
* Return a random deviate with a normal distribution of mean 0 and
* variance 1.
*
* @tparam Random the type of the random generator.
* @param[in,out] r a random generator.
* @return the random sample.
**********************************************************************/
template<class Random> RandomNumber<bits> operator()(Random& r) const;
private:
/**
* Return true with probability exp(&minus;1/2). For \e bits = 1, this
* consumes, on average, \e t = 2.846 random digits. We have \e t = \e a
* (1&minus;exp(&minus;1/2)) + \e b exp(&minus;1/2), where \e a is the mean
* bit count for false result = 3.786 and \e b is the mean bit count for
* true result = 2.236.
**********************************************************************/
template<class Random> bool ExpProbH(Random& r) const;
/**
* Return true with probability exp(&minus;<i>n</i>/2). For \e bits = 1,
* this consumes, on average, \e t
* (1&minus;exp(&minus;<i>n</i>/2))/(1&minus;exp(&minus;1/2)) random
* digits. A true result uses \e n \e b random digits. A false result
* uses \e a + \e b [exp(&minus;1/2)/(1&minus;exp(&minus;1/2)) &minus;
* <i>n</i> exp(&minus;<i>n</i>/2)/(1&minus;exp(&minus;<i>n</i>/2))] random
* digits.
**********************************************************************/
template<class Random> bool ExpProb(Random& r, unsigned n) const;
/**
* Return \e n with probability exp(&minus;<i>n</i>/2)
* (1&minus;exp(&minus;1/2)). For \e bits = 1, this consumes \e n \e a +
* \e b random digits if the result is \e n. Averaging over \e n this
* becomes (\e b &minus; (\e b &minus; \e a) exp(&minus;1/2))/(1 &minus;
* exp(&minus;1/2)) digits.
**********************************************************************/
template<class Random> unsigned ExpProbN(Random& r) const;
/**
* Return true with probability 1/2. This is similar to r.Boolean() but
* forces all the random results to come thru RandomNumber::RandomDigit.
**********************************************************************/
template<class Random> static bool Boolean(Random& r) {
// A more general implementation which deals with the case where the base
// might be negative is:
//
// const unsigned base = 1u << bits;
// unsigned b;
// do
// b = RandomNumber<bits>::RandomDigit(r);
// while (b == (base / 2) * 2);
// return b & 1u;
return RandomNumber<bits>::RandomDigit(r) & 1u;
}
/**
* Implement outcomes for choosing with prob (\e x + 2\e k) / (2\e k + 2);
* return:
* - 1 (succeed unconditionally) with prob (2\e k) / (2\e k + 2),
* - 0 (succeed with probability x) with prob 1 / (2\e k + 2),
* - &minus;1 (fail unconditionally) with prob 1 / (2\e k + 2).
* .
* This simulates \code
double x = r.Fixed(); // Uniform in [0,1)
x *= (2 * k + 2);
return x < 2 * k ? 1 : (x < 2 * k + 1 ? 0 : -1);
\endcode
**********************************************************************/
template<class Random> static int Choose(Random& r, int k) {
// Limit base to 2^15 to avoid integer overflow
const int b = bits > 15 ? 15 : bits;
const unsigned mask = (1u << b) - 1;
const int m = 2 * k + 2;
int n1 = m - 2, n2 = m - 1;
// Evaluate u < n/m where u is a random real number in [0,1). Write u =
// (d + u') / 2^b where d is a random integer in [0,2^b) and u' is in
// [0,1). Then u < n/m becomes u' < n'/m where n' = 2^b * n - d * m and
// exit if n' <= 0 (false) or n' >= m (true).
while (true) {
int d = (mask & RandomNumber<bits>::RandomDigit(r)) * m;
n1 = (std::max)((n1 << b) - d, 0);
if (n1 >= m) return 1;
n2 = (std::min)((n2 << b) - d, m);
if (n2 <= 0) return -1;
if (n1 == 0 && n2 == m) return 0;
}
}
mutable RandomNumber<bits> _x;
mutable RandomNumber<bits> _p;
mutable RandomNumber<bits> _q;
};
template<int bits> template<class Random>
bool ExactNormal<bits>::ExpProbH(Random& r) const {
// Bit counts
// ExpProbH: 2.846 = 3.786 * (1-exp(-1/2)) + 2.236 * exp(-1/2)
// t = a * (1-exp(-1/2)) + b * exp(-1/2)
// t = mean bit count for result = 2.846
// a = mean bit count for false result = 3.786
// b = mean bit count for true result = 2.236
//
// for bits large
// t = exp(1/2) = 1.6487
// a = exp(1/2)/(2*(1-exp(-1/2))) = 2.0951
// b = exp(1/2)/(2*exp(-1/2)) = 1.3591
//
// Results for Prob(exp(-1)), omitting first test
// total = 5.889, false = 5.347, true = 6.826
//
// Results for Prob(exp(-1)) using ExpProbH(r) && ExpProbH(r),
// total = 4.572 = (1 - exp(-1)) * a + (1 + exp(-1/2)) * exp(-1/2) * b
// false = 4.630 = a + b * exp(-1/2)/(1 + exp(-1/2)),
// true = 4.472 = 2 * b
_p.Init();
if (_p.Digit(r, 0) >> (bits - 1)) return true;
while (true) {
_q.Init(); if (!_q.LessThan(r, _p)) return false;
_p.Init(); if (!_p.LessThan(r, _q)) return true;
}
}
template<int bits> template<class Random>
bool ExactNormal<bits>::ExpProb(Random& r, unsigned n) const {
// Bit counts
// ExpProb(n): t * (1-exp(-n/2))/(1-exp(-1/2))
// ExpProb(n) = true: n * b
// ExpProb(n) = false: a +
// b * (exp(-1/2)/(1-exp(-1/2)) - n*exp(-n/2)/(1-exp(-n/2)))
while (n--) { if (!ExpProbH(r)) return false; }
return true;
}
template<int bits> template<class Random>
unsigned ExactNormal<bits>::ExpProbN(Random& r) const {
// Bit counts
// ExpProbN() = n: n * a + b
unsigned n = 0;
while (ExpProbH(r)) ++n;
return n;
}
template<int bits> template<class Random> RandomNumber<bits>
ExactNormal<bits>::operator()(Random& r) const {
// With bits = 1,
// - mean number of bits used = 30.10434
// - mean number of bits in fraction = 1.18700
// - mean number of bits in result = 3.55257 (unary-binary)
// - mean balance = 30.10434 - 3.55257 = 26.55177
// - mean number of bits to generate a double = 83.33398
// .
// Note
// - unary-binary notation (Knuth + Yao, 1976): write x = n + y, with n =
// integer and y in [0,1). If n >=0, then write (n+1) 1's followed by a
// 0; otherwise (n < 0), write (-n) 0's followed by a 1. Write y as a
// binary fraction.
// - (bits in result) - (bits in fraction) = 2 (for encoding overhead for
// the integer part) + 0.36557, where 0.36557 = (bits used for integer
// part) = sum(k*int(sqrt(2/pi)*exp(-x^2/2), x=k..k+1), k=0..inf)
// - (bits for double) approx (bits used) - (bits in fraction) + 1 (for
// guard bit) + 53.41664 where 53.41664 = (bits in fraction of double) =
// sum((52-l)*int(sqrt(2/pi)*exp(-x^2/2), x=2^l,2^(l+1)), l=-inf..inf)
// This is approximate because it doesn't account for the minimum
// exponent, denormalized numbers, and rounding changing the exponent.
//
while (true) {
// Executed sqrt(2/pi)/(1-exp(-1/2)) = 2.027818889827955 times on
// average.
unsigned k = ExpProbN(r); // the integer part of the result.
if (ExpProb(r, (k - 1) * k)) {
// Probability that this test succeeds is
// (1 - exp(-1/2)) * sum(exp(-k/2) * exp(-(k-1)*k/2), k=0..inf))
// = (1 - exp(-1/2)) * G = 0.689875359564630
// where G = sum(exp(-k^2/2, k=0..inf) = 1.75331414402145
// For k == 0, sample from exp(-x^2/2) for x in [0,1]. This succeeds
// with probability int(exp(-x^2/2),x=0..1).
//
// For general k, substitute x' = x + k in exp(-x'^2/2), and obtain
// exp(-k^2/2) * exp(-x*(x+2*k)/2). So sample from exp(-x*(x+2*k)/2).
// This succeeds with probability int(exp(-x*(x+2*k)/2),x=0..1) =
// int(exp(-x^2/2),x=k..k+1)*exp(k^2/2) =
//
// 0.8556243918921 for k = 0
// 0.5616593588061 for k = 1
// 0.3963669350376 for k = 2
// 0.2974440159655 for k = 3
// 0.2345104783458 for k = 4
// 0.1921445042826 for k = 5
//
// Returns a result with prob sqrt(pi/2) / G = 0.714825772431666;
// otherwise another trip through the outer loop is taken.
_x.Init();
unsigned s = 1;
for (unsigned j = 0; j <= k; ++j) { // execute k + 1 times
bool first;
for (s = 1, first = true; ; s ^= 1, first = false) {
// A simpler algorithm is indicated by ALT, results in
// - mean number of bits used = 29.99968
// - mean number of bits in fraction = 1.55580
// - mean number of bits in result = 3.92137 (unary-binary)
// - mean balance = 29.99968 - 3.92137 = 26.07831
// - mean number of bits to generate a double = 82.86049
// .
// This has a smaller balance (by 0.47 bits). However the number
// of bits in the fraction is larger by 0.37
if (first) { // ALT: if (false) {
// This implements the success prob (x + 2*k) / (2*k + 2).
int y = Choose(r, k);
if (y < 0) break; // the y test fails
_q.Init();
if (y > 0) { // the y test succeeds just test q < x
if (!_q.LessThan(r, _x)) break;
} else { // the y test is ambiguous
// Test max(q, p) < x. List _q before _p since it ends up with
// slightly more digits generated (and these will be used
// subsequently). (_p's digits are immediately thrown away.)
_p.Init(); if (!_x.GreaterPair(r, _q, _p)) break;
}
} else {
// Split off the failure test for k == 0, i.e., factor the prob
// x/2 test into the product: 1/2 (here) times x (in assignment
// of y).
if (k == 0 && Boolean(r)) break;
// ALT: _q.Init(); if (!_q.LessThan(r, first ? _x : _p)) break;
_q.Init(); if (!_q.LessThan(r, _p)) break;
// succeed with prob k == 0 ? x : (x + 2*k) / (2*k + 2)
int y = k == 0 ? 0 : Choose(r, k);
if (y < 0)
break;
else if (y == 0) {
_p.Init(); if (!_p.LessThan(r, _x)) break;
}
}
_p.swap(_q); // a fast way of doing p = q
}
if (s == 0) break;
}
if (s != 0) {
_x.AddInteger(k);
if (Boolean(r)) _x.Negate(); // half of the numbers are negative
return _x;
}
}
}
}
} // namespace RandomLib
#if defined(_MSC_VER)
# pragma warning (pop)
#endif
#endif // RANDOMLIB_EXACTNORMAL_HPP

View File

@ -1,100 +0,0 @@
/**
* \file ExactPower.hpp
* \brief Header for ExactPower
*
* Sample exactly from a power distribution.
*
* Copyright (c) Charles Karney (2006-2011) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* http://randomlib.sourceforge.net/
**********************************************************************/
#if !defined(RANDOMLIB_EXACTPOWER_HPP)
#define RANDOMLIB_EXACTPOWER_HPP 1
#include <RandomLib/RandomNumber.hpp>
namespace RandomLib {
/**
* \brief Sample exactly from a power distribution.
*
* Sample exactly from power distribution (<i>n</i> + 1)
* <i>x</i><sup><i>n</i></sup> for \e x in (0,1) and integer \e n &ge; 0 using
* infinite precision. The template parameter \e bits specifies the number
* of bits in the base used for RandomNumber (i.e., base =
* 2<sup><i>bits</i></sup>).
*
* This class uses some mutable RandomNumber objects. So a single ExactPower
* object cannot safely be used by multiple threads. In a multi-processing
* environment, each thread should use a thread-specific ExactPower object.
* In addition, these should be invoked with thread-specific random generator
* objects.
*
* @tparam bits the number of bits in each digit.
**********************************************************************/
template<int bits = 1> class ExactPower {
public:
/**
* Return the random deviate with a power distribution, (<i>n</i> + 1)
* <i>x</i><sup><i>n</i></sup> for \e x in (0,1) and integer \e n &ge; 0.
* Returned result is a RandomNumber with base 2<sup><i>bits</i></sup>.
* For \e bits = 1, the number of random bits in the result and consumed
* are as follows: \verbatim
n random bits
result consumed
0 0 0
1 2 4
2 2.33 6.67
3 2.67 9.24
4 2.96 11.71
5 3.20 14.11
6 3.41 16.45
7 3.59 18.75
8 3.75 21.01
9 3.89 23.25
10 4.02 25.47
\endverbatim
* The relative frequency of the results with \e bits = 1 and \e n = 2 can
* be is shown by the histogram
* \image html powerhist.png
* The base of each rectangle gives the range represented by the
* corresponding binary number and the area is proportional to its
* frequency. A PDF version of this figure
* <a href="powerhist.pdf">here</a>. This allows the figure to be
* magnified to show the rectangles for all binary numbers up to 9 bits.
*
* @tparam Random the type of the random generator.
* @param[in,out] r a random generator.
* @param[in] n the power.
* @return the random sample.
**********************************************************************/
template<class Random>
RandomNumber<bits> operator()(Random& r, unsigned n) const;
private:
mutable RandomNumber<bits> _x;
mutable RandomNumber<bits> _y;
};
template<int bits> template<class Random> RandomNumber<bits>
ExactPower<bits>::operator()(Random& r, unsigned n) const {
// Return max(u_0, u_1, u_2, ..., u_n). Equivalent to taking the
// (n+1)th root of u_0.
_x.Init();
for (; n--;) {
_y.Init();
// For bits = 1, we can save 1 bit on the first iteration by using a
// technique suggested by Knuth and Yao (1976). When comparing the
// digits of x and y, use 1 bit to determine if the digits are the same.
// If they are, then use another bit for the value of the digit. If they
// are not, then the next bit of the maximum must be 1 (avoiding using a
// second bit). Applying this optimization to subsequent iterations
// (when x already is filled with some bits) gets trickier.
if (_x.LessThan(r, _y))
_x.swap(_y); // x = y;
}
return _x;
}
} // namespace RandomLib
#endif // RANDOMLIB_EXACTPOWER_HPP

View File

@ -1,69 +0,0 @@
/**
* \file ExponentialDistribution.hpp
* \brief Header for ExponentialDistribution
*
* Sample from an exponential distribution.
*
* Copyright (c) Charles Karney (2006-2011) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* http://randomlib.sourceforge.net/
**********************************************************************/
#if !defined(RANDOMLIB_EXPONENTIALDISTRIBUTION_HPP)
#define RANDOMLIB_EXPONENTIALDISTRIBUTION_HPP 1
#include <cmath>
namespace RandomLib {
/**
* \brief The exponential distribution.
*
* Sample from the distribution exp(&minus;<i>x</i>/&mu;) for \e x &ge; 0.
* This uses the logarithm method, see Knuth, TAOCP, Vol 2, Sec 3.4.1.D.
* Example \code
#include <RandomLib/ExponentialDistribution.hpp>
RandomLib::Random r;
std::cout << "Seed set to " << r.SeedString() << "\n";
RandomLib::ExponentialDistribution<double> expdist;
std::cout << "Select from exponential distribution:";
for (size_t i = 0; i < 10; ++i)
std::cout << " " << expdist(r);
std::cout << "\n";
\endcode
*
* @tparam RealType the real type of the results (default double).
**********************************************************************/
template<typename RealType = double> class ExponentialDistribution {
public:
/**
* The type returned by ExponentialDistribution::operator()(Random&)
**********************************************************************/
typedef RealType result_type;
/**
* Return a sample of type RealType from the exponential distribution and
* mean &mu;. This uses Random::FloatU() which avoids taking log(0) and
* allows rare large values to be returned. If &mu; = 1, minimum returned
* value = 0 with prob 1/2<sup><i>p</i></sup>; maximum returned value =
* log(2)(\e p + \e e) with prob 1/2<sup><i>p</i> + <i>e</i></sup>. Here
* \e p is the precision of real type RealType and \e e is the exponent
* range.
*
* @tparam Random the type of RandomCanonical generator.
* @param[in,out] r the RandomCanonical generator.
* @param[in] mu the mean value of the exponential distribution (default 1).
* @return the random sample.
**********************************************************************/
template<class Random>
RealType operator()(Random& r, RealType mu = RealType(1)) const throw();
};
template<typename RealType> template<class Random> inline RealType
ExponentialDistribution<RealType>::operator()(Random& r, RealType mu) const
throw() {
return -mu * std::log(r.template FloatU<RealType>());
}
} // namespace RandomLib
#endif // RANDOMLIB_EXPONENTIALDISTRIBUTION_HPP

View File

@ -1,166 +0,0 @@
/**
* \file ExponentialProb.hpp
* \brief Header for ExponentialProb
*
* Return true with probabililty exp(-\e p).
*
* Copyright (c) Charles Karney (2006-2012) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* http://randomlib.sourceforge.net/
**********************************************************************/
#if !defined(RANDOMLIB_EXPONENTIALPROB_HPP)
#define RANDOMLIB_EXPONENTIALPROB_HPP 1
#include <vector>
#include <limits>
#if defined(_MSC_VER)
// Squelch warnings about constant conditional expressions
# pragma warning (push)
# pragma warning (disable: 4127)
#endif
namespace RandomLib {
/**
* \brief The exponential probability.
*
* Return true with probability exp(&minus;\e p). Basic method taken from:\n
* J. von Neumann,\n Various Techniques used in Connection with Random
* Digits,\n J. Res. Nat. Bur. Stand., Appl. Math. Ser. 12, 36--38
* (1951),\n reprinted in Collected Works, Vol. 5, 768--770 (Pergammon,
* 1963).\n See also the references given for the ExactExponential class.
*
* Here the method is extended to be exact by generating sufficient bits in
* the random numbers in the algorithm to allow the unambiguous comparisons
* to be made.
*
* Here's one way of sampling from a normal distribution with zero mean and
* unit variance in the interval [&minus;1,1] with reasonable accuracy:
* \code
#include <RandomLib/Random.hpp>
#include <RandomLib/ExponentialProb.hpp>
double Normal(RandomLib::Random& r) {
double x;
RandomLib::ExponentialProb e;
do
x = r.FloatW();
while ( !e(r, - 0.5 * x * x) );
return x;
}
\endcode
* (Note that the ExactNormal class samples from the normal distribution
* exactly.)
*
* This class uses a mutable private vector. So a single ExponentialProb
* object cannot safely be used by multiple threads. In a multi-processing
* environment, each thread should use a thread-specific ExponentialProb
* object.
**********************************************************************/
class ExponentialProb {
private:
typedef unsigned word;
public:
ExponentialProb() : _v(std::vector<word>(alloc_incr)) {}
/**
* Return true with probability exp(&minus;\e p). Returns false if \e p
* &le; 0. For in \e p (0,1], it requires about exp(\e p) random deviates.
* For \e p large, it requires about exp(1)/(1 &minus; exp(&minus;1))
* random deviates.
*
* @tparam RealType the real type of the argument.
* @tparam Random the type of the random generator.
* @param[in,out] r a random generator.
* @param[in] p the probability.
* @return true with probability \e p.
**********************************************************************/
template<typename RealType, class Random>
bool operator()(Random& r, RealType p) const;
private:
/**
* Return true with probability exp(&minus;\e p) for \e p in [0,1].
**********************************************************************/
template<typename RealType, class Random>
bool ExpFraction(Random& r, RealType p) const;
/**
* Holds as much of intermediate uniform deviates as needed.
**********************************************************************/
mutable std::vector<word> _v;
/**
* Increment on size of _v.
**********************************************************************/
static const unsigned alloc_incr = 16;
};
template<typename RealType, class Random>
bool ExponentialProb::operator()(Random& r, RealType p) const {
STATIC_ASSERT(!std::numeric_limits<RealType>::is_integer,
"ExponentialProb(): invalid real type RealType");
return p <= 0 || // True if p <=0
// Ensure p - 1 < p. Also deal with IsNaN(p)
( p < RealType(1)/std::numeric_limits<RealType>::epsilon() &&
// exp(a+b) = exp(a) * exp(b)
ExpFraction(r, p < RealType(1) ? p : RealType(1)) &&
( p <= RealType(1) || operator()(r, p - RealType(1)) ) );
}
template<typename RealType, class Random>
bool ExponentialProb::ExpFraction(Random& r, RealType p) const {
// Base of _v is 2^c. Adjust so that word(p) doesn't lose precision.
static const int c = // The Intel compiler needs this to be static??
std::numeric_limits<word>::digits <
std::numeric_limits<RealType>::digits ?
std::numeric_limits<word>::digits :
std::numeric_limits<RealType>::digits;
// m gives number of valid words in _v
unsigned m = 0, l = unsigned(_v.size());
if (p < RealType(1))
while (true) {
if (p <= RealType(0))
return true;
// p in (0, 1)
if (l == m)
_v.resize(l += alloc_incr);
_v[m++] = r.template Integer<word, c>();
p *= std::pow(RealType(2), c); // p in (0, 2^c)
word w = word(p); // w in [0, 2^c)
if (_v[m - 1] > w)
return true;
else if (_v[m - 1] < w)
break;
else // _v[m - 1] == w
p -= RealType(w); // p in [0, 1)
}
// Here _v < p. Now loop finding decreasing V. Exit when first increasing
// one is found.
for (unsigned s = 0; ; s ^= 1) { // Parity of loop count
for (unsigned j = 0; ; ++j) {
if (j == m) {
// Need more bits in the old V
if (l == m)
_v.resize(l += alloc_incr);
_v[m++] = r.template Integer<word, c>();
}
word w = r.template Integer<word, c>();
if (w > _v[j])
return s != 0u; // New V is bigger, so exit
else if (w < _v[j]) {
_v[j] = w; // New V is smaller, update _v
m = j + 1; // adjusting its size
break; // and generate the next V
}
// Else w == _v[j] and we need to check the next c bits
}
}
}
} // namespace RandomLib
#if defined(_MSC_VER)
# pragma warning (pop)
#endif
#endif // RANDOMLIB_EXPONENTIALPROB_HPP

View File

@ -1,67 +0,0 @@
/**
* \file InverseEProb.hpp
* \brief Header for InverseEProb
*
* Return true with probabililty 1/\e e.
*
* Copyright (c) Charles Karney (2012) <charles@karney.com> and licensed under
* the MIT/X11 License. For more information, see
* http://randomlib.sourceforge.net/
**********************************************************************/
#if !defined(RANDOMLIB_INVERSEEPROB_HPP)
#define RANDOMLIB_INVERSEEPROB_HPP 1
#include <vector>
#include <RandomLib/Random.hpp>
namespace RandomLib {
/**
* \brief Return true with probability 1/\e e = exp(&minus;1).
*
* InverseEProb p; p(Random& r) returns true with prob 1/\e e using von
* Neumann's rejection method. It consumes 4.572 bits per call on average.
*
* This class illustrates how to return an exact result using coin tosses
* only. A more efficient way of returning an exact result would be to use
* ExponentialProb p; p(r, 1.0f);
**********************************************************************/
class InverseEProb {
private:
mutable std::vector<bool> _p;
template<class Random> bool exph(Random& r) {
// Return true with prob 1/sqrt(e).
if (r.Boolean()) return true;
_p.clear(); // vector of bits in p
_p.push_back(false);
for (bool s = false; ; s = !s) { // s is a parity
for (size_t i = 0; ; ++i) { // Compare bits of p and q
if (i == _p.size())
_p.push_back(r.Boolean()); // Generate next bit of p if necessary
if (r.Boolean()) { // Half the time the bits differ
if (_p[i]) { // p's bit is 1, so q is smaller, update p
_p[i] = false; // Last bit of q 0
if (++i < _p.size()) _p.resize(i); // p = q
break;
} else
return s; // p's bit is 0, so q is bigger, return parity
} // The other half of the time the bits match, so go to next bit
}
}
}
public:
/**
* Return true with probability 1/\e e.
*
* @tparam Random the type of the random generator.
* @param[in,out] r a random generator.
* @return true with probability 1/\e e.
**********************************************************************/
template<class Random> bool operator()(Random& r)
{ return exph(r) && exph(r); }
};
} // namespace RandomLib
#endif // RANDOMLIB_INVERSEEPROB_HPP

View File

@ -1,150 +0,0 @@
/**
* \file InversePiProb.hpp
* \brief Header for InversePiProb
*
* Return true with probabililty 1/&pi;.
*
* Copyright (c) Charles Karney (2012) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* http://randomlib.sourceforge.net/
**********************************************************************/
#if !defined(RANDOMLIB_INVERSEPIPROB_HPP)
#define RANDOMLIB_INVERSEPIPROB_HPP 1
#include <cstdlib> // for abs(int)
#include <RandomLib/Random.hpp>
namespace RandomLib {
/**
* \brief Return true with probability 1/&pi;.
*
* InversePiProb p; p(Random& r) returns true with prob 1/&pi; using the
* method of Flajolet et al. It consumes 9.6365 bits per call on average.
*
* The method is given in Section 3.3 of
* - P. Flajolet, M. Pelletier, and M. Soria,<br>
* On Buffon Machines and Numbers,<br> Proc. 22nd ACM-SIAM Symposium on
* Discrete Algorithms (SODA), Jan. 2011.<br>
* http://www.siam.org/proceedings/soda/2011/SODA11_015_flajoletp.pdf <br>
* .
* using the identity
* \f[ \frac 1\pi = \sum_{n=0}^\infty
* {{2n}\choose n}^3 \frac{6n+1}{2^{8n+2}} \f]
*
* It is based on the expression for 1/&pi; given by Eq. (28) of<br>
* - S. Ramanujan,<br>
* Modular Equations and Approximations to &pi;,<br>
* Quart. J. Pure App. Math. 45, 350--372 (1914);<br>
* In Collected Papers, edited by G. H. Hardy, P. V. Seshu Aiyar,
* B. M. Wilson (Cambridge Univ. Press, 1927; reprinted AMS, 2000).<br>
* http://books.google.com/books?id=oSioAM4wORMC&pg=PA36 <br>
* .
* \f[\frac4\pi = 1 + \frac74 \biggl(\frac 12 \biggr)^3
* + \frac{13}{4^2} \biggl(\frac {1\cdot3}{2\cdot4} \biggr)^3
* + \frac{19}{4^3} \biggl(\frac {1\cdot3\cdot5}{2\cdot4\cdot6} \biggr)^3
* + \ldots \f]
*
* The following is a description of how to carry out the algorithm "by hand"
* with a real coin, together with a worked example:
* -# Perform three coin tossing experiments in which you toss a coin until
* you get tails, e.g., <tt>HHHHT</tt>; <tt>HHHT</tt>; <tt>HHT</tt>. Let
* <i>h</i><sub>1</sub> = 4, <i>h</i><sub>2</sub> = 3,
* <i>h</i><sub>3</sub> = 2 be the numbers of heads tossed in each
* experiment.
* -# Compute <i>n</i> = &lfloor;<i>h</i><sub>1</sub>/2&rfloor; +
* &lfloor;<i>h</i><sub>2</sub>/2&rfloor; +
* mod(&lfloor;(<i>h</i><sub>3</sub> &minus; 1)/3&rfloor;, 2) = 2 + 1 + 0
* = 3. Here is a table of the 3 contributions to <i>n</i>:\verbatim
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 h
0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 floor(h1/2)
0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 floor(h2/2)
1 0 0 0 1 1 1 0 0 0 1 1 1 0 0 0 1 1 mod(floor((h3-1)/3), 2)
\endverbatim
* -# Perform three additional coin tossing experiments in each of which you
* toss a coin 2<i>n</i> = 6 times, e.g., <tt>TTHHTH</tt>;
* <tt>HHTHH|H</tt>; <tt>THHHHH</tt>. Are the number of heads and tails
* equal in each experiment? <b>yes</b> and <b>no</b> and <b>no</b> &rarr;
* <b>false</b>. (Here, you can give up at the |.)
* .
* The final result in this example is <b>false</b>. The most common way a
* <b>true</b> result is obtained is with <i>n</i> = 0, in which case the
* last step vacuously returns <b>true</b>.
*
* Proof of the algorithm: Flajolet et al. rearrange Ramanujan's identity as
* \f[ \frac 1\pi = \sum_{n=0}^\infty
* \biggl[{2n\choose n} \frac1{2^{2n}} \biggr]^3
* \frac{6n+1}{2^{2n+2}}. \f]
* Noticing that
* \f[ \sum_{n=0}^\infty
* \frac{6n+1}{2^{2n+2}} = 1, \f]
* the algorithm becomes:
* -# pick <i>n</i> &ge; 0 with prob (6<i>n</i>+1) / 2<sup>2<i>n</i>+2</sup>
* (mean <i>n</i> = 11/9);
* -# return <b>true</b> with prob (binomial(2<i>n</i>, <i>n</i>) /
* 2<sup>2<i>n</i></sup>)<sup>3</sup>.
*
* Implement (1) as
* - geom4(r) + geom4(r) returns <i>n</i> with probability 9(<i>n</i> +
* 1) / 2<sup>2<i>n</i>+4</sup>;
* - geom4(r) + geom4(r) + 1 returns <i>n</i> with probability
* 36<i>n</i> / 2<sup>2<i>n</i>+4</sup>;
* - combine these with probabilities [4/9, 5/9] to yield (6<i>n</i> +
* 1) / 2<sup>2<i>n</i>+2</sup>, as required.
* .
* Implement (2) as the outcome of 3 coin tossing experiments of 2<i>n</i>
* tosses with success defined as equal numbers of heads and tails in each
* trial.
*
* This class illustrates how to return an exact result using coin tosses
* only. A more efficient implementation (which is still exact) would
* replace prob59 by r.Prob(5,9) and geom4 by LeadingZeros z; z(r)/2.
**********************************************************************/
class InversePiProb {
private:
template<class Random> bool prob59(Random& r) {
// true with prob 5/9 = 0.1 000 111 000 111 000 111 ... (binary expansion)
if (r.Boolean()) return true;
for (bool res = false; ; res = !res)
for (int i = 3; i--; ) if (r.Boolean()) return res;
}
template<class Random> int geom4(Random& r) { // Geom(1/4)
int sum = 0;
while (r.Boolean() && r.Boolean()) ++sum;
return sum;
}
template<class Random> bool binom(Random& r, int n) {
// Probability of equal heads and tails on 2*n tosses
// = binomial(2*n, n) / 2^(2*n)
int d = 0;
for (int k = n; k--; ) d += r.Boolean() ? 1 : -1;
for (int k = n; k--; ) {
d += r.Boolean() ? 1 : -1;
// This optimization saves 0.1686 bit per call to operator() on average.
if (std::abs(d) > k) return false;
}
return true;
}
public:
/**
* Return true with probability 1/&pi;.
*
* @tparam Random the type of the random generator.
* @param[in,out] r a random generator.
* @return true with probability 1/&pi;.
**********************************************************************/
template<class Random> bool operator()(Random& r) {
// Return true with prob 1/pi.
int n = geom4(r) + geom4(r) + (prob59(r) ? 1 : 0);
for (int j = 3; j--; ) if (!binom(r, n)) return false;
return true;
}
};
} // namespace RandomLib
#endif // RANDOMLIB_INVERSEPIPROB_HPP

View File

@ -1,84 +0,0 @@
/**
* \file LeadingZeros.hpp
* \brief Header for LeadingZeros
*
* Count the leading zeros in a real number.
*
* Copyright (c) Charles Karney (2006-2011) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* http://randomlib.sourceforge.net/
**********************************************************************/
#if !defined(RANDOMLIB_LEADINGZEROS_HPP)
#define RANDOMLIB_LEADINGZEROS_HPP 1
namespace RandomLib {
/**
* \brief Count of leading zeros.
*
* Count of leading zero bits after the binary point in a real number
* uniformly distributed in (0,1). (This is equivalent to the geometric
* distribution with probability 1/2.) For example
* \code
#include <RandomLib/LeadingZeros.hpp>
RandomLib::Random r; // A RandomGenerator works here too
std::cout << "Seed set to " << r.SeedString() << "\n";
LeadingZeros zeros;
std::cout << "Count of leading zeros:";
for (size_t i = 0; i < 20; ++i)
std::cout << " " << zeros(r);
std::cout << "\n";
\endcode
**********************************************************************/
class LeadingZeros {
public:
/**
* Return the number of zero bits after the binary point in a real number
* uniformly distributed in (0,1). Thus \e k is returned with probability
* 1/2<sup><i>k</i>+1</sup>. Because MT19937 is \e not a perfect random
* number generator, this always returns a result in [0, 19937).
*
* @tparam Random the type of the random generator.
* @param[in,out] r a random generator.
* @return the random sample.
**********************************************************************/
template<class Random> unsigned operator()(Random& r) const throw();
};
template<class Random>
unsigned LeadingZeros::operator()(Random& r) const throw() {
// It's simpler to count the number of trailing ones in each w-bit block
// stopping when we get to a zero bit.
//
// Process a word in chunks of size m. The algorithm here can deal with
// any m assuming that z is modified accordingly. m = 4 is an approximate
// optimum.
//
// Can also adapt this routine to use RandomNumber::highest_bit_idx
// instead. However the result is considerably slower.
const int m = 4;
STATIC_ASSERT(m <= Random::width, "LeadingZeros: m too large");
// mask with m low bits set
const typename Random::result_type mask = ~(Random::max << m);
// Number of trailing 1 bits in [0, 1<<m). However, correct results are
// also obtained with any permutation of this array. This particular
// permutation is useful since the initial 1/2, 1/4, etc. can be used for
// m-1, m-2, etc. To generate the array for the next higher m, append a
// duplicate of the array and increment the last entry by one.
const unsigned z[1 << m] =
{ 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, };
typename Random::result_type x = r();
for (unsigned b = m, n = 0; b < Random::width; b += m) {
n += z[x & mask]; // count trailing 1s in chunk
if (n < b) // chunk contains a 0
return n;
x >>= m; // shift out the chunk we've processed
}
// x is all ones (prob 1/2^w); process the next word.
return Random::width + operator()(r);
}
} // namespace RandomLib
#endif // RANDOMLIB_LEADINGZEROS_HPP

View File

@ -1,92 +0,0 @@
/**
* \file MPFRExponential.hpp
* \brief Header for MPFRExponential
*
* Sampling exactly from the normal distribution for MPFR.
*
* Copyright (c) Charles Karney (2012) <charles@karney.com> and licensed under
* the MIT/X11 License. For more information, see
* http://randomlib.sourceforge.net/
**********************************************************************/
#if !defined(RANDOMLIB_MPFREXPONENTIAL_HPP)
#define RANDOMLIB_MPFREXPONENTIAL_HPP 1
#include <RandomLib/MPFRRandom.hpp>
#if HAVE_MPFR || defined(DOXYGEN)
namespace RandomLib {
/**
* \brief The exponential distribution for MPFR.
*
* This is a transcription of ExactExponential (version 1.4) for use with
* MPFR.
*
* This class uses mutable private objects. So a single MPFRExponential
* object cannot safely be used by multiple threads. In a multi-processing
* environment, each thread should use a thread-specific MPFRExponential
* object.
*
* @tparam bits the number of bits in each digit.
**********************************************************************/
template<int bits = 32> class MPFRExponential {
public:
/**
* Initialize the MPFRExponential object.
**********************************************************************/
MPFRExponential() {};
/**
* Sample from the exponential distribution with mean 1 returning a
* MPFRRandom.
*
* @param[out] t the MPFRRandom result.
* @param[in,out] r a GMP random generator.
**********************************************************************/
void operator()(MPFRRandom<bits>& t, gmp_randstate_t r) const
{ Compute(r); _x.swap(t); }
/**
* Sample from the exponential distribution with mean 1.
*
* @param[out] val the sample from the exponential distribution
* @param[in,out] r a GMP random generator.
* @param[in] round the rounding direction.
* @return the MPFR ternary result (&plusmn; if val is larger/smaller than
* the exact sample).
**********************************************************************/
int operator()(mpfr_t val, gmp_randstate_t r, mpfr_rnd_t round) const
{ Compute(r); return _x(val, r, round); }
private:
// Disable copy constructor and assignment operator
MPFRExponential(const MPFRExponential&);
MPFRExponential& operator=(const MPFRExponential&);
int ExpFraction(gmp_randstate_t r, MPFRRandom<bits>& p) const {
// The early bale out
if (p.TestHighBit(r)) return 0;
// Implement the von Neumann algorithm
_w.Init();
if (!_w.LessThan(r, p)) return 1;
while (true) {
_v.Init(); if (!_v.LessThan(r, _w)) return 0;
_w.Init(); if (!_w.LessThan(r, _v)) return 1;
}
}
void Compute(gmp_randstate_t r) const {
_x.Init();
unsigned k = 0;
while (!ExpFraction(r, _x)) { ++k; _x.Init(); }
if (k & 1) _x.SetHighBit(r);
_x.AddInteger(k >> 1);
return;
}
mutable MPFRRandom<bits> _x;
mutable MPFRRandom<bits> _v;
mutable MPFRRandom<bits> _w;
};
} // namespace RandomLib
#endif // HAVE_MPFR
#endif // RANDOMLIB_MPFREXPONENTIAL_HPP

View File

@ -1,123 +0,0 @@
/**
* \file MPFRExponentialL.hpp
* \brief Header for MPFRExponentialL
*
* Sampling exactly from the exponential distribution for MPFR using the
* traditional method.
*
* Copyright (c) Charles Karney (2012) <charles@karney.com> and licensed under
* the MIT/X11 License. For more information, see
* http://randomlib.sourceforge.net/
**********************************************************************/
#if !defined(RANDOMLIB_MPFREXPONENTIALL_HPP)
#define RANDOMLIB_MPFREXPONENTIALL_HPP 1
#include <cmath> // for log
#include <mpfr.h>
#define HAVE_MPFR (MPFR_VERSION_MAJOR >= 3)
#if HAVE_MPFR || defined(DOXYGEN)
namespace RandomLib {
/**
* \brief The exponential distribution for MPFR (the log method).
*
* This class is <b>DEPRECATED</b>. It is included for illustrative purposes
* only. The MPFRExponential class provides a much more efficient method for
* sampling from the exponential distribution.
*
* This is an adaption of ExponentialDistribution to MPFR. The changes are
* - Use MPFR's random number generator
* - Use sufficient precision internally to ensure that a correctly rounded
* result is returned.
*
* This class uses mutable private objects. So a single MPFRExponentialL
* object cannot safely be used by multiple threads. In a multi-processing
* environment, each thread should use a thread-specific MPFRExponentialL
* object.
**********************************************************************/
class MPFRExponentialL {
private:
// The number of bits of randomness to add at a time.
static const long chunk_ = 32;
public:
/**
* Initialize the MPFRExponentialL object.
**********************************************************************/
MPFRExponentialL() {
mpz_init(_vi);
mpfr_init2(_eps, chunk_);
mpfr_init2(_v1, chunk_);
mpfr_init2(_v2, chunk_);
}
/**
* Destroy the MPFRExponentialL object.
**********************************************************************/
~MPFRExponentialL() {
mpfr_clear(_v2);
mpfr_clear(_v1);
mpfr_clear(_eps);
mpz_clear(_vi);
}
/**
* Sample from the exponential distribution with mean 1.
*
* @param[out] val the sample from the exponential distribution
* @param[in,out] r a GMP random generator.
* @param[in] round the rounding direction.
* @return the MPFR ternary result (&plusmn; if val is larger/smaller than
* the exact sample).
**********************************************************************/
int operator()(mpfr_t val, gmp_randstate_t r, mpfr_rnd_t round) const {
mpfr_prec_t prec0 = mpfr_get_prec (val);
mpfr_prec_t prec = prec0 + 10; // A rough optimum
mpz_urandomb(_vi, r, prec);
mpfr_set_ui_2exp(_eps, 1u, -prec, MPFR_RNDN);
mpfr_set_prec(_v1, prec);
mpfr_set_z_2exp(_v1, _vi, -prec, MPFR_RNDN);
mpfr_set_prec(_v2, prec);
mpfr_add(_v2, _v1, _eps, MPFR_RNDN);
while (true) {
int f2 = mpfr_log(val, _v2, round); // val = log(upper bound)
mpfr_set_prec(_v2, prec0);
int f1 = mpfr_log(_v2, _v1, round); // v2 = log(lower bound)
if (f1 == f2 && mpfr_equal_p(val, _v2)) {
mpfr_neg(val, val, MPFR_RNDN);
return -f1;
}
prec = Refine(r, prec);
}
}
private:
// disable copy constructor and assignment operator
MPFRExponentialL(const MPFRExponentialL&);
MPFRExponentialL& operator=(const MPFRExponentialL&);
// Refine the random interval
mpfr_prec_t Refine(gmp_randstate_t r, mpfr_prec_t prec)
const {
prec += chunk_;
mpfr_div_2ui(_eps, _eps, chunk_, MPFR_RNDN);
mpz_urandomb(_vi, r, chunk_);
mpfr_set_prec(_v2, prec);
mpfr_set_z_2exp(_v2, _vi, -prec, MPFR_RNDN);
mpfr_add(_v2, _v1, _v2, MPFR_RNDN);
mpfr_swap(_v1, _v2); // v1 = v2;
mpfr_set_prec(_v2, prec);
mpfr_add(_v2, _v1, _eps, MPFR_RNDN);
return prec;
}
mutable mpz_t _vi;
mutable mpfr_t _eps;
mutable mpfr_t _v1;
mutable mpfr_t _v2;
};
} // namespace RandomLib
#endif // HAVE_MPFR
#endif // RANDOMLIB_MPFREXPONENTIALL_HPP

View File

@ -1,144 +0,0 @@
/**
* \file MPFRNormal.hpp
* \brief Header for MPFRNormal
*
* Sampling exactly from the normal distribution for MPFR.
*
* Copyright (c) Charles Karney (2012) <charles@karney.com> and licensed under
* the MIT/X11 License. For more information, see
* http://randomlib.sourceforge.net/
**********************************************************************/
#if !defined(RANDOMLIB_MPFRNORMAL_HPP)
#define RANDOMLIB_MPFRNORMAL_HPP 1
#include <algorithm> // for max/min
#include <RandomLib/MPFRRandom.hpp>
#if HAVE_MPFR || defined(DOXYGEN)
namespace RandomLib {
/**
* \brief The normal distribution for MPFR.
*
* This is a transcription of ExactNormal (version 1.3) for use with MPFR.
*
* This class uses mutable private objects. So a single MPFRNormal object
* cannot safely be used by multiple threads. In a multi-processing
* environment, each thread should use a thread-specific MPFRNormal object.
*
* @tparam bits the number of bits in each digit.
**********************************************************************/
template<int bits = 32> class MPFRNormal {
public:
/**
* Initialize the MPFRNormal object.
**********************************************************************/
MPFRNormal() { mpz_init(_tt); }
/**
* Destroy the MPFRNormal object.
**********************************************************************/
~MPFRNormal() { mpz_clear(_tt); }
/**
* Sample from the normal distribution with mean 0 and variance 1 returning
* a MPFRRandom.
*
* @param[out] t the MPFRRandom result.
* @param[in,out] r a GMP random generator.
**********************************************************************/
void operator()(MPFRRandom<bits>& t,gmp_randstate_t r) const
{ Compute(r); return _x.swap(t); }
/**
* Sample from the normal distribution with mean 0 and variance 1.
*
* @param[out] val the sample from the normal distribution
* @param[in,out] r a GMP random generator.
* @param[in] round the rounding direction.
* @return the MPFR ternary result (&plusmn;1 if val is larger/smaller than
* the exact sample).
**********************************************************************/
int operator()(mpfr_t val, gmp_randstate_t r, mpfr_rnd_t round) const
{ Compute(r); return _x(val, r, round); }
private:
// Disable copy constructor and assignment operator
MPFRNormal(const MPFRNormal&);
MPFRNormal& operator=(const MPFRNormal&);
// True with prob exp(-1/2)
int ExpProbH(gmp_randstate_t r) const {
_p.Init(); if (_p.TestHighBit(r)) return 1;
// von Neumann rejection
while (true) {
_q.Init(); if (!_q.LessThan(r, _p)) return 0;
_p.Init(); if (!_p.LessThan(r, _q)) return 1;
}
}
// True with prob exp(-n/2)
int ExpProb(gmp_randstate_t r, unsigned n) const {
while (n--) { if (!ExpProbH(r)) return 0; }
return 1;
}
// n with prob (1-exp(-1/2)) * exp(-n/2)
unsigned ExpProbN(gmp_randstate_t r) const {
unsigned n = 0;
while (ExpProbH(r)) ++n;
return n;
}
// Return:
// 1 with prob 2k/(2k + 2)
// 0 with prob 1/(2k + 2)
// -1 with prob 1/(2k + 2)
int Choose(gmp_randstate_t r, int k) const {
const int b = 15; // To avoid integer overflow on multiplication
const int m = 2 * k + 2;
int n1 = m - 2, n2 = m - 1;
while (true) {
mpz_urandomb(_tt, r, b);
int d = int( mpz_get_ui(_tt) ) * m;
n1 = (std::max)((n1 << b) - d, 0);
if (n1 >= m) return 1;
n2 = (std::min)((n2 << b) - d, m);
if (n2 <= 0) return -1;
if (n1 == 0 && n2 == m) return 0;
}
}
void Compute(gmp_randstate_t r) const {
while (true) {
unsigned k = ExpProbN(r); // the integer part of the result.
if (ExpProb(r, (k - 1) * k)) {
_x.Init();
unsigned s = 1;
for (unsigned j = 0; j <= k; ++j) { // execute k + 1 times
bool first;
for (s = 1, first = true; ; s ^= 1, first = false) {
if (k == 0 && _x.Boolean(r)) break;
_q.Init(); if (!_q.LessThan(r, first ? _x : _p)) break;
int y = k == 0 ? 0 : Choose(r, k);
if (y < 0)
break;
else if (y == 0) {
_p.Init(); if (!_p.LessThan(r, _x)) break;
}
_p.swap(_q); // a fast way of doing p = q
}
if (s == 0) break;
}
if (s != 0) {
_x.AddInteger(k);
if (_x.Boolean(r)) _x.Negate();
return;
}
}
}
}
mutable mpz_t _tt; // A temporary
mutable MPFRRandom<bits> _x;
mutable MPFRRandom<bits> _p;
mutable MPFRRandom<bits> _q;
};
} // namespace RandomLib
#endif // HAVE_MPFR
#endif // RANDOMLIB_MPFRNORMAL_HPP

View File

@ -1,138 +0,0 @@
/**
* \file MPFRNormalK.hpp
* \brief Header for MPFRNormalK
*
* Sampling exactly from the normal distribution for MPFR.
*
* Copyright (c) Charles Karney (2012) <charles@karney.com> and licensed under
* the MIT/X11 License. For more information, see
* http://randomlib.sourceforge.net/
**********************************************************************/
#if !defined(RANDOMLIB_MPFRNORMALK_HPP)
#define RANDOMLIB_MPFRNORMALK_HPP 1
#include <algorithm> // for max
#include <RandomLib/MPFRRandom.hpp>
#include <RandomLib/MPFRExponential.hpp>
#if HAVE_MPFR || defined(DOXYGEN)
namespace RandomLib {
/**
* \brief The normal distribution for MPFR (Kahn algorithm).
*
* This class is <b>DEPRECATED</b>. It is included for illustrative purposes
* only. The MPFRNormal class provides a somewhat more efficient method for
* sampling from the normal distribution.
*
* Refs:
* - H. Kahn, Rand Report RM-1237-AEC, p. 41 (1954).
* - M. Abramowitz and I. A. Stegun, p. 953, Sec. 26.8.6.a(4) (1964).
* .
* N.B. Damien Stehle' drew my attention to this algorithm as a useful way to
* compute normal deviates exactly.
*
* This class uses mutable private objects. So a single MPFRNormalK object
* cannot safely be used by multiple threads. In a multi-processing
* environment, each thread should use a thread-specific MPFRNormalK object.
*
* @tparam bits the number of bits in each digit.
**********************************************************************/
template<int bits = 32> class MPFRNormalK {
public:
/**
* Initialize the MPFRNormalK object.
**********************************************************************/
MPFRNormalK()
{ mpfr_init2(_xf, MPFR_PREC_MIN); mpfr_init2(_zf, MPFR_PREC_MIN); }
/**
* Destroy the MPFRNormalK object.
**********************************************************************/
~MPFRNormalK()
{ mpfr_clear(_zf); mpfr_clear(_xf); }
/**
* Sample from the normal distribution with mean 0 and variance 1 returning
* a MPFRRandom.
*
* @param[out] t the MPFRRandom result.
* @param[in,out] r a GMP random generator.
**********************************************************************/
void operator()(MPFRRandom<bits>& t, gmp_randstate_t r) const
{ Compute(r); _x.swap(t); }
/**
* Sample from the normal distribution with mean 0 and variance 1.
*
* @param[out] val the sample from the normal distribution
* @param[in,out] r a GMP random generator.
* @param[in] round the rounding direction.
* @return the MPFR ternary result (&plusmn;1 if val is larger/smaller than
* the exact sample).
**********************************************************************/
int operator()(mpfr_t val, gmp_randstate_t r, mpfr_rnd_t round) const
{ Compute(r); return _x(val, r, round); }
private:
// disable copy constructor and assignment operator
MPFRNormalK(const MPFRNormalK&);
MPFRNormalK& operator=(const MPFRNormalK&);
void Compute(gmp_randstate_t r) const {
// The algorithm is sample x and z from the exponential distribution; if
// (x-1)^2 < 2*z, return (random sign)*x; otherwise repeat. Probability
// of acceptance is sqrt(pi/2) * exp(-1/2) = 0.7602.
while (true) {
_edist(_x, r);
_edist(_z, r);
for (mp_size_t k = 1; ; ++k) {
_x.ExpandTo(r, k - 1);
_z.ExpandTo(r, k - 1);
mpfr_prec_t prec = (std::max)(mpfr_prec_t(MPFR_PREC_MIN), k * bits);
mpfr_set_prec(_xf, prec);
mpfr_set_prec(_zf, prec);
// Try for acceptance first; so compute upper limit on (y-1)^2 and
// lower limit on 2*z.
if (_x.UInteger() == 0) {
_x(_xf, MPFR_RNDD);
mpfr_ui_sub(_xf, 1u, _xf, MPFR_RNDU);
} else {
_x(_xf, MPFR_RNDU);
mpfr_sub_ui(_xf, _xf, 1u, MPFR_RNDU);
}
mpfr_sqr(_xf, _xf, MPFR_RNDU);
_z(_zf, MPFR_RNDD);
mpfr_mul_2ui(_zf, _zf, 1u, MPFR_RNDD);
if (mpfr_cmp(_xf, _zf) < 0) { // (y-1)^2 < 2*z, so accept
if (_x.Boolean(r)) _x.Negate(); // include a random sign
return;
}
// Try for rejection; so compute lower limit on (y-1)^2 and upper
// limit on 2*z.
if (_x.UInteger() == 0) {
_x(_xf, MPFR_RNDU);
mpfr_ui_sub(_xf, 1u, _xf, MPFR_RNDD);
} else {
_x(_xf, MPFR_RNDD);
mpfr_sub_ui(_xf, _xf, 1u, MPFR_RNDD);
}
mpfr_sqr(_xf, _xf, MPFR_RNDD);
_z(_zf, MPFR_RNDU);
mpfr_mul_2ui(_zf, _zf, 1u, MPFR_RNDU);
if (mpfr_cmp(_xf, _zf) > 0) // (y-1)^2 > 2*z, so reject
break;
// Otherwise repeat with more precision
}
// Reject and start over with a new y and z
}
}
mutable MPFRRandom<bits> _x;
mutable MPFRRandom<bits> _z;
mutable mpfr_t _xf;
mutable mpfr_t _zf;
const MPFRExponential<bits> _edist;
};
} // namespace RandomLib
#endif // HAVE_MPFR
#endif // RANDOMLIB_MPFRNORMALK_HPP

View File

@ -1,255 +0,0 @@
/**
* \file MPFRNormalR.hpp
* \brief Header for MPFRNormalR
*
* Sampling exactly from the normal distribution for MPFR using the ratio
* method.
*
* Copyright (c) Charles Karney (2012) <charles@karney.com> and licensed under
* the MIT/X11 License. For more information, see
* http://randomlib.sourceforge.net/
**********************************************************************/
#if !defined(RANDOMLIB_MPFRNORMALR_HPP)
#define RANDOMLIB_MPFRNORMALR_HPP 1
#include <algorithm> // for max/min
#include <cmath> // for pow
#include <mpfr.h>
#define HAVE_MPFR (MPFR_VERSION_MAJOR >= 3)
#if HAVE_MPFR || defined(DOXYGEN)
namespace RandomLib {
/**
* \brief The normal distribution for MPFR (ratio method).
*
* This class is <b>DEPRECATED</b>. It is included for illustrative purposes
* only. The MPFRNormal class provides a much more efficient method for
* sampling from the normal distribution.
*
* This is an adaption of NormalDistribution to MPFR. The changes are
* - Use MPFR's random number generator
* - Use sufficient precision internally to ensure that a correctly rounded
* result is returned.
*
* This class uses a mutable private object. So a single MPFRNormalR
* object cannot safely be used by multiple threads. In a multi-processing
* environment, each thread should use a thread-specific MPFRNormalR
* object.
**********************************************************************/
class MPFRNormalR {
private:
// The number of bits of randomness to add at a time. Require that Leva's
// bounds "work" at a precision of 2^-chunk and that an unsigned long can
// hold this many bits.
static const long chunk_ = 32;
static const unsigned long m = 3684067834; // ceil(2^chunk*sqrt(2/e))
public:
/**
* Initialize the MPFRNormalR object.
**********************************************************************/
MPFRNormalR() {
mpz_init(_ui);
mpz_init(_vi);
mpfr_init2(_eps, chunk_);
mpfr_init2(_u, chunk_);
mpfr_init2(_v, chunk_);
mpfr_init2(_up, chunk_);
mpfr_init2(_vp, chunk_);
mpfr_init2(_vx, chunk_);
mpfr_init2(_x1, chunk_);
mpfr_init2(_x2, chunk_);
}
/**
* Destroy the MPFRNormalR object.
**********************************************************************/
~MPFRNormalR() {
mpfr_clear(_x2);
mpfr_clear(_x1);
mpfr_clear(_vx);
mpfr_clear(_vp);
mpfr_clear(_up);
mpfr_clear(_v);
mpfr_clear(_u);
mpfr_clear(_eps);
mpz_clear(_vi);
mpz_clear(_ui);
}
/**
* Sample from the normal distribution with mean 0 and variance 1.
*
* @param[out] val the sample from the normal distribution
* @param[in,out] r a GMP random generator.
* @param[in] round the rounding direction.
* @return the MPFR ternary result (&plusmn;1 if val is larger/smaller than
* the exact sample).
**********************************************************************/
int operator()(mpfr_t val, gmp_randstate_t r, mpfr_rnd_t round) const {
const double
s = 0.449871, // Constants from Leva
t = -0.386595,
a = 0.19600 ,
b = 0.25472 ,
r1 = 0.27597 ,
r2 = 0.27846 ,
u1 = 0.606530, // sqrt(1/e) rounded down and up
u2 = 0.606531,
scale = std::pow(2.0, -chunk_); // for turning randoms into doubles
while (true) {
mpz_urandomb(_vi, r, chunk_);
if (mpz_cmp_ui(_vi, m) >= 0) continue; // Very early reject
double vf = (mpz_get_ui(_vi) + 0.5) * scale;
mpz_urandomb(_ui, r, chunk_);
double uf = (mpz_get_ui(_ui) + 0.5) * scale;
double
x = uf - s,
y = vf - t,
Q = x*x + y * (a*y - b*x);
if (Q >= r2) continue; // Early reject
mpfr_set_ui_2exp(_eps, 1u, -chunk_, MPFR_RNDN);
mpfr_prec_t prec = chunk_;
mpfr_set_prec(_u, prec);
mpfr_set_prec(_v, prec);
// (u,v) = sw corner of range
mpfr_set_z_2exp(_u, _ui, -prec, MPFR_RNDN);
mpfr_set_z_2exp(_v, _vi, -prec, MPFR_RNDN);
mpfr_set_prec(_up, prec);
mpfr_set_prec(_vp, prec);
// (up,vp) = ne corner of range
mpfr_add(_up, _u, _eps, MPFR_RNDN);
mpfr_add(_vp, _v, _eps, MPFR_RNDN);
// Estimate how many extra bits will be needed to achieve the desired
// precision.
mpfr_prec_t prec_guard = 3 + chunk_ -
(std::max)(mpz_sizeinbase(_ui, 2), mpz_sizeinbase(_vi, 2));
if (Q > r1) {
int reject;
while (true) {
// Rejection curve v^2 + 4 * u^2 * log(u) < 0 has a peak at u =
// exp(-1/2) = 0.60653066. So treat uf in (0.606530, 0.606531) =
// (u1, u2) specially
// Try for rejection first
if (uf <= u1)
reject = Reject(_u, _vp, prec, MPFR_RNDU);
else if (uf >= u2)
reject = Reject(_up, _vp, prec, MPFR_RNDU);
else { // u in (u1, u2)
mpfr_set_prec(_vx, prec);
mpfr_add(_vx, _vp, _eps, MPFR_RNDN);
reject = Reject(_u, _vx, prec, MPFR_RNDU); // Could use _up too
}
if (reject < 0) break; // tried to reject but failed, so accept
// Try for acceptance
if (uf <= u1)
reject = Reject(_up, _v, prec, MPFR_RNDD);
else if (uf >= u2)
reject = Reject(_u, _v, prec, MPFR_RNDD);
else { // u in (u2, u2)
mpfr_sub(_vx, _v, _eps, MPFR_RNDN);
reject = Reject(_u, _vx, prec, MPFR_RNDD); // Could use _up too
}
if (reject > 0) break; // tried to accept but failed, so reject
prec = Refine(r, prec); // still can't decide, to refine
}
if (reject > 0) continue; // reject, back to outer loop
}
// Now evaluate v/u to the necessary precision
mpfr_prec_t prec0 = mpfr_get_prec (val);
// while (prec < prec0 + prec_guard) prec = Refine(r, prec);
if (prec < prec0 + prec_guard)
prec = Refine(r, prec,
(prec0 + prec_guard - prec + chunk_ - 1) / chunk_);
mpfr_set_prec(_x1, prec0);
mpfr_set_prec(_x2, prec0);
int flag;
while (true) {
int
f1 = mpfr_div(_x1, _v, _up, round), // min slope
f2 = mpfr_div(_x2, _vp, _u, round); // max slope
if (f1 == f2 && mpfr_equal_p(_x1, _x2)) {
flag = f1;
break;
}
prec = Refine(r, prec);
}
mpz_urandomb(_ui, r, 1);
if (mpz_tstbit(_ui, 0)) {
flag = -flag;
mpfr_neg(val, _x1, MPFR_RNDN);
} else
mpfr_set(val, _x1, MPFR_RNDN);
// std::cerr << uf << " " << vf << " " << Q << "\n";
return flag;
}
}
private:
// disable copy constructor and assignment operator
MPFRNormalR(const MPFRNormalR&);
MPFRNormalR& operator=(const MPFRNormalR&);
// Refine the random square
mpfr_prec_t Refine(gmp_randstate_t r, mpfr_prec_t prec, long num = 1)
const {
if (num <= 0) return prec;
// Use _vx as scratch
prec += num * chunk_;
mpfr_div_2ui(_eps, _eps, num * chunk_, MPFR_RNDN);
mpz_urandomb(_ui, r, num * chunk_);
mpfr_set_prec(_up, prec);
mpfr_set_z_2exp(_up, _ui, -prec, MPFR_RNDN);
mpfr_set_prec(_vx, prec);
mpfr_add(_vx, _u, _up, MPFR_RNDN);
mpfr_swap(_u, _vx); // u = vx
mpfr_add(_up, _u, _eps, MPFR_RNDN);
mpz_urandomb(_vi, r, num * chunk_);
mpfr_set_prec(_vp, prec);
mpfr_set_z_2exp(_vp, _vi, -prec, MPFR_RNDN);
mpfr_set_prec(_vx, prec);
mpfr_add(_vx, _v, _vp, MPFR_RNDN);
mpfr_swap(_v, _vx); // v = vx
mpfr_add(_vp, _v, _eps, MPFR_RNDN);
return prec;
}
// Evaluate the sign of the rejection condition v^2 + 4*u^2*log(u)
int Reject(mpfr_t u, mpfr_t v, mpfr_prec_t prec, mpfr_rnd_t round) const {
// Use x1, x2 as scratch
mpfr_set_prec(_x1, prec);
mpfr_log(_x1, u, round);
mpfr_mul(_x1, _x1, u, round); // Important to do the multiplications in
mpfr_mul(_x1, _x1, u, round); // this order so that rounding works right.
mpfr_mul_2ui(_x1, _x1, 2u, round); // 4*u^2*log(u)
mpfr_set_prec(_x2, prec);
mpfr_mul(_x2, v, v, round); // v^2
mpfr_add(_x1, _x1, _x2, round); // v^2 + 4*u^2*log(u)
return mpfr_sgn(_x1);
}
mutable mpz_t _ui;
mutable mpz_t _vi;
mutable mpfr_t _eps;
mutable mpfr_t _u;
mutable mpfr_t _v;
mutable mpfr_t _up;
mutable mpfr_t _vp;
mutable mpfr_t _vx;
mutable mpfr_t _x1;
mutable mpfr_t _x2;
};
} // namespace RandomLib
#endif // HAVE_MPFR
#endif // RANDOMLIB_MPFRNORMALR_HPP

View File

@ -1,383 +0,0 @@
/**
* \file MPFRRandom.hpp
* \brief Header for MPFRRandom
*
* Utility class for MPFRUniform, MPFRExponential, and MPFRNormal.
*
* Copyright (c) Charles Karney (2012) <charles@karney.com> and licensed under
* the MIT/X11 License. For more information, see
* http://randomlib.sourceforge.net/
**********************************************************************/
#if !defined(RANDOMLIB_MPFRRANDOM_HPP)
#define RANDOMLIB_MPFRRANDOM_HPP 1
#include <algorithm> // for swap
#include <mpfr.h>
#define HAVE_MPFR (MPFR_VERSION_MAJOR >= 3)
#if HAVE_MPFR || defined(DOXYGEN)
/**
* A compile-time assert. Use C++11 static_assert, if available.
**********************************************************************/
#if !defined(STATIC_ASSERT)
# if defined(__GXX_EXPERIMENTAL_CXX0X__)
# define STATIC_ASSERT static_assert
# elif defined(_MSC_VER) && _MSC_VER >= 1600
# define STATIC_ASSERT static_assert
# else
# define STATIC_ASSERT(cond,reason) \
{ enum{ STATIC_ASSERT_ENUM = 1/int(cond) }; }
# endif
#endif
namespace RandomLib {
/**
* \brief Handling random numbers in MPFR.
*
* This class provides roughly the same capabilities as RandomNumber. The
* fraction is represented by a mpz integer \e f and an exponent \e e. We
* have \e e &ge; 0 and 0 &le; \e f < <i>b</i><sup><i>e</i></sup>, and \e b =
* 2<sup><i>bits</i></sup>. This represents the number \e x = \e f
* <i>b</i><sup>&minus;<i>e</i></sup>, with x in [0, 1).
*
* @tparam bits the number of bits in each digit.
*
* \e bits must divide GMP_LIMB_BITS. The default value \e bits = 32 yields
* portable results on all MPFR platforms.
**********************************************************************/
template<int bits = 32> class MPFRRandom {
private:
static const int limb_ = GMP_LIMB_BITS; // How many bits in a limb
static const int loglimb_ = (limb_ == 32 ? 5 :
(limb_ == 64 ? 6 :
(limb_ == 128 ? 7 : -1)));
static const int logbits_ = (bits == 1 ? 0 :
(bits == 2 ? 1 :
(bits == 4 ? 2 :
(bits == 8 ? 3 :
(bits == 16 ? 4 :
(bits == 32 ? 5 :
(bits == 64 ? 6 :
(bits == 128 ? 7 : -1))))))));
static const mp_limb_t mask_ = (bits == limb_ ? ~0UL : // Digit mask
~(~0UL << (bits < limb_ ? bits : 0)));
static const int logw_ = loglimb_ - logbits_; // 2^logw digits per limb
static const unsigned wmask_ = ~(~0U << logw_);
mutable mpz_t _tt; // A temporary
mpz_t _f; // The fraction
mp_size_t _e; // Count of digits
unsigned long _n; // Integer part
int _s; // Sign
void AddDigits(gmp_randstate_t r, long num = 1) { // Add num more digits
if (num <= 0) return;
mpz_mul_2exp(_f, _f, num << logbits_);
mpz_urandomb(_tt, r, num << logbits_);
mpz_add(_f, _f, _tt);
_e += num;
}
// return k'th digit counting k = 0 as most significant
mp_limb_t Digit(gmp_randstate_t r, mp_size_t k) {
ExpandTo(r, k); // Now e > k
k = _e - 1 - k; // Reverse k so k = 0 is least significant
// (k >> logw) is the limb index
// (k & wmask) is the digit position within the limb
return mask_ &
(mpz_getlimbn(_f, k >> logw_) >> ((k & wmask_) << logbits_));
}
// Return index [0..32] of highest bit set. Return 0 if x = 0, 32 is if x
// = ~0. (From Algorithms for programmers by Joerg Arndt.)
static int highest_bit_idx(unsigned long x) throw() {
if (x == 0) return 0;
int r = 1;
// STILL TO DO: handle 64-bit unsigned longs.
if (x & 0xffff0000UL) { x >>= 16; r += 16; }
if (x & 0x0000ff00UL) { x >>= 8; r += 8; }
if (x & 0x000000f0UL) { x >>= 4; r += 4; }
if (x & 0x0000000cUL) { x >>= 2; r += 2; }
if (x & 0x00000002UL) { r += 1; }
return r;
}
public:
/**
* Initialize the MPFRRandom object.
**********************************************************************/
MPFRRandom() : _e(0u), _n(0u), _s(1) {
STATIC_ASSERT(logbits_ >= 0 && loglimb_ >= 0 && logbits_ <= loglimb_,
"MPRFRandom: unsupported value for bits");
mpz_init(_f); mpz_init(_tt);
}
/**
* Initialize the MPFRRandom object from another one.
*
* @param[in] t the MPFRRandom to copy.
**********************************************************************/
MPFRRandom(const MPFRRandom& t) : _e(t._e), _n(t._n), _s(t._s)
{ mpz_init(_f); mpz_set(_f, t._f); mpz_init(_tt); }
/**
* Destroy the MPFRRandom object.
**********************************************************************/
~MPFRRandom() { mpz_clear(_f); mpz_clear(_tt); }
/**
* Assignment operator. (But swapping is typically faster.)
*
* @param[in] t the MPFRRandom to copy.
**********************************************************************/
MPFRRandom& operator=(const MPFRRandom& t) {
_e = t._e;
_n = t._n;
_s = t._s;
mpz_set(_f, t._f); // Don't copy _tt
return *this;
}
/**
* Swap with another MPFRRandom. This is a fast way of doing an
* assignment.
*
* @param[in,out] t the MPFRRandom to swap with.
**********************************************************************/
void swap(MPFRRandom& t) throw() {
if (this != &t) {
std::swap(_e, t._e);
std::swap(_n, t._n);
std::swap(_s, t._s);
mpz_swap(_f, t._f); // Don't swap _tt
}
}
/**
* Reinitialize the MPFRRandom object, setting its value to [0,1].
**********************************************************************/
void Init() { mpz_set_ui(_f, 0u); _e = 0; _n = 0; _s = 1; }
/**
* @return the sign of the MPFRRandom (&plusmn; 1).
**********************************************************************/
int Sign() const throw() { return _s; }
/**
* Change the sign of the MPFRRandom.
**********************************************************************/
void Negate() throw() { _s *= -1; }
/**
* @return the floor of the MPFRRandom
**********************************************************************/
long Floor() const throw() { return _s > 0 ? long(_n) : -1 - long(_n); }
/**
* @return the ceiling of the MPFRRandom
**********************************************************************/
long Ceiling() const throw() { return _s > 0 ? 1 + long(_n) : -long(_n); }
/**
* @return the unsigned integer component of the MPFRRandom.
**********************************************************************/
unsigned long UInteger() const throw() { return _n; }
/**
* @return the number of digits in fraction
**********************************************************************/
unsigned long Size() const throw() { return unsigned(_e); }
/**
* Add integer \e k to the MPRFRandom.
*
* @param[in] k the integer to add.
**********************************************************************/
void AddInteger(long k) {
k += Floor(); // The new floor
int ns = k < 0 ? -1 : 1; // The new sign
if (ns != _s) { // If sign changes, set f = 1 - f
mpz_set_ui(_tt, 1u);
mpz_mul_2exp(_tt, _tt, _e << logbits_);
mpz_sub_ui(_tt, _tt, 1u);
mpz_sub(_f, _tt, _f);
_s = ns;
}
_n = ns > 0 ? k : -(k + 1);
}
/**
* Compare with another MPFRRandom, *this < \e t.
*
* @param[in,out] r a random generator.
* @param[in,out] t a MPFRRandom to compare.
* @return true if *this < \e t.
**********************************************************************/
int LessThan(gmp_randstate_t r, MPFRRandom& t) {
if (this == &t) return false; // same object
if (_s != t._s) return _s < t._s;
if (_n != t._n) return (_s < 0) ^ (_n < t._n);
for (mp_size_t k = 0; ; ++k) {
mp_limb_t x = Digit(r, k);
mp_limb_t y = t.Digit(r, k);
if (x != y) return (_s < 0) ^ (x < y);
}
}
/**
* Set high bit of fraction to 1.
*
* @param[in,out] r a random generator.
**********************************************************************/
void SetHighBit(gmp_randstate_t r) { // Set the msb to 1
ExpandTo(r, 0); // Generate msb if necessary
mpz_setbit(_f, (_e << logbits_) - 1);
}
/**
* Test high bit of fraction.
*
* @param[in,out] r a random generator.
**********************************************************************/
int TestHighBit(gmp_randstate_t r) { // test the msb of f
ExpandTo(r, 0); // Generate msb if necessary
return mpz_tstbit(_f, (_e << logbits_) - 1);
}
/**
* Return the position of the most significant bit in the MPFRRandom.
*
* @param[in,out] r a random generator.
*
* The bit position is numbered such the 1/2 bit is 0, the 1/4 bit is -1,
* etc.
**********************************************************************/
mp_size_t LeadingBit(gmp_randstate_t r) {
if (_n) return highest_bit_idx(_n);
while (true) {
int sgn = mpz_sgn(_f);
if (sgn != 0)
return mp_size_t(mpz_sizeinbase(_f, 2)) - mp_size_t(_e << logbits_);
AddDigits(r);
}
}
/**
* Ensure that the k'th digit of the fraction is computed.
*
* @param[in,out] r a random generator.
* @param[in] k the digit number (0 is the most significant, 1 is the next
* most significant, etc.
**********************************************************************/
void ExpandTo(gmp_randstate_t r, mp_size_t k)
{ if (_e <= k) AddDigits(r, k - _e + 1); }
/**
* Convert to a MPFR number \e without adding more bits.
*
* @param[out] val the value of s * (n + *this).
* @param[in] round the rounding direction.
* @return the MPFR ternary result (&plusmn; if val is larger/smaller than
* the exact sample).
*
* If round is MPFR_RNDN, then the rounded midpoint of the interval
* represented by the MPFRRandom is returned. Otherwise it is the rounded
* lower or upper bound of the interval (whichever is appropriate).
**********************************************************************/
int operator()(mpfr_t val, mpfr_rnd_t round)
{ return operator()(val, NULL, round); }
/**
* Convert to a MPFR number.
*
* @param[out] val the value of s * (n + *this).
* @param[in,out] r a GMP random generator.
* @param[in] round the rounding direction.
* @return the MPFR ternary result (&plusmn; if val is larger/smaller than
* the exact sample).
*
* If \e r is NULL, then no additional random bits are generated and the
* lower bound, midpoint, or upper bound of the MPFRRandom interval is
* returned, depending on the value of \e round.
**********************************************************************/
int operator()(mpfr_t val, gmp_randstate_t r, mpfr_rnd_t round) {
// The value is constructed as a positive quantity, so adjust rounding
// mode to account for this.
switch (round) {
case MPFR_RNDD:
case MPFR_RNDU:
case MPFR_RNDN:
break;
case MPFR_RNDZ:
round = _s < 0 ? MPFR_RNDU : MPFR_RNDD;
break;
case MPFR_RNDA:
round = _s < 0 ? MPFR_RNDD : MPFR_RNDU;
break;
default:
round = MPFR_RNDN; // New rounding modes are variants of N
break;
} // Now round is one of MPFR_RND{D,N,U}
mp_size_t excess;
mpfr_exp_t expt;
if (r == NULL) {
// If r is NULL then all the bits currently generated are considered
// significant. Thus no excess bits need to be squeezed out.
excess = 0;
// And the exponent shift in mpfr_set_z_2exp is just...
expt = -(_e << logbits_);
// However, if rounding to nearest, we need to make room for the
// midpoint bit.
if (round == MPFR_RNDN) {
excess = -1;
--expt;
}
} else { // r is non-NULL
// Generate enough digits, i.e., enough to generate prec significant
// figures for RNDD and RNDU; for RNDN we need to generate an
// additional guard bit.
mp_size_t lead = LeadingBit(r);
mpfr_prec_t prec = mpfr_get_prec (val);
mp_size_t trail = lead - prec; // position one past trailing bit
mp_size_t guard = trail + (round == MPFR_RNDN ? 0 : 1); // guard bit pos
// Generate the bits needed.
if (guard <= 0) ExpandTo(r, (-guard) >> logbits_);
// Unless bits = 1, the generation process will typically have
// generated too many bits. We figure out how many, but leaving room
// for one additional "inexact" bit. The inexact bit is set to 1 in
// order to force MPFR to treat the result as inexact, to break RNDN
// ties, and to get the ternary value set correctly.
//
// expt is the exponent used when forming the number using
// mpfr_set_z_2exp. Without the inexact bit, it's (guard - 1).
// Subtract 1 to account for the inexact bit.
expt = guard - 2;
// The number of excess bits is now the difference between the number
// of bits in the fraction (e << logbits) and -expt. Note that this
// may be -1 (meaning we'll need to shift the number left to
// accommodate the inexact bit).
excess = (_e << logbits_) + expt;
}
mpz_set_ui(_tt, _n); // The integer part
mpz_mul_2exp(_tt, _tt, _e << logbits_); // Shift to allow for fraction
mpz_add(_tt, _tt, _f); // Add fraction
if (excess > 0)
mpz_tdiv_q_2exp(_tt, _tt, excess);
else if (excess < 0)
mpz_mul_2exp(_tt, _tt, -excess);
if (r || round == MPFR_RNDN)
// Set the inexact bit (or compute the midpoint if r is NULL).
mpz_setbit(_tt, 0);
else if (round == MPFR_RNDU)
// If r is NULL, compute the upper bound.
mpz_add_ui(_tt, _tt, 1u);
// Convert to a mpfr number. If r is specified, then there are
// sufficient bits in tt that the result is inexact and that (in the case
// of RNDN) there are no ties.
int flag = mpfr_set_z_2exp(val, _tt, expt, round);
if (_s < 0) {
mpfr_neg (val, val, MPFR_RNDN);
flag = -flag;
}
return flag;
}
/**
* A coin toss. (This should really be a static function. But it uses the
* MPFRRandom temporary variable.)
*
* @param[in,out] r a GMP random generator.
* @return true or false.
**********************************************************************/
int Boolean(gmp_randstate_t r) const {
mpz_urandomb(_tt, r, 1);
return mpz_tstbit(_tt, 0);
}
};
} // namespace RandomLib
#endif // HAVE_MPFR
#endif // RANDOMLIB_MPFRRANDOM_HPP

View File

@ -1,72 +0,0 @@
/**
* \file MPFRUniform.hpp
* \brief Header for MPFRUniform
*
* Sampling exactly from a uniform distribution for MPFR.
*
* Copyright (c) Charles Karney (2012) <charles@karney.com> and licensed under
* the MIT/X11 License. For more information, see
* http://randomlib.sourceforge.net/
**********************************************************************/
#if !defined(RANDOMLIB_MPFRUNIFORM_HPP)
#define RANDOMLIB_MPFRUNIFORM_HPP 1
#include <RandomLib/MPFRRandom.hpp>
#if HAVE_MPFR || defined(DOXYGEN)
namespace RandomLib {
/**
* \brief The uniform distribution for MPFR.
*
* This is just a thin layer on top of MPFRRandom to provide random numbers
* uniformly distributed in [0,1].
*
* This class uses a mutable private object. So a single MPFRUniform object
* cannot safely be used by multiple threads. In a multi-processing
* environment, each thread should use a thread-specific MPFRUniform object.
*
* @tparam bits the number of bits in each digit.
**********************************************************************/
template<int bits = 32> class MPFRUniform {
public:
/**
* Initialize the MPFRUniform object.
**********************************************************************/
MPFRUniform() {};
/**
* Sample from the uniform distribution in [0,1] returning a MPFRRandom.
* This function takes an unused GMP random generator as a parameter, in
* order to parallel the usage of MPFRExponential and MPFRNormal.
*
* @param[out] t the MPFRRandom result.
* @param[in,out] r a GMP random generator (unused).
**********************************************************************/
void operator()(MPFRRandom<bits>& t, gmp_randstate_t r) const
{ Compute(r); _x.swap(t); }
/**
* Sample from the uniform distribution in [0,1].
*
* @param[out] val the sample from the uniform distribution
* @param[in,out] r a GMP random generator.
* @param[in] round the rounding direction.
* @return the MPFR ternary result (&plusmn; if val is larger/smaller than
* the exact sample).
**********************************************************************/
int operator()(mpfr_t val, gmp_randstate_t r, mpfr_rnd_t round) const
{ Compute(r); return _x(val, r, round); }
private:
// disable copy constructor and assignment operator
MPFRUniform(const MPFRUniform&);
MPFRUniform& operator=(const MPFRUniform&);
void Compute(gmp_randstate_t /* r */) const { _x. Init(); }
mutable MPFRRandom<bits> _x;
};
} // namespace RandomLib
#endif // HAVE_MPFR
#endif // RANDOMLIB_MPFRUNIFORM_HPP

View File

@ -1,114 +0,0 @@
/**
* \file NormalDistribution.hpp
* \brief Header for NormalDistribution
*
* Compute normal deviates.
*
* Copyright (c) Charles Karney (2006-2011) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* http://randomlib.sourceforge.net/
**********************************************************************/
#if !defined(RANDOMLIB_NORMALDISTRIBUTION_HPP)
#define RANDOMLIB_NORMALDISTRIBUTION_HPP 1
#include <cmath> // for std::log
namespace RandomLib {
/**
* \brief Normal deviates
*
* Sample from the normal distribution.
*
* This uses the ratio method; see Knuth, TAOCP, Vol 2, Sec. 3.4.1.C,
* Algorithm R. Unlike the Box-Muller method which generates two normal
* deviates at a time, this method generates just one. This means that this
* class has no state that needs to be saved when checkpointing a
* calculation. Original citation is\n A. J. Kinderman, J. F. Monahan,\n
* Computer Generation of Random Variables Using the Ratio of Uniform
* Deviates,\n ACM TOMS 3, 257--260 (1977).
*
* Improved "quadratic" bounds are given by\n J. L. Leva,\n A Fast Normal
* Random Number Generator,\n ACM TOMS 18, 449--453 and 454--455
* (1992).
*
* The log is evaluated 1.369 times per normal deviate with no bounds, 0.232
* times with Knuth's bounds, and 0.012 times with the quadratic bounds.
* Time is approx 0.3 us per deviate (1GHz machine, optimized, RealType =
* float).
*
* Example
* \code
* #include <RandomLib/NormalDistribution.hpp>
*
* RandomLib::Random r;
* std::cout << "Seed set to " << r.SeedString() << "\n";
* RandomLib::NormalDistribution<double> normdist;
* std::cout << "Select from normal distribution:";
* for (size_t i = 0; i < 10; ++i)
* std::cout << " " << normdist(r);
* std::cout << "\n";
* \endcode
*
* @tparam RealType the real type of the results (default double).
**********************************************************************/
template<typename RealType = double> class NormalDistribution {
public:
/**
* The type returned by NormalDistribution::operator()(Random&)
**********************************************************************/
typedef RealType result_type;
/**
* Return a sample of type RealType from the normal distribution with mean
* &mu; and standard deviation &sigma;.
*
* For &mu; = 0 and &sigma; = 1 (the defaults), the distribution is
* symmetric about zero and is nonzero. The maximum result is less than 2
* sqrt(log(2) \e p) where \e p is the precision of real type RealType.
* The minimum positive value is approximately 1/2<sup><i>p</i>+1</sup>.
* Here \e p is the precision of real type RealType.
*
* @tparam Random the type of RandomCanonical generator.
* @param[in,out] r the RandomCanonical generator.
* @param[in] mu the mean value of the normal distribution (default 0).
* @param[in] sigma the standard deviation of the normal distribution
* (default 1).
* @return the random sample.
**********************************************************************/
template<class Random>
RealType operator()(Random& r, RealType mu = RealType(0),
RealType sigma = RealType(1)) const throw();
};
template<typename RealType> template<class Random> inline RealType
NormalDistribution<RealType>::operator()(Random& r, RealType mu,
RealType sigma) const throw() {
// N.B. These constants can be regarded as "exact", so that the same number
// of significant figures are used in all versions. (They serve to
// "bracket" the real boundary specified by the log expression.)
const RealType
m = RealType( 1.7156 ), // sqrt(8/e) (rounded up)
s = RealType( 0.449871), // Constants from Leva
t = RealType(-0.386595),
a = RealType( 0.19600 ),
b = RealType( 0.25472 ),
r1 = RealType( 0.27597 ),
r2 = RealType( 0.27846 );
RealType u, v, Q;
do { // This loop is executed 1.369 times on average
// Pick point P = (u, v)
u = r.template FixedU<RealType>(); // Sample u in (0,1]
v = m * r.template FixedS<RealType>(); // Sample v in (-m/2, m/2); avoid 0
// Compute quadratic form Q
const RealType x = u - s;
const RealType y = (v < 0 ? -v : v) - t; // Sun has no long double abs!
Q = x*x + y * (a*y - b*x);
} while ( Q >= r1 && // accept P if Q < r1
( Q > r2 || // reject P if Q > r2
v*v > - 4 * u*u * std::log(u) ) ); // accept P if v^2 <= ...
return mu + sigma * (v / u); // return the slope of P (note u != 0)
}
} // namespace RandomLib
#endif // RANDOMLIB_NORMALDISTRIBUTION_HPP

View File

@ -1,141 +0,0 @@
/**
* \file Random.hpp
* \brief Header for Random, RandomGenerator.
*
* This loads up the header for RandomCanonical, RandomEngine, etc., to
* provide access to random integers of various sizes, random reals with
* various precisions, a random probability, etc.
*
* Copyright (c) Charles Karney (2006-2011) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* http://randomlib.sourceforge.net/
**********************************************************************/
#if !defined(RANDOMLIB_RANDOM_HPP)
#define RANDOMLIB_RANDOM_HPP 1
#include <RandomLib/Config.h>
#if defined(_MSC_VER)
typedef unsigned uint32_t;
typedef unsigned long long uint64_t;
#else
#include <stdint.h>
#endif
/**
* Use table, Power2::power2, for pow2? This isn't necessary with g++ 4.0
* because calls to std::pow are optimized. g++ 4.1 seems to have lost this
* capability though! And it's back in g++ 4.4. So, for simplicity, assume
* that all "current" versions of g++ perform the optimization.
**********************************************************************/
#if !defined(RANDOMLIB_POWERTABLE)
#if defined(__GNUC__)
#define RANDOMLIB_POWERTABLE 0
#else
// otherwise use a lookup table
#define RANDOMLIB_POWERTABLE 1
#endif
#endif
#if !HAVE_LONG_DOUBLE || defined(_MSC_VER)
#define RANDOMLIB_LONGDOUBLEPREC 53
#elif defined(__sparc)
#define RANDOMLIB_LONGDOUBLEPREC 113
#else
/**
* The precision of long doubles, used for sizing Power2::power2. 64 on
* Linux/Intel, 106 on MaxOS/PowerPC
**********************************************************************/
#define RANDOMLIB_LONGDOUBLEPREC __LDBL_MANT_DIG__
#endif
/**
* A compile-time assert. Use C++11 static_assert, if available.
**********************************************************************/
#if !defined(STATIC_ASSERT)
# if __cplusplus >= 201103
# define STATIC_ASSERT static_assert
# elif defined(__GXX_EXPERIMENTAL_CXX0X__)
# define STATIC_ASSERT static_assert
# elif defined(_MSC_VER) && _MSC_VER >= 1600
# define STATIC_ASSERT static_assert
# else
# define STATIC_ASSERT(cond,reason) \
{ enum{ STATIC_ASSERT_ENUM = 1/int(cond) }; }
# endif
#endif
/**
* Are denormalized reals of type RealType supported?
**********************************************************************/
#define RANDOMLIB_HASDENORM(RealType) 1
#if defined(_MSC_VER) && defined(RANDOMLIB_SHARED_LIB) && RANDOMLIB_SHARED_LIB
# if RANDOMLIB_SHARED_LIB > 1
# error RANDOMLIB_SHARED_LIB must be 0 or 1
# elif defined(RandomLib_EXPORTS)
# define RANDOMLIB_EXPORT __declspec(dllexport)
# else
# define RANDOMLIB_EXPORT __declspec(dllimport)
# endif
#else
# define RANDOMLIB_EXPORT
#endif
#include <stdexcept>
/**
* \brief Namespace for %RandomLib
*
* All of %RandomLib is defined within the RandomLib namespace. In addtiion
* all the header files are included via %RandomLib/filename. This minimizes
* the likelihood of conflicts with other packages.
**********************************************************************/
namespace RandomLib {
/**
* \brief Exception handling for %RandomLib
*
* A class to handle exceptions. It's derived from std::runtime_error so it
* can be caught by the usual catch clauses.
**********************************************************************/
class RandomErr : public std::runtime_error {
public:
/**
* Constructor
*
* @param[in] msg a string message, which is accessible in the catch
* clause, via what().
**********************************************************************/
RandomErr(const std::string& msg) : std::runtime_error(msg) {}
};
} // namespace RandomLib
#include <RandomLib/RandomCanonical.hpp>
#if !defined(RANDOMLIB_BUILDING_LIBRARY)
namespace RandomLib {
#if !defined(RANDOMLIB_DEFAULT_GENERATOR)
#define RANDOMLIB_DEFAULT_GENERATOR SRandomGenerator32
#endif
/**
* Point Random to one of a specific MT19937 generators.
**********************************************************************/
typedef RANDOMLIB_DEFAULT_GENERATOR RandomGenerator;
/**
* Hook Random to RandomGenerator
**********************************************************************/
typedef RandomCanonical<RandomGenerator> Random;
} // namespace RandomLib
#endif // !defined(RANDOMLIB_BUILDING_LIBRARY)
#endif // RANDOMLIB_RANDOM_HPP

View File

@ -1,384 +0,0 @@
/**
* \file RandomAlgorithm.hpp
* \brief Header for MT19937 and SFMT19937.
*
* This provides an interface to the Mersenne Twister
* <a href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html">
* MT19937</a> and SIMD oriented Fast Mersenne Twister
* <a href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html">
* SFMT19937</a> random number engines.
*
* Interface routines written by Charles Karney <charles@karney.com> and
* licensed under the MIT/X11 License. For more information, see
* http://randomlib.sourceforge.net/
**********************************************************************/
#if !defined(RANDOMLIB_RANDOMALGORITHM_HPP)
#define RANDOMLIB_RANDOMALGORITHM_HPP 1
#include <RandomLib/RandomType.hpp>
#include <stdexcept>
#include <string>
#if defined(HAVE_SSE2) && HAVE_SSE2
#include <emmintrin.h>
#endif
#if (defined(HAVE_SSE2) && HAVE_SSE2) && (defined(HAVE_ALTIVEC) && HAVE_ALTIVEC)
#error "HAVE_SSE2 and HAVE_ALTIVEC should not both be defined"
#endif
#if defined(_MSC_VER)
// Squelch warnings about casts truncating constants
# pragma warning (push)
# pragma warning (disable: 4310)
#endif
namespace RandomLib {
/**
* \brief The %MT19937 random number engine.
*
* This provides an interface to Mersenne Twister random number engine,
* <a href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html">
* MT19937</a>. See\n Makoto Matsumoto and Takuji Nishimura,\n Mersenne
* Twister: A 623-Dimensionally Equidistributed Uniform Pseudo-Random Number
* Generator,\n ACM TOMACS 8, 3--30 (1998)
*
* This is adapted from the 32-bit and 64-bit C versions available at
* http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html and
* http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt64.html
*
* The template argument give the type \e RandomType of the "natural" result.
* This incorporates the bit width and the C++ type of the result. Although
* the two versions of MT19937 produce different sequences, the
* implementations here are portable across 32-bit and 64-bit architectures.
*
* The class chiefly supplies the method for advancing the state by
* Transition.
*
* @tparam RandomType the type of the results, either Random_u32 or
* Random_u64.
*
* Interface routines written by Charles Karney <charles@karney.com> and
* licensed under the MIT/X11 License. For more information, see
* http://randomlib.sourceforge.net/
**********************************************************************/
template<class RandomType> class RANDOMLIB_EXPORT MT19937 {
public:
/**
* The result RandomType
**********************************************************************/
typedef RandomType engine_t;
/**
* The internal numeric type for MT19337::Transition
**********************************************************************/
typedef typename engine_t::type internal_type;
private:
/**
* The unsigned type of engine_t
**********************************************************************/
typedef typename engine_t::type engine_type;
/**
* The width of the engine_t
**********************************************************************/
static const unsigned width = engine_t::width;
enum {
/**
* The Mersenne prime is 2<sup><i>P</i></sup> &minus; 1
**********************************************************************/
P = 19937,
/**
* The short lag for MT19937
**********************************************************************/
M = width == 32 ? 397 : 156,
/**
* The number of ignored bits in the first word of the state
**********************************************************************/
R = ((P + width - 1)/width) * width - P
};
static const engine_type mask = engine_t::mask;
/**
* Magic matrix for MT19937
**********************************************************************/
static const engine_type magic =
width == 32 ? 0x9908b0dfULL : 0xb5026f5aa96619e9ULL;
/**
* Mask for top \e width &minus; \e R bits of a word
**********************************************************************/
static const engine_type upper = mask << R & mask;
/**
* Mask for low \e R bits of a <i>width</i>-bit word
**********************************************************************/
static const engine_type lower = ~upper & mask;
public:
/**
* A version number "EnMT" or "EnMU" to ensure safety of Save/Load. This
* needs to be unique across RandomAlgorithms.
**********************************************************************/
static const unsigned version = 0x456e4d54UL + (engine_t::width/32 - 1);
enum {
/**
* The size of the state. This is the long lag for MT19937.
**********************************************************************/
N = (P + width - 1)/width
};
/**
* Advance state by \e count batches. For speed all \e N words of state
* are advanced together. If \e count is negative, the state is stepped
* backwards. This is the meat of the MT19937 engine.
*
* @param[in] count how many batches to advance.
* @param[in,out] statev the internal state of the random number generator.
**********************************************************************/
static void Transition(long long count, internal_type statev[]) throw();
/**
* Manipulate a word of the state prior to output.
*
* @param[in] y a word of the state.
* @return the result.
**********************************************************************/
static engine_type Generate(engine_type y) throw();
/**
* Convert an arbitrary state into a legal one. This consists of (a)
* turning on one bit if the state is all zero and (b) making 31 bits of
* the state consistent with the other 19937 bits.
*
* @param[in,out] state the state of the generator.
**********************************************************************/
static void NormalizeState(engine_type state[]) throw();
/**
* Check that the state is legal, throwing an exception if it is not. At
* the same time, accumulate a checksum of the state.
*
* @param[in] state the state of the generator.
* @param[in,out] check an accumulated checksum.
**********************************************************************/
static void CheckState(const engine_type state[], Random_u32::type& check);
/**
* Return the name of the engine
*
* @return the name.
**********************************************************************/
static std::string Name() throw() {
return "MT19937<Random_u" + std::string(width == 32 ? "32" : "64") + ">";
}
};
/// \cond SKIP
template<>
inline Random_u32::type MT19937<Random_u32>::Generate(engine_type y) throw() {
y ^= y >> 11;
y ^= y << 7 & engine_type(0x9d2c5680UL);
y ^= y << 15 & engine_type(0xefc60000UL);
y ^= y >> 18;
return y;
}
template<>
inline Random_u64::type MT19937<Random_u64>::Generate(engine_type y) throw() {
// Specific tempering instantiation for width = 64 given in
// http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt64.html
y ^= y >> 29 & engine_type(0x5555555555555555ULL);
y ^= y << 17 & engine_type(0x71d67fffeda60000ULL);
y ^= y << 37 & engine_type(0xfff7eee000000000ULL);
y ^= y >> 43;
return y;
}
/// \endcond
/**
* \brief The SFMT random number engine.
*
* This provides an implementation of the SIMD-oriented Fast Mersenne Twister
* random number engine,
* <a href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html">
* SFMT</a>. See\n Mutsuo Saito,\n An Application of Finite Field: Design
* and Implementation of 128-bit Instruction-Based Fast Pseudorandom Number
* Generator,\n Master's Thesis, Dept. of Math., Hiroshima University
* (Feb. 2007).\n
* http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/M062821.pdf
* Mutsuo Saito and Makoto Matsumoto,\n
* SIMD-oriented Fast Mersenne Twister: a 128-bit Pseudorandom Number
* Generator,\n accepted in the proceedings of MCQMC2006\n
* http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/ARTICLES/sfmt.pdf
*
* The template argument gives the type \e RandomType of the "natural"
* result. This incorporates the bit width and the C++ type of the result.
* The 32-bit and 64-bit versions of SFMT19937 produce the same sequences and
* the differing only in whether how the state is represented. The
* implementation includes a version using 128-bit SSE2 instructions. On
* machines without these instructions, portable implementations using
* traditional operations are provided. With the same starting seed,
* SRandom32::Ran64() and SRandom64::Ran64() produces the same sequences.
* Similarly SRandom64::Ran32() produces every other member of the sequence
* produced by SRandom32::Ran32().
*
* The class chiefly supplies the method for advancing the state by
* Transition.
*
* @tparam RandomType the type of the results, either Random_u32 or
* Random_u64.
*
* Written by Charles Karney <charles@karney.com> and licensed under the
* MIT/X11 License. For more information, see
* http://randomlib.sourceforge.net/
**********************************************************************/
template<class RandomType> class RANDOMLIB_EXPORT SFMT19937 {
public:
/**
* The result RandomType
**********************************************************************/
typedef RandomType engine_t;
#if defined(HAVE_SSE2) && HAVE_SSE2
typedef __m128i internal_type;
#elif defined(HAVE_ALTIVEC) && HAVE_ALTIVEC
typedef vector unsigned internal_type;
#else
/**
* The internal numeric type for SFMT19337::Transition
**********************************************************************/
typedef typename engine_t::type internal_type;
#endif
private:
/**
* The unsigned type of engine_t
**********************************************************************/
typedef typename engine_t::type engine_type;
/**
* The width of the engine_t
**********************************************************************/
static const unsigned width = engine_t::width;
enum {
/**
* The Mersenne prime is 2<sup><i>P</i></sup> &minus; 1
**********************************************************************/
P = 19937,
/**
* The long lag for SFMT19937 in units of 128-bit words
**********************************************************************/
N128 = (P + 128 - 1)/128,
/**
* How many width words per 128-bit word.
**********************************************************************/
R = 128 / width,
/**
* The short lag for SFMT19937 in units of 128-bit words
**********************************************************************/
M128 = 122,
/**
* The short lag for SFMT19937
**********************************************************************/
M = M128 * R
};
#if (defined(HAVE_SSE2) && HAVE_SSE2) || (defined(HAVE_ALTIVEC) && HAVE_ALTIVEC)
static const Random_u32::type magic0 = 0x1fffefUL;
static const Random_u32::type magic1 = 0x1ecb7fUL;
static const Random_u32::type magic2 = 0x1affffUL;
static const Random_u32::type magic3 = 0x1ffff6UL;
#else
/**
* Magic matrix for SFMT19937. Only the low 21 (= 32 &minus; 11) bits need
* to be set. (11 is the right shift applied to the words before masking.
**********************************************************************/
static const engine_type
magic0 = width == 32 ? 0x1fffefULL : 0x1ecb7f001fffefULL;
static const engine_type
magic1 = width == 32 ? 0x1ecb7fULL : 0x1ffff6001affffULL;
static const engine_type
magic2 = width == 32 ? 0x1affffULL : 0ULL;
static const engine_type
magic3 = width == 32 ? 0x1ffff6ULL : 0ULL;
#endif
/**
* Mask for simulating u32 << 18 with 64-bit words
**********************************************************************/
static const engine_type mask18 = engine_type(0xfffc0000fffc0000ULL);
/**
* Magic constants needed by "period certification"
**********************************************************************/
static const engine_type PARITY0 = 1U;
static const engine_type PARITY1 = width == 32 ? 0U : 0x13c9e68400000000ULL;
static const engine_type PARITY2 = 0U;
static const engine_type PARITY3 = width == 32 ? 0x13c9e684UL : 0U;
/**
* Least significant bit of PARITY
**********************************************************************/
static const unsigned PARITY_LSB = 0;
static const engine_type mask = engine_t::mask;
public:
/**
* A version number "EnSM" or "EnSN" to ensure safety of Save/Load. This
* needs to be unique across RandomAlgorithms.
**********************************************************************/
static const unsigned version = 0x456e534dUL + (engine_t::width/32 - 1);
enum {
/**
* The size of the state. The long lag for SFMT19937
**********************************************************************/
N = N128 * R
};
/**
* Advance state by \e count batches. For speed all \e N words of state
* are advanced together. If \e count is negative, the state is stepped
* backwards. This is the meat of the SFMT19937 engine.
*
* @param[in] count how many batches to advance.
* @param[in,out] statev the internal state of the random number generator.
**********************************************************************/
static void Transition(long long count, internal_type statev[])
throw();
/**
* Manipulate a word of the state prior to output. This is a no-op for
* SFMT19937.
*
* @param[in] y a word of the state.
* @return the result.
**********************************************************************/
static engine_type Generate(engine_type y) throw() { return y; }
/**
* Convert an arbitrary state into a legal one. This consists a "period
* certification to ensure that the period of the generator is at least
* 2<sup><i>P</i></sup> &minus; 1.
*
* @param[in,out] state the state of the generator.
**********************************************************************/
static void NormalizeState(engine_type state[]) throw();
/**
* Check that the state is legal, throwing an exception if it is not. This
* merely verifies that the state is not all zero. At the same time,
* accumulate a checksum of the state.
*
* @param[in] state the state of the generator.
* @param[in,out] check an accumulated checksum.
**********************************************************************/
static void CheckState(const engine_type state[], Random_u32::type& check);
/**
* Return the name of the engine
*
* @return the name.
**********************************************************************/
static std::string Name() throw() {
return "SFMT19937<Random_u" +
std::string(width == 32 ? "32" : "64") + ">";
}
};
} // namespace RandomLib
#if defined(_MSC_VER)
# pragma warning (pop)
#endif
#endif // RANDOMLIB_RANDOMALGORITHM_HPP

File diff suppressed because it is too large Load Diff

View File

@ -1,640 +0,0 @@
/**
* \file RandomEngine.hpp
* \brief Header for RandomEngine.
*
* Copyright (c) Charles Karney (2006-2012) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* http://randomlib.sourceforge.net/
**********************************************************************/
#if !defined(RANDOMLIB_RANDOMENGINE_HPP)
#define RANDOMLIB_RANDOMENGINE_HPP 1
#include <RandomLib/RandomSeed.hpp>
#include <RandomLib/RandomAlgorithm.hpp>
#include <RandomLib/RandomMixer.hpp>
#include <limits>
#include <string>
#include <algorithm>
#if defined(HAVE_SSE2) && HAVE_SSE2 && defined(_MSC_VER) && !defined(_WIN64)
#include <new>
#endif
#if !defined(RANDOMLIB_BUILDING_LIBRARY) && \
defined(HAVE_BOOST_SERIALIZATION) && HAVE_BOOST_SERIALIZATION
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/split_member.hpp>
#include <boost/serialization/vector.hpp>
#endif
namespace RandomLib {
/**
* \brief Uniform random number generator.
*
* This implements a generic random number generator. Such a generator
* requires two data holders RandomSeed, to hold the seed, and RandomEngine,
* to hold the state. In addition we need two piece of machinery, a "Mixer"
* to convert the seed into an initial state and an "Algorithm" to advance the
* state.
*
* @tparam Algorithm the random number algorithm.
* @tparam Mixer the way seeds are turned into state.
*
* RandomSeed is responsible for setting and reporting the seed.
*
* Mixer has no state and implements only static methods. It needs to have
* the following public interface
* - typedef mixer_t: a RandomType giving the output type
* - unsigned version: an identifying version number
* - static std::string Name(): an identifying name for the mixer
* - static method SeedToState: converts a seed into n words of state.
*
* Algorithm has no state and implements only static methods. It needs to
* have the following public interface
* - typedef engine_t: a RandomType giving the output type
* - typedef internal_type: a integer type used by Transition. This is
* usually the same as engine_t::type. However it allows the use of
* vector instructions on some platforms. We require that engine_t::type
* and internal_type line up properly in a union so that there is no need
* to convert the data explicitly between internal_type and
* engine_t::type.
* - unsigned version: an identifying version number
* - static std::string Name(): an identifying name for the mixer
* - enum N: the size of the state in units of engine_t.
* - static method Transition: steps the generator forwards or backwards.
* - static method Generate: tempers the state immediately prior to output
* - static method NormalizeState: force the initial state (the result of
* the Mixer) into a legal state.
* - static method CheckState accumulates the checksum for the state into
* check. In addition it throws an exception if the state is bad.
*
* RandomEngine is the glue that holds everything together. It repacks
* the mixer_t data from Mixer into engine_t if necessary. It deals with
* delivering individual random results, stepping the state forwards and
* backwards, leapfrogging the generator, I/O of the generator, etc.
*
* Written by Charles Karney <charles@karney.com> and licensed under the
* MIT/X11 License. For more information, see
* http://randomlib.sourceforge.net/
**********************************************************************/
template<class Algorithm, class Mixer>
class RANDOMLIB_EXPORT RandomEngine : public RandomSeed {
private:
/**
* The result RandomType (carried over from the \e Algorithm).
**********************************************************************/
typedef typename Algorithm::engine_t result_t;
/**
* The RandomType used by the \e Mixer.
**********************************************************************/
typedef typename Mixer::mixer_t mixer_t;
/**
* The internal_type used by the Algorithm::Transition().
**********************************************************************/
typedef typename Algorithm::internal_type engine_type;
public:
/**
* The number of random bits produced by Ran().
**********************************************************************/
enum {
width = result_t::width
};
/**
* A type large enough to hold \e width bits. This is used for the
* internal state of the generator and the result returned by Ran().
**********************************************************************/
typedef typename result_t::type result_type;
/**
* The minimum result returned by Ran() = 0.
**********************************************************************/
static const result_type min = result_t::min;
/**
* The maximum result returned by Ran() = 2<sup><i>w</i></sup> &minus; 1.
**********************************************************************/
static const result_type max = result_t::max;
protected:
/**
* The mask for the result_t.
**********************************************************************/
static const result_type mask = result_t::mask;
private:
/**
* A version number "RandLib0" to ensure safety of Save/Load. The first 7
* bytes can be regarded as a "signature" and the 8th byte a version
* number.
**********************************************************************/
static const u64::type version = 0x52616e644c696230ULL; // 'RandLib0'
/**
* Marker for uninitialized object
**********************************************************************/
static const unsigned UNINIT = 0xffffffffU;
enum {
/**
* The size of the state in units of result_type
**********************************************************************/
N = Algorithm::N,
/**
* The size of the state in units of mixer_t::type
**********************************************************************/
NU = (N * width + mixer_t::width - 1) / mixer_t::width,
/**
* The size of the state in units of engine_type.
**********************************************************************/
NV = N * sizeof(result_type) / sizeof(engine_type)
};
/**
* \brief Union for the state.
*
* A union to hold the state in the result_type, mixer_t::type, and
* engine_type representations.
**********************************************************************/
union {
/**
* the result_type representation returned by Ran()
**********************************************************************/
result_type _state[N];
/**
* the mixer_t::type representation returned by Mixer::SeedToState.
**********************************************************************/
typename mixer_t::type _stateu[NU];
/**
* the engine_type representation returned by Algorithm::Transition.
**********************************************************************/
engine_type _statev[NV];
};
/**
* The index for the next random value
**********************************************************************/
unsigned _ptr;
/**
* How many times has Transition() been called
**********************************************************************/
long long _rounds;
/**
* Stride for leapfrogging
**********************************************************************/
unsigned _stride;
public:
/**
* \name Constructors
**********************************************************************/
///@{
/**
* Initialize from a vector. Only the low \e 32 bits of each element are
* used.
*
* @tparam IntType the integral type of the elements of the vector.
* @param[in] v the vector of elements.
**********************************************************************/
template<typename IntType>
explicit RandomEngine(const std::vector<IntType>& v) { Reseed(v); }
/**
* Initialize from a pair of iterators setting seed to [\e a, \e b). The
* iterator must produce results which can be converted into seed_type.
* Only the low \e 32 bits of each element are used.
*
* @tparam InputIterator the type of the iterator.
* @param[in] a the beginning iterator.
* @param[in] b the ending iterator.
**********************************************************************/
template<typename InputIterator>
RandomEngine(InputIterator a, InputIterator b) { Reseed(a, b); }
/**
* Initialize with seed [\e n]. Only the low \e width bits of \e n are
* used.
*
* @param[in] n the new seed to use.
**********************************************************************/
explicit RandomEngine(seed_type n) { Reseed(n); }
/**
* Initialize with seed []. This can be followed by a call to Reseed() to
* select a unique seed.
**********************************************************************/
RandomEngine() { unsigned long s[1]; Reseed(s, s); }
/**
* Initialize from a string. See Reseed(const std::string& s)
*
* @param[in] s the string to be decoded into a seed.
**********************************************************************/
explicit RandomEngine(const std::string& s) { Reseed(s); }
///@}
/**
* \name Functions for returning random data
**********************************************************************/
///@{
/**
* Return \e width bits of randomness. This is the natural unit of random
* data produced random number generator.
*
* @return the next random number of width \e width.
**********************************************************************/
result_type Ran() throw() {
if (_ptr >= N)
Next();
result_type y = _state[_ptr];
_ptr += _stride;
return Algorithm::Generate(y);
}
/**
* Return 32 bits of randomness.
*
* @return a 32-bit random number.
**********************************************************************/
u32::type Ran32() throw() {
// return width > 32 ? u32::cast(Ran()) : Ran();
return u32::cast(Ran());
}
/**
* Return 64 bits of randomness.
*
* @return a 64-bit random number.
**********************************************************************/
u64::type Ran64() throw() {
const u64::type x = Ran();
return width > 32 ? x : u64::cast(Ran()) << (64 - width) | x;
}
/**
* Return \e width bits of randomness. Result is in [0,
* 2<sup><i>w</i></sup>). (This just calls Ran().)
*
* @return the next random number of width \e width.
**********************************************************************/
result_type operator()() throw() { return Ran(); }
///@}
#if defined(HAVE_SSE2) && HAVE_SSE2 && defined(_MSC_VER) && !defined(_WIN64)
/**
* new operator with alignment (needed for Visual Studio)
**********************************************************************/
void* operator new(size_t n) {
void* p = _aligned_malloc(n, __alignof(RandomEngine));
if (p == 0) throw std::bad_alloc();
return p;
}
/**
* delete operator with alignment (needed for Visual Studio)
**********************************************************************/
void operator delete(void* p) { _aligned_free(p); }
/**
* new[] operator with alignment (needed for Visual Studio)
**********************************************************************/
void* operator new[](size_t n) {
void* p = _aligned_malloc(n, __alignof(RandomEngine));
if (p == 0) throw std::bad_alloc();
return p;
}
/**
* delete[] operator with alignment (needed for Visual Studio)
**********************************************************************/
void operator delete[](void* p) { _aligned_free(p); }
#endif
/**
* \name Comparing Random objects
**********************************************************************/
///@{
/**
* Test equality of two Random objects. This test that the seeds match and
* that they have produced the same number of random numbers.
*
* @param[in] r the RandomEngine object to compare.
* @return true if the RandomEngine objects produce the same results.
**********************************************************************/
bool operator==(const RandomEngine& r) const throw()
// Ensure that the two Random objects behave the same way. Note however
// that the internal states may still be different, e.g., the following all
// result in Random objects which are == (with Count() == 0) but which all
// have different internal states:
//
// Random r(0); _ptr == UNINIT
// r.StepCount( 1); r.StepCount(-1); _ptr == 0, _rounds == 0
// r.StepCount(-1); r.StepCount( 1); _ptr == N, _rounds == -1
{ return Count() == r.Count() && _seed == r._seed &&
_stride == r._stride; }
/**
* Test inequality of two Random objects. See Random::operator==
*
* @param[in] r the RandomEngine object to compare.
* @return true if the RandomEngine objects produce different results.
**********************************************************************/
bool operator!=(const RandomEngine& r) const throw()
{ return !operator==(r); }
///@}
/**
* \name Interchanging Random objects
**********************************************************************/
///@{
/**
* Swap with another Random object.
*
* @param[in,out] t the RandomEngine object to swap with.
**********************************************************************/
void swap(RandomEngine& t) throw() {
_seed.swap(t._seed);
std::swap(_ptr, t._ptr);
std::swap(_stride, t._stride);
std::swap(_rounds, t._rounds);
std::swap_ranges(_state, _state + N, t._state);
}
///@}
/**
* \name Writing to and reading from a stream
**********************************************************************/
///@{
/**
* Save the state of the Random object to an output stream. Format is a
* sequence of unsigned 32-bit integers written either in decimal (\e bin
* false, text format) or in network order with most significant byte first
* (\e bin true, binary format). Data consists of:
*
* - RandomLib magic string + version (2 words)
* - Algorithm version (1 word)
* - Mixer version (1 word)
* - _seed.size() (1 word)
* - _seed data (_seed.size() words)
* - _ptr (1 word)
* - _stride (1 word)
* - if _ptr != UNINIT, _rounds (2 words)
* - if _ptr != UNINIT, _state (N words or 2 N words)
* - checksum
*
* Shortest possible saved result consists of 8 words. This corresponds to
* RandomSeed() = [] and Count() = 0.
*
* @param[in,out] os the output stream.
* @param[in] bin if true (the default) save in binary mode.
**********************************************************************/
void Save(std::ostream& os, bool bin = true) const;
/**
* Restore the state of the Random object from an input stream. If \e bin,
* read in binary, else use text format. See documentation of
* RandomEngine::Save for the format. Include error checking on data to
* make sure the input has not been corrupted. If an error occurs while
* reading, the Random object is unchanged.
*
* @param[in,out] is the input stream.
* @param[in] bin if true (the default) load in binary mode.
* @exception RandomErr if the state read from \e is is illegal.
**********************************************************************/
void Load(std::istream& is, bool bin = true) {
// Read state into temporary so as not to change object on error.
RandomEngine t(is, bin);
_seed.reserve(t._seed.size());
*this = t;
}
///@}
/**
* \name Basic I/O
**********************************************************************/
///@{
/**
* Write the state of a generator to stream \e os as text
*
* @param[in,out] os the output stream.
* @param[in] r the RandomEngine object to be saved.
**********************************************************************/
friend std::ostream& operator<<(std::ostream& os, const RandomEngine& r) {
r.Save(os, false);
return os;
}
/**
* Read the state of a generator from stream \e is as text
*
* @param[in,out] is the output stream.
* @param[in] r the RandomEngine object to be loaded.
* @exception RandomErr if the state read from \e is is illegal.
**********************************************************************/
friend std::istream& operator>>(std::istream& is, RandomEngine& r) {
r.Load(is, false);
return is;
}
///@}
/**
* \name Examining and advancing the Random generator
**********************************************************************/
///@{
/**
* Return the number of random numbers used. This needs to return a long
* long result since it can reasonably exceed 2<sup>31</sup>. (On a 1GHz
* machine, it takes about a minute to produce 2<sup>32</sup> random
* numbers.) More precisely this is the (zero-based) index of the next
* random number to be produced. (This distinction is important when
* leapfrogging is in effect.)
*
* @return the count of random numbers used.
**********************************************************************/
long long Count() const throw()
{ return _ptr == UNINIT ? 0 : _rounds * N + _ptr; }
/**
* Step the generator forwards or backwards so that the value returned
* by Count() is \e n
*
* @param[in] n the new count.
**********************************************************************/
void SetCount(long long n) throw() { StepCount(n - Count()); }
/**
* Step the generator forward \e n steps. \e n can be negative.
*
* @param[in] n how much to step the generator forward.
**********************************************************************/
void StepCount(long long n) throw();
/**
* Resets the sequence. Equivalent to SetCount(0), but works by
* reinitializing the Random object from its seed, rather than by stepping
* the sequence backwards. In addition, this undoes leapfrogging.
**********************************************************************/
void Reset() throw() { _ptr = UNINIT; _stride = 1; }
///@}
/**
* \name Leapfrogging
**********************************************************************/
///@{
/**
* Set leapfrogging stride to a positive number \e n and increment Count()
* by \e k < \e n. If the current Count() is \e i, then normally the next
* 3 random numbers would have (zero-based) indices \e i, \e i + 1, \e i +
* 2, and the new Count() is \e i + 2. However, after SetStride(\e n, \e
* k) the next 3 random numbers have indices \e i + \e k, \e i + \e k + \e
* n, \e i + \e k + 2\e n, and the new Count() is \e i + \e k + 3\e n.
* With leapfrogging in effect, the time to produce raw random numbers is
* roughly proportional to 1 + (\e n &minus; 1)/3. Reseed(...) and Reset()
* both reset the stride back to 1. See \ref parallel for a description of
* how to use this facility.
*
* @param[in] n the stride (default 1).
* @param[in] k the initial increment (default 0).
* @exception RandomErr if \e n is 0 or too large or if \e k is not less
* than \e n.
**********************************************************************/
void SetStride(unsigned n = 1, unsigned k = 0) {
// Limit stride to UNINIT/2. This catches negative numbers that have
// been cast into unsigned. In reality the stride should be no more than
// 10-100.
if (n == 0 || n > UNINIT/2)
throw RandomErr("RandomEngine: Invalid stride");
if (k >= n)
throw RandomErr("RandomEngine: Invalid offset");
_stride = n;
StepCount(k);
}
/**
* Return leapfrogging stride.
*
* @return the stride.
**********************************************************************/
unsigned GetStride() const throw() { return _stride; }
///@}
/**
* Tests basic engine.
*
* @exception RandomErr if any of the tests fail.
**********************************************************************/
static void SelfTest();
/**
* Return the name of the generator. This incorporates the names of the \e
* Algorithm and \e Mixer.
*
* @return the name of the generator.
**********************************************************************/
static std::string Name() {
return "RandomEngine<" + Algorithm::Name() + "," + Mixer::Name() + ">";
}
private:
/**
* Compute initial state from seed
**********************************************************************/
void Init() throw();
/**
* The interface to Transition used by Ran().
**********************************************************************/
void Next() throw() {
if (_ptr == UNINIT)
Init();
_rounds += _ptr/N;
Algorithm::Transition(_ptr/N, _statev);
_ptr %= N;
}
u32::type Check(u64::type v, u32::type e, u32::type m) const;
static result_type SelfTestResult(unsigned) throw() { return 0; }
/**
* Read from an input stream. Potentially corrupts object. This private
* constructor is used by RandomEngine::Load so that it can avoid
* corrupting its state on bad input.
**********************************************************************/
explicit RandomEngine(std::istream& is, bool bin);
#if !defined(RANDOMLIB_BUILDING_LIBRARY) && \
defined(HAVE_BOOST_SERIALIZATION) && HAVE_BOOST_SERIALIZATION
friend class boost::serialization::access;
/**
* Save to a boost archive. Boost versioning isn't very robust. (It
* allows a RandomGenerator32 to be read back in as a RandomGenerator64.
* It doesn't interact well with templates.) So we do our own versioning
* and supplement this with a checksum.
**********************************************************************/
template<class Archive> void save(Archive& ar, const unsigned int) const {
u64::type _version = version;
u32::type _eversion = Algorithm::version,
_mversion = Mixer::version,
_checksum = Check(_version, _eversion, _mversion);
ar & boost::serialization::make_nvp("version" , _version )
& boost::serialization::make_nvp("eversion", _eversion)
& boost::serialization::make_nvp("mversion", _mversion)
& boost::serialization::make_nvp("seed" , _seed )
& boost::serialization::make_nvp("ptr" , _ptr )
& boost::serialization::make_nvp("stride" , _stride );
if (_ptr != UNINIT)
ar & boost::serialization::make_nvp("rounds", _rounds )
& boost::serialization::make_nvp("state" , _state );
ar & boost::serialization::make_nvp("checksum", _checksum);
}
/**
* Load from a boost archive. Do this safely so that the current object is
* not corrupted if the archive is bogus.
**********************************************************************/
template<class Archive> void load(Archive& ar, const unsigned int) {
u64::type _version;
u32::type _eversion, _mversion, _checksum;
ar & boost::serialization::make_nvp("version" , _version )
& boost::serialization::make_nvp("eversion", _eversion )
& boost::serialization::make_nvp("mversion", _mversion );
RandomEngine<Algorithm, Mixer> t(std::vector<seed_type>(0));
ar & boost::serialization::make_nvp("seed" , t._seed )
& boost::serialization::make_nvp("ptr" , t._ptr )
& boost::serialization::make_nvp("stride" , t._stride );
if (t._ptr != UNINIT)
ar & boost::serialization::make_nvp("rounds", t._rounds )
& boost::serialization::make_nvp("state" , t._state );
ar & boost::serialization::make_nvp("checksum", _checksum );
if (t.Check(_version, _eversion, _mversion) != _checksum)
throw RandomErr("RandomEngine: Checksum failure");
_seed.reserve(t._seed.size());
*this = t;
}
/**
* Glue the boost save and load functionality together---a bit of boost
* magic.
**********************************************************************/
template<class Archive>
void serialize(Archive &ar, const unsigned int file_version)
{ boost::serialization::split_member(ar, *this, file_version); }
#endif // HAVE_BOOST_SERIALIZATION
};
typedef RandomEngine<MT19937 <Random_u32>, MixerSFMT> MRandomGenerator32;
typedef RandomEngine<MT19937 <Random_u64>, MixerSFMT> MRandomGenerator64;
typedef RandomEngine<SFMT19937<Random_u32>, MixerSFMT> SRandomGenerator32;
typedef RandomEngine<SFMT19937<Random_u64>, MixerSFMT> SRandomGenerator64;
} // namespace RandomLib
namespace std {
/**
* Swap two RandomEngines. This is about 3x faster than the default swap.
*
* @tparam Algorithm the algorithm for the RandomEngine.
* @tparam Mixer the mixer for the RandomEngine.
* @param[in,out] r the first RandomEngine to swap.
* @param[in,out] s the second RandomEngine to swap.
**********************************************************************/
template<class Algorithm, class Mixer>
void swap(RandomLib::RandomEngine<Algorithm, Mixer>& r,
RandomLib::RandomEngine<Algorithm, Mixer>& s) throw() {
r.swap(s);
}
} // namespace std
#endif // RANDOMLIB_RANDOMENGINE_HPP

View File

@ -1,258 +0,0 @@
/**
* \file RandomMixer.hpp
* \brief Header for Mixer classes.
*
* Mixer classes convert a seed vector into a random generator state. An
* important property of this method is that "close" seeds should produce
* "widely separated" states. This allows the seeds to be set is some
* systematic fashion to produce a set of uncorrelated random number
* sequences.
*
* Copyright (c) Charles Karney (2006-2011) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* http://randomlib.sourceforge.net/
**********************************************************************/
#if !defined(RANDOMLIB_RANDOMMIXER_HPP)
#define RANDOMLIB_RANDOMMIXER_HPP 1
#include <vector>
#include <string>
#include <RandomLib/RandomSeed.hpp>
namespace RandomLib {
/**
* \brief The original %MT19937 mixing functionality
*
* This implements the functionality of init_by_array in MT19937
* http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/CODES/mt19937ar.c
* and init_by_array64 in MT19937_64
* http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/VERSIONS/C-LANG/mt19937-64.c
* with the following changes:
* - in the case of an zero-length seed array, behave in the same way if
* MT19937 and MT19937_64 are called without initialization in which case,
* e.g., init_genrand(5489UL) is called. (init_by_array does not allow
* calling with a zero-length seed.)
* - init_by_array64 accepts a seed array of 64-bit unsigned ints. Here with
* seed is an array of 32-bit unsigned ints and these are repacked into
* 64-bit quantities internally using a LSB convention. Thus, to mimic the
* MT19937_64 sample invocation with a seed array {0x12345ULL, 0x23456ULL,
* 0x34567ULL, 0x45678ULL}, MixerMT0<Random_u64>::SeedToState needs to
* be invoked with a seed vector [0x12345UL, 0, 0x23456UL, 0, 0x34567UL, 0,
* 0x45678UL, 0]. (Actually the last 0 is unnecessary.)
*
* The template parameter \e RandomType switches between the 32-bit and
* 64-bit versions.
*
* MixerMT0 is specific to the MT19937 generators and should not be used
* for other generators (e.g., SFMT19937). In addition, MixerMT0 has
* known defects and should only be used to check the operation of the
* MT19937 engines against the original implementation. These defects are
* described in the MixerMT1 which is a modification of MixerMT0
* which corrects these defects. For production use MixerMT1 or,
* preferably, MixerSFMT should be used.
*
* @tparam RandomType the type of the results, either Random_u32 or
* Random_u64.
**********************************************************************/
template<class RandomType> class RANDOMLIB_EXPORT MixerMT0 {
public:
/**
* The RandomType controlling the output of MixerMT0::SeedToState
**********************************************************************/
typedef RandomType mixer_t;
/**
* A version number which should be unique to this RandomMixer. This
* prevents RandomEngine::Load from loading a saved generator with a
* different RandomMixer. Here the version is "MxMT" or "MxMU".
**********************************************************************/
static const unsigned version = 0x4d784d54UL + (mixer_t::width == 64);
private:
/**
* The unsigned type corresponding to mixer_t.
**********************************************************************/
typedef typename mixer_t::type mixer_type;
/**
* The mask for mixer_t.
**********************************************************************/
static const mixer_type mask = mixer_t::mask;
public:
/**
* Mix the seed vector, \e seed, into the state array, \e state, of size \e
* n.
*
* @param[in] seed the input seed vector.
* @param[out] state the generator state.
* @param[in] n the size of the state.
**********************************************************************/
static void SeedToState(const std::vector<RandomSeed::seed_type>& seed,
mixer_type state[], unsigned n) throw();
/**
* Return the name of this class.
*
* @return the name.
**********************************************************************/
static std::string Name() {
return "MixerMT0<Random_u" +
std::string(mixer_t::width == 32 ? "32" : "64") + ">";
}
private:
static const mixer_type a0 = 5489ULL;
static const mixer_type a1 = 19650218ULL;
static const mixer_type
b = mixer_t::width == 32 ? 1812433253ULL : 6364136223846793005ULL;
static const mixer_type
c = mixer_t::width == 32 ? 1664525ULL : 3935559000370003845ULL;
static const mixer_type
d = mixer_t::width == 32 ? 1566083941ULL : 2862933555777941757ULL;
};
/**
* \brief The modified %MT19937 mixing functionality
*
* MixerMT0 has two defects
* - The zeroth word of the state is set to a constant (independent of the
* seed). This is a relatively minor defect which halves the accessible
* state space for MT19937 (but the resulting state space is still huge).
* (Actually, for the 64-bit version, it reduces the accessible states by
* 2<sup>33</sup>. On the other hand the 64-bit has better mixing
* properties.)
* - Close seeds, for example, [1] and [1,0], result in the same state. This
* is a potentially serious flaw which might result is identical random
* number sequences being generated instead of independent sequences.
*
* MixerMT1 fixes these defects in a straightforward manner. The
* resulting algorithm was included in one of the proposals for Random Number
* Generation for C++0X, see Brown, et al.,
* http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2079.pdf
*
* The template parameter \e RandomType switches between the 32-bit and
* 64-bit versions.
*
* MixerMT1 still has a weakness in that it doesn't thoroughly mix the
* state. This is illustrated by an example given to me by Makoto Matsumoto:
* Consider a seed of length \e N and suppose we consider all \e
* W<sup><i>N</i>/2</sup> values for the first half of the seed (here \e W =
* 2<sup><i>width</i></sup>). MixerMT1 has a bottleneck in the way that
* the state is initialized which results in the second half of the state
* only taking on \e W<sup>2</sup> possible values. MixerSFMT mixes the
* seed into the state much more thoroughly.
*
* @tparam RandomType the type of the results, either Random_u32 or
* Random_u64.
**********************************************************************/
template<class RandomType> class RANDOMLIB_EXPORT MixerMT1 {
public:
/**
* The RandomType controlling the output of MixerMT1::SeedToState
**********************************************************************/
typedef RandomType mixer_t;
/**
* A version number which should be unique to this RandomMixer. This
* prevents RandomEngine::Load from loading a saved generator with a
* different RandomMixer. Here the version is "MxMV" or "MxMW".
**********************************************************************/
static const unsigned version = 0x4d784d56UL + (mixer_t::width == 64);
private:
/**
* The unsigned type corresponding to mixer_t.
**********************************************************************/
typedef typename mixer_t::type mixer_type;
/**
* The mask for mixer_t.
**********************************************************************/
static const mixer_type mask = mixer_t::mask;
public:
/**
* Mix the seed vector, \e seed, into the state array, \e state, of size \e
* n.
*
* @param[in] seed the input seed vector.
* @param[out] state the generator state.
* @param[in] n the size of the state.
**********************************************************************/
static void SeedToState(const std::vector<RandomSeed::seed_type>& seed,
mixer_type state[], unsigned n) throw();
/**
* Return the name of this class.
*
* @return the name.
**********************************************************************/
static std::string Name() {
return "MixerMT1<Random_u" +
std::string(mixer_t::width == 32 ? "32" : "64") + ">";
}
private:
static const mixer_type a = 5489ULL;
static const mixer_type
b = mixer_t::width == 32 ? 1812433253ULL : 6364136223846793005ULL;
static const mixer_type
c = mixer_t::width == 32 ? 1664525ULL : 3935559000370003845ULL;
static const mixer_type
d = mixer_t::width == 32 ? 1566083941ULL : 2862933555777941757ULL;
};
/**
* \brief The SFMT mixing functionality
*
* MixerSFMT is adapted from SFMT's init_by_array Mutsuo Saito given in
* http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/SFMT-src-1.2.tar.gz
* and is part of the C++11 standard; see P. Becker, Working Draft, Standard
* for Programming Language C++, Oct. 2007, Sec. 26.4.7.1,
* http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2461.pdf
*
* MixerSFMT contains a single change is to allow it to function properly
* when the size of the state is small.
*
* MixerSFMT mixes the seed much more thoroughly than MixerMT1 and, in
* particular, it removes the mixing bottleneck present in MixerMT1.
* Thus it is the recommended mixing scheme for all production work.
**********************************************************************/
class RANDOMLIB_EXPORT MixerSFMT {
public:
/**
* The RandomType controlling the output of MixerSFMT::SeedToState
**********************************************************************/
typedef Random_u32 mixer_t;
/**
* A version number which should be unique to this RandomMixer. This
* prevents RandomEngine::Load from loading a saved generator with a
* different RandomMixer. Here the version is "MxSM".
**********************************************************************/
static const unsigned version = 0x4d78534dUL;
private:
/**
* The unsigned type corresponding to mixer_t.
**********************************************************************/
typedef mixer_t::type mixer_type;
/**
* The mask for mixer_t.
**********************************************************************/
static const mixer_type mask = mixer_t::mask;
public:
/**
* Mix the seed vector, \e seed, into the state array, \e state, of size \e
* n.
*
* @param[in] seed the input seed vector.
* @param[out] state the generator state.
* @param[in] n the size of the state.
**********************************************************************/
static void SeedToState(const std::vector<RandomSeed::seed_type>& seed,
mixer_type state[], unsigned n) throw();
/**
* Return the name of this class.
*
* @return the name.
**********************************************************************/
static std::string Name() { return "MixerSFMT"; }
private:
static const mixer_type a = 0x8b8b8b8bUL;
static const mixer_type b = 1664525UL;
static const mixer_type c = 1566083941UL;
};
} // namespace RandomLib
#endif // RANDOMLIB_RANDOMMIXER_HPP

View File

@ -1,472 +0,0 @@
/**
* \file RandomNumber.hpp
* \brief Header for RandomNumber
*
* Infinite precision random numbers.
*
* Copyright (c) Charles Karney (2006-2013) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* http://randomlib.sourceforge.net/
**********************************************************************/
#if !defined(RANDOMLIB_RANDOMNUMBER_HPP)
#define RANDOMLIB_RANDOMNUMBER_HPP 1
#include <vector>
#include <iomanip>
#include <limits>
#include <cmath> // for std::pow
#include <RandomLib/UniformInteger.hpp>
namespace RandomLib {
/**
* \brief Infinite precision random numbers.
*
* Implement infinite precision random numbers. Integer part is non-random.
* Fraction part consists of any some number of digits in base
* 2<sup><i>b</i></sup>. If \e m digits have been generated then the
* fraction is uniformly distributed in the open interval
* &sum;<sub><i>k</i>=1</sub><sup><i>m</i></sup>
* <i>f</i><sub><i>k</i>&minus;1</sub>/2<sup><i>kb</i></sup> +
* (0,1)/2<sup><i>mb</i></sup>. When a RandomNumber is first constructed the
* integer part is zero and \e m = 0, and the number represents (0,1). A
* RandomNumber is able to represent all numbers in the symmetric open
* interval (&minus;2<sup>31</sup>, 2<sup>31</sup>). In this implementation,
* \e b must one of 1, 2, 3, 4, 8, 12, 16, 20, 24, 28, or 32. (This
* restriction allows printing in hexadecimal and can easily be relaxed.
* There's also no essential reason why the base should be a power of 2.)
*
* @tparam bits the number of bits in each digit.
**********************************************************************/
template<int bits = 1> class RandomNumber {
public:
/**
* Constructor sets number to a random number uniformly distributed in
* (0,1).
**********************************************************************/
RandomNumber() throw() : _n(0), _s(1) {}
/**
* Swap with another RandomNumber. This is a fast way of doing an
* assignment.
*
* @param[in,out] t the RandomNumber to swap with.
**********************************************************************/
void swap(RandomNumber& t) throw() {
if (this != &t) {
std::swap(_n, t._n);
std::swap(_s, t._s);
_f.swap(t._f);
}
}
/**
* Return to initial state, uniformly distributed in (0,1).
**********************************************************************/
void Init() throw() {
STATIC_ASSERT(bits > 0 && bits <= w && (bits < 4 || bits % 4 == 0),
"RandomNumber: unsupported value for bits");
_n = 0;
_s = 1;
_f.clear();
}
/**
* @return the sign of the RandomNumber (&plusmn; 1).
**********************************************************************/
int Sign() const throw() { return _s; }
/**
* Change the sign of the RandomNumber.
**********************************************************************/
void Negate() throw() { _s *= -1; }
/**
* @return the floor of the RandomNumber.
**********************************************************************/
int Floor() const throw() { return _s > 0 ? int(_n) : -1 - int(_n); }
/**
* @return the ceiling of the RandomNumber.
**********************************************************************/
int Ceiling() const throw() { return _s > 0 ? 1 + int(_n) : - int(_n); }
/**
* @return the unsigned integer component of the RandomNumber.
**********************************************************************/
unsigned UInteger() const throw() { return _n; }
/**
* Add integer \e k to the RandomNumber.
*
* @param[in] k the integer to add.
**********************************************************************/
void AddInteger(int k) throw() {
k += Floor(); // The new floor
int ns = k < 0 ? -1 : 1; // The new sign
if (ns != _s) // If sign changes, set f = 1 - f
for (size_t k = 0; k < Size(); ++k)
_f[k] = ~_f[k] & mask;
_n = ns > 0 ? k : -(k + 1);
}
/**
* Compare with another RandomNumber, *this &lt; \e t
*
* @tparam Random the type of the random generator.
* @param[in,out] r a random generator.
* @param[in,out] t a RandomNumber to compare.
* @return true if *this &lt; \e t.
**********************************************************************/
template<class Random> bool LessThan(Random& r, RandomNumber& t) {
if (this == &t) return false; // same object
if (_s != t._s) return _s < t._s;
if (_n != t._n) return (_s < 0) ^ (_n < t._n);
for (unsigned k = 0; ; ++k) {
// Impose an order on the evaluation of the digits.
const unsigned x = Digit(r,k);
const unsigned y = t.Digit(r,k);
if (x != y) return (_s < 0) ^ (x < y);
// Two distinct numbers are never equal
}
}
/**
* Compare RandomNumber with two others, *this &gt; max(\e u, \e v)
*
* @tparam Random the type of the random generator.
* @param[in,out] r a random generator.
* @param[in,out] u first RandomNumber to compare.
* @param[in,out] v second RandomNumber to compare.
* @return true if *this &gt; max(\e u, \e v).
**********************************************************************/
template<class Random> bool GreaterPair(Random& r,
RandomNumber& u, RandomNumber& v) {
// cmps is set to false as soon as u <= *this, and likewise for cmpt.
bool cmpu = this != &u, cmpv = this != &v && &u != &v;
if (!(cmpu || cmpv)) return true;
// Check signs first
if (cmpu) {
if (u._s > _s) return false; // u > *this
if (u._s < _s) cmpu = false;
}
if (cmpv) {
if (v._s > _s) return false; // v > *this
if (v._s < _s) cmpv = false;
}
if (!(cmpu || cmpv)) return true; // u <= *this && v <= *this
// Check integer parts
if (cmpu) {
if ((_s < 0) ^ (u._n > _n)) return false; // u > *this
if ((_s < 0) ^ (u._n < _n)) cmpu = false;
}
if (cmpv) {
if ((_s < 0) ^ (v._n > _n)) return false; // v > *this
if ((_s < 0) ^ (v._n < _n)) cmpv = false;
}
if (!(cmpu || cmpv)) return true; // u <= *this && v <= *this
// Check fractions
for (unsigned k = 0; ; ++k) {
// Impose an order on the evaluation of the digits. Note that this is
// asymmetric on interchange of u and v; since u is tested first, more
// digits of u are generated than v (on average).
const unsigned x = Digit(r,k);
if (cmpu) {
const unsigned y = u.Digit(r,k);
if ((_s < 0) ^ (y > x)) return false; // u > *this
if ((_s < 0) ^ (y < x)) cmpu = false;
}
if (cmpv) {
const unsigned y = v.Digit(r,k);
if ((_s < 0) ^ (y > x)) return false; // v > *this
if ((_s < 0) ^ (y < x)) cmpv = false;
}
if (!(cmpu || cmpv)) return true; // u <= *this && v <= *this
}
}
/**
* Compare with a fraction, *this &lt; <i>p</i>/<i>q</i>
*
* @tparam Random the type of the random generator.
* @param[in,out] r a random generator.
* @param[in] p the numerator of the fraction.
* @param[in] q the denominator of the fraction (require \e q &gt; 0).
* @return true if *this &lt; <i>p</i>/<i>q</i>.
**********************************************************************/
template<class Random, typename IntType>
bool LessThan(Random& r, IntType p, IntType q) {
for (int k = 0;; ++k) {
if (p <= 0) return false;
if (p >= q) return true;
// Here p is in [1,q-1]. Need to avoid overflow in computation of
// (q-1)<<bits and (2^bits-1)*q
p = (p << bits) - Digit(r,k) * q;
}
}
/**
* Compare with a paritally sampled fraction
*
* @tparam Random the type of the random generator.
* @param[in,out] r a random generator.
* @param[in] p0 the starting point for the numerator.
* @param[in] c the stride for the fraction (require \e c &gt; 0).
* @param[in] q the denominator of the fraction (require \e q &gt; 0).
* @param[in,out] j the increment for the numerator.
* @return true if *this &lt; (<i>p</i><sub>0</sub> + <i>cj</i>)/<i>q</i>.
**********************************************************************/
template<class Random, typename IntType>
bool LessThan(Random& r, IntType p0, IntType c, IntType q,
UniformInteger<IntType, bits>& j) {
for (int k = 0;; ++k) {
if (j. LessThanEqual(r, - p0, c)) return false;
if (j.GreaterThanEqual(r, q - p0, c)) return true;
p0 = (p0 << bits) - IntType(Digit(r,k)) * q;
c <<= bits;
}
}
/**
* @tparam Random the type of the random generator.
* @param[in,out] r a random generator.
* @param[in] k the index of a digit of the fraction
* @return digit number \e k, generating it if necessary.
**********************************************************************/
template<class Random> unsigned Digit(Random& r, unsigned k) {
ExpandTo(r, k + 1);
return _f[k];
}
/**
* Add one digit to the fraction.
*
* @tparam Random the type of the random generator.
* @param[in,out] r a random generator.
**********************************************************************/
template<class Random> void AddDigit(Random& r)
{ _f.push_back(RandomDigit(r)); }
/**
* @param[in] k the index of a digit of the fraction
* @return a const reference to digit number \e k, without generating new
* digits.
* @exception std::out_of_range if the digit hasn't been generated.
**********************************************************************/
const unsigned& RawDigit(unsigned k) const throw()
{ return (const unsigned&)(_f.at(k)); }
/**
* @param[in] k the index of a digit of the fraction
* @return a non-const reference to digit number \e k, without generating
* new digits.
* @exception std::out_of_range if the digit hasn't been generated.
**********************************************************************/
unsigned& RawDigit(unsigned k) throw()
{ return (unsigned&)(_f.at(k)); }
/**
* Return to initial state, uniformly distributed in \e n + (0,1). This is
* similar to Init but also returns the memory used by the object to the
* system. Normally Init should be used.
**********************************************************************/
void Clear() {
std::vector<unsigned> z(0);
_n = 0;
_s = 1;
_f.swap(z);
}
/**
* @return the number of digits in fraction
**********************************************************************/
unsigned Size() const throw() { return unsigned(_f.size()); }
/**
* Return the fraction part of the RandomNumber as a floating point number
* of type RealType rounded to the nearest multiple of
* 1/2<sup><i>p</i></sup>, where \e p =
* std::numeric_limits<RealType>::digits, and, if necessary, creating
* additional digits of the number.
*
* @tparam RealType the floating point type to convert to.
* @tparam Random the type of the random generator.
* @param[in,out] r a random generator for generating the necessary digits.
* @return the fraction of the RandomNumber rounded to a RealType.
**********************************************************************/
template<typename RealType, typename Random> RealType Fraction(Random& r) {
STATIC_ASSERT(!std::numeric_limits<RealType>::is_integer,
"RandomNumber::Fraction: invalid real type RealType");
const int d = std::numeric_limits<RealType>::digits;
const int k = (d + bits - 1)/bits;
const int kg = (d + bits)/bits; // For guard bit
RealType y = 0;
if (Digit(r, kg - 1) & (1U << (kg * bits - d - 1)))
// if guard bit is set, round up.
y += std::pow(RealType(2), -d);
const RealType fact = std::pow(RealType(2), -bits);
RealType mult = RealType(1);
for (int i = 0; i < k; ++i) {
mult *= fact;
y += mult * RealType(i < k - 1 ? RawDigit(i) :
RawDigit(i) & (~0U << (k * bits - d)));
}
return y;
}
/**
* Return the value of the RandomNumber rounded to nearest floating point
* number of type RealType and, if necessary, creating additional digits of
* the number.
*
* @tparam RealType the floating point type to convert to.
* @tparam Random the type of the random generator.
* @param[in,out] r a random generator for generating the necessary digits.
* @return the value of the RandomNumber rounded to a RealType.
**********************************************************************/
template<typename RealType, class Random> RealType Value(Random& r) {
// Ignore the possibility of overflow here (OK because int doesn't
// currently overflow any real type). Assume the real type supports
// denormalized numbers. Need to treat rounding explicitly since the
// missing digits always imply rounding up.
STATIC_ASSERT(!std::numeric_limits<RealType>::is_integer,
"RandomNumber::Value: invalid real type RealType");
const int digits = std::numeric_limits<RealType>::digits,
min_exp = std::numeric_limits<RealType>::min_exponent;
RealType y;
int lead; // Position of leading bit (0.5 = position 0)
if (_n) lead = highest_bit_idx(_n);
else {
int i = 0;
while ( Digit(r, i) == 0 && i < (-min_exp)/bits ) ++i;
lead = highest_bit_idx(RawDigit(i)) - (i + 1) * bits;
// To handle denormalized numbers set lead = max(lead, min_exp)
lead = lead > min_exp ? lead : min_exp;
}
int trail = lead - digits; // Position of guard bit (0.5 = position 0)
if (trail > 0) {
y = RealType(_n & (~0U << trail));
if (_n & (1U << (trail - 1)))
y += std::pow(RealType(2), trail);
} else {
y = RealType(_n);
int k = (-trail)/bits; // Byte with guard bit
if (Digit(r, k) & (1U << ((k + 1) * bits + trail - 1)))
// If guard bit is set, round bit (some subsequent bit will be 1).
y += std::pow(RealType(2), trail);
// Byte with trailing bit (can be negative)
k = (-trail - 1 + bits)/bits - 1;
const RealType fact = std::pow(RealType(2), -bits);
RealType mult = RealType(1);
for (int i = 0; i <= k; ++i) {
mult *= fact;
y += mult *
RealType(i < k ? RawDigit(i) :
RawDigit(i) & (~0U << ((k + 1) * bits + trail)));
}
}
if (_s < 0) y *= -1;
return y;
}
/**
* Return the range of possible values for the RandomNumber as pair of
* doubles. This doesn't create any additional digits of the result and
* doesn't try to control roundoff.
*
* @return a pair denoting the range with first being the lower limit and
* second being the upper limit.
**********************************************************************/
std::pair<double, double> Range() const throw() {
double y = _n;
const double fact = std::pow(double(2), -bits);
double mult = double(1);
for (unsigned i = 0; i < Size(); ++i) {
mult *= fact;
y += mult * RawDigit(i);
}
return std::pair<double, double>(_s > 0 ? y : -(y + mult),
_s > 0 ? (y + mult) : -y);
}
/**
* @tparam Random the type of the random generator.
* @param[in,out] r a random generator.
* @return a random digit in [0, 2<sup><i>bits</i></sup>).
**********************************************************************/
template<class Random> static unsigned RandomDigit(Random& r) throw()
{ return unsigned(r.template Integer<bits>()); }
private:
/**
* The integer part
**********************************************************************/
unsigned _n;
/**
* The sign
**********************************************************************/
int _s;
/**
* The fraction part
**********************************************************************/
std::vector<unsigned> _f;
/**
* Fill RandomNumber to \e k digits.
**********************************************************************/
template<class Random> void ExpandTo(Random& r, size_t k) {
size_t l = _f.size();
if (k <= l)
return;
_f.resize(k);
for (size_t i = l; i < k; ++i)
_f[i] = RandomDigit(r);
}
/**
* Return index [0..32] of highest bit set. Return 0 if x = 0, 32 is if x
* = ~0. (From Algorithms for programmers by Joerg Arndt.)
**********************************************************************/
static int highest_bit_idx(unsigned x) throw() {
if (x == 0) return 0;
int r = 1;
if (x & 0xffff0000U) { x >>= 16; r += 16; }
if (x & 0x0000ff00U) { x >>= 8; r += 8; }
if (x & 0x000000f0U) { x >>= 4; r += 4; }
if (x & 0x0000000cU) { x >>= 2; r += 2; }
if (x & 0x00000002U) { r += 1; }
return r;
}
/**
* The number of bits in unsigned.
**********************************************************************/
static const int w = std::numeric_limits<unsigned>::digits;
public:
/**
* A mask for the digits.
**********************************************************************/
static const unsigned mask =
bits == w ? ~0U : ~(~0U << (bits < w ? bits : 0));
};
/**
* \relates RandomNumber
* Print a RandomNumber. Format is n.dddd... where the base for printing is
* 2<sup>max(4,<i>b</i>)</sup>. The ... represents an infinite sequence of
* ungenerated random digits (uniformly distributed). Thus with \e b = 1,
* 0.0... = (0,1/2), 0.00... = (0,1/4), 0.11... = (3/4,1), etc.
**********************************************************************/
template<int bits>
std::ostream& operator<<(std::ostream& os, const RandomNumber<bits>& n) {
const std::ios::fmtflags oldflags = os.flags();
RandomNumber<bits> t = n;
os << (t.Sign() > 0 ? "+" : "-");
unsigned i = t.UInteger();
os << std::hex << std::setfill('0');
if (i == 0)
os << "0";
else {
bool first = true;
const int w = std::numeric_limits<unsigned>::digits;
const unsigned mask = RandomNumber<bits>::mask;
for (int s = ((w + bits - 1)/bits) * bits - bits; s >= 0; s -= bits) {
unsigned d = mask & (i >> s);
if (d || !first) {
if (first) {
os << d;
first = false;
}
else
os << std::setw((bits+3)/4) << d;
}
}
}
os << ".";
unsigned s = t.Size();
for (unsigned i = 0; i < s; ++i)
os << std::setw((bits+3)/4) << t.RawDigit(i);
os << "..." << std::setfill(' ');
os.flags(oldflags);
return os;
}
} // namespace RandomLib
#endif // RANDOMLIB_RANDOMNUMBER_HPP

View File

@ -1,77 +0,0 @@
/**
* \file RandomPower2.hpp
* \brief Header for RandomPower2.
*
* Return and multiply by powers of two.
*
* Copyright (c) Charles Karney (2006-2011) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* http://randomlib.sourceforge.net/
**********************************************************************/
#if !defined(RANDOMLIB_RANDOMPOWER2_HPP)
#define RANDOMLIB_RANDOMPOWER2_HPP 1
#include <cmath> // For std::pow
namespace RandomLib {
/**
* \brief Return or multiply by powers of 2
*
* With some compilers it's fastest to do a table lookup of powers of
* 2. If RANDOMLIB_POWERTABLE is 1, a lookup table is used. If
* RANDOMLIB_POWERTABLE is 0, then std::pow is used.
**********************************************************************/
class RANDOMLIB_EXPORT RandomPower2 {
public:
/**
* Return powers of 2 (either using a lookup table or std::pow)
*
* @param[in] n the integer power.
* @return 2<sup><i>n</i></sup>.
**********************************************************************/
template<typename RealType> static inline RealType pow2(int n) throw() {
#if RANDOMLIB_POWERTABLE
return RealType(power2[n - minpow]);
#else
return std::pow(RealType(2), n);
#endif
}
/**
* Multiply a real by a power of 2
*
* @tparam RealType the type of \e x.
* @param[in] x the real number.
* @param[in] n the power (positive or negative).
* @return \e x 2<sup><i>n</i></sup>.
**********************************************************************/
template<typename RealType>
static inline RealType shiftf(RealType x, int n) throw()
// std::ldexp(x, n); is equivalent, but slower
{ return x * pow2<RealType>(n); }
// Constants
enum {
/**
* Minimum power in RandomPower2::power2
**********************************************************************/
#if RANDOMLIB_LONGDOUBLEPREC > 64
minpow = -120,
#else
minpow = -64,
#endif
maxpow = 64 /**< Maximum power in RandomPower2::power2. */
};
private:
#if RANDOMLIB_POWERTABLE
/**
* Table of powers of two
**********************************************************************/
static const float power2[maxpow - minpow + 1]; // Powers of two
#endif
};
} // namespace RandomLib
#endif // RANDOMLIB_RANDOMPOWER2_HPP

View File

@ -1,251 +0,0 @@
/**
* \file RandomSeed.hpp
* \brief Header for RandomSeed
*
* This provides a base class for random generators.
*
* Copyright (c) Charles Karney (2006-2011) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* http://randomlib.sourceforge.net/
**********************************************************************/
#if !defined(RANDOMLIB_RANDOMSEED_HPP)
#define RANDOMLIB_RANDOMSEED_HPP 1
#include <iostream>
#include <stdexcept>
#include <vector>
#include <iterator>
#include <algorithm> // For std::transform
#include <sstream> // For VectorToString
#include <RandomLib/RandomType.hpp>
#if defined(_MSC_VER)
// Squelch warnings about dll vs vector
#pragma warning (push)
#pragma warning (disable: 4251)
#endif
namespace RandomLib {
/**
* \brief A base class for random generators
*
* This provides facilities for managing the seed and for converting the seed
* into random generator state.
*
* The seed is taken to be a vector of unsigned longs of arbitrary length.
* (Only the low 32 bit of each element of the vector are used.) The class
* provides several methods for setting the seed, static functions for
* producing "random" and "unique" seeds, and facilities for converting the
* seed to a string so that it can be printed easily.
*
* The seeding algorithms are those used by
* <a href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html">
* MT19937</a> with some modifications to make all states accessible and to
* minimize the likelihood of different seeds giving the same state.
*
* Finally some low-level routines are provided to facilitate the creation of
* I/O methods for the random generator.
*
* A random generator class can be written based on this class. The
* generator class would use the base class methods for setting the seed and
* for converting the seed into state. It would provide the machinery for
* advancing the state and for producing random data. It is also responsible
* for the routine to save and restore the generator state (including the
* seed).
*
* Written by Charles Karney <charles@karney.com> and licensed under the
* MIT/X11 License. The seeding algorithms are adapted from those of
* <a href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html">
* MT19937</a>. For more information, see http://randomlib.sourceforge.net/
**********************************************************************/
class RANDOMLIB_EXPORT RandomSeed {
public:
typedef Random_u32 u32;
typedef Random_u64 u64;
virtual ~RandomSeed() throw() = 0;
/**
* A type large enough to hold the seed words. This is needs to hold 32
* bits and is an unsigned long for portability.
**********************************************************************/
typedef RandomType<32, unsigned long> seed_t;
typedef seed_t::type seed_type;
/**
* \name Resetting the seed
**********************************************************************/
///@{
/**
* Set the seed to a vector \e v. Only the low \e 32 bits of each element
* are used.
*
* @tparam IntType the integral type of the elements of the vector.
* @param[in] v the vector of elements.
**********************************************************************/
template<typename IntType> void Reseed(const std::vector<IntType>& v) {
Reseed(v.begin(), v.end());
}
/**
* Set the seed to [\e a, \e b) from a pair of iterators. The iterator
* must produce results which can be converted into seed_type. Only the
* low 32 bits of each element are used.
*
* @tparam InputIterator the type of the iterator.
* @param[in] a the beginning iterator.
* @param[in] b the ending iterator.
**********************************************************************/
template<typename InputIterator>
void Reseed(InputIterator a, InputIterator b) {
// Read new seed into temporary so as not to change object on error.
std::vector<seed_type> t;
std::transform(a, b, back_inserter(t),
seed_t::cast<typename std::iterator_traits<InputIterator>
::value_type>);
_seed.swap(t);
Reset();
}
/**
* Set the seed to [\e n]. Only the low 32 bits of \e n are used.
*
* @param[in] n the new seed to use.
**********************************************************************/
void Reseed(seed_type n) {
// Reserve space for new seed so as not to change object on error.
_seed.reserve(1);
_seed.resize(1);
_seed[0] = seed_t::cast(n);
Reset();
}
/**
* Set the seed to [SeedVector()]. This is the standard way to reseed with
* a "unique" seed.
**********************************************************************/
void Reseed() { Reseed(SeedVector()); }
/**
* Set the seed from the string \e s using Random::StringToVector.
*
* @param[in] s the string to be decoded into a seed.
**********************************************************************/
void Reseed(const std::string& s) {
// Read new seed into temporary so as not to change object on error.
std::vector<seed_type> t = StringToVector(s);
_seed.swap(t);
Reset();
}
///@}
/**
* \name Examining the seed
**********************************************************************/
///@{
/**
* Return reference to the seed vector (read-only).
*
* @return the seed vector.
**********************************************************************/
const std::vector<seed_type>& Seed() const throw() { return _seed; }
/**
* Format the current seed suitable for printing.
*
* @return the seedd as a string.
**********************************************************************/
std::string SeedString() const { return VectorToString(_seed); }
///@}
/**
* \name Resetting the random seed
**********************************************************************/
///@{
/**
* Resets the sequence to its just-seeded state. This needs to be declared
* virtual here so that the Reseed functions can call it after saving the
* seed.
**********************************************************************/
virtual void Reset() throw() = 0;
///@}
/**
* \name Static functions for seed management
**********************************************************************/
///@{
/**
* Return a 32 bits of data suitable for seeding the random generator. The
* result is obtained by combining data from /dev/urandom, gettimeofday,
* time, and getpid to provide a reasonably "random" word of data.
* Usually, it is safer to seed the random generator with SeedVector()
* instead of SeedWord().
*
* @return a single "more-or-less random" seed_type to be used as a seed.
**********************************************************************/
static seed_type SeedWord();
/**
* Return a vector of unsigned longs suitable for seeding the random
* generator. The vector is almost certainly unique; however, the results
* of successive calls to Random::SeedVector() will be correlated. If
* several Random objects are required within a single program execution,
* call Random::SeedVector once, print it out (!), push_back additional
* data to identify the instance (e.g., loop index, thread ID, etc.), and
* use the result to seed the Random object. The number of elements
* included in the vector may depend on the operating system. Additional
* elements may be added in future versions of this library.
*
* @return a "unique" vector of seed_type to be uses as a seed.
**********************************************************************/
static std::vector<seed_type> SeedVector();
/**
* Convert a vector into a string suitable for printing or as an argument
* for Random::Reseed(const std::string& s).
*
* @tparam IntType the integral type of the elements of the vector.
* @param[in] v the vector to be converted.
* @return the resulting string.
**********************************************************************/
template<typename IntType>
static std::string VectorToString(const std::vector<IntType>& v) {
std::ostringstream os;
os << "[";
for (typename std::vector<IntType>::const_iterator n = v.begin();
n != v.end(); ++n) {
if (n != v.begin())
os << ",";
// Normalize in case this is called by user.
os << seed_t::cast(*n);
}
os << "]";
return os.str();
}
/**
* Convert a string into a vector of seed_type suitable for printing or as
* an argument for Random::Reseed(const std::vector<seed_type>& v). Reads
* consecutive digits in string. Thus "[1,2,3]" => [1,2,3]; "-0.123e-4" =>
* [0,123,4], etc. strtoul understands C's notation for octal and
* hexadecimal, for example "012 10 0xa" => [10,10,10]. Reading of a
* number stops at the first illegal character for the base. Thus
* "2006-04-08" => [2006,4,0,8] (i.e., 08 becomes two numbers). Note that
* input numbers greater than ULONG_MAX overflow to ULONG_MAX, which
* probably will result in the number being interpreted as LONG_MASK.
*
* @param[in] s the string to be converted.
* @return the resulting vector of seed_type.
**********************************************************************/
static std::vector<seed_type> StringToVector(const std::string& s);
///@}
protected:
/**
* The seed vector
**********************************************************************/
std::vector<seed_type> _seed;
};
inline RandomSeed::~RandomSeed() throw() {}
} // namespace RandomLib
#if defined(_MSC_VER)
#pragma warning (pop)
#endif
#endif // RANDOMLIB_RANDOMSEED_HPP

View File

@ -1,335 +0,0 @@
/**
* \file RandomSelect.hpp
* \brief Header for RandomSelect.
*
* An implementation of the Walker algorithm for selecting from a finite set.
*
* Copyright (c) Charles Karney (2006-2011) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* http://randomlib.sourceforge.net/
**********************************************************************/
#if !defined(RANDOMLIB_RANDOMSELECT_HPP)
#define RANDOMLIB_RANDOMSELECT_HPP 1
#include <vector>
#include <limits>
#include <stdexcept>
#if defined(_MSC_VER)
// Squelch warnings about constant conditional expressions
# pragma warning (push)
# pragma warning (disable: 4127)
#endif
namespace RandomLib {
/**
* \brief Random selection from a discrete set.
*
* An implementation of Walker algorithm for selecting from a finite set
* (following Knuth, TAOCP, Vol 2, Sec 3.4.1.A). This provides a rapid way
* of selecting one of several choices depending on a discrete set weights.
* Original citation is\n A. J. Walker,\n An Efficient Method for Generating
* Discrete Random Variables and General Distributions,\n ACM TOMS 3,
* 253--256 (1977).
*
* There are two changes here in the setup algorithm as given by Knuth:
*
* - The probabilities aren't sorted at the beginning of the setup; nor are
* they maintained in a sorted order. Instead they are just partitioned on
* the mean. This improves the setup time from O(\e k<sup>2</sup>) to O(\e
* k).
*
* - The internal calculations are carried out with type \e NumericType. If
* the input weights are of integer type, then choosing an integer type for
* \e NumericType yields an exact solution for the returned distribution
* (assuming that the underlying random generator is exact.)
*
* Example:
* \code
#include <RandomLib/RandomSelect.hpp>
// Weights for throwing a pair of dice
unsigned w[] = { 0, 0, 1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1 };
// Initialize selection
RandomLib::RandomSelect<unsigned> sel(w, w + 13);
RandomLib::Random r; // Initialize random numbers
std::cout << "Seed set to " << r.SeedString() << "\n";
std::cout << "Throw a pair of dice 100 times:";
for (unsigned i = 0; i < 100; ++i)
std::cout << " " << sel(r);
std::cout << "\n";
\endcode
*
* @tparam NumericType the numeric type to use (default double).
**********************************************************************/
template<typename NumericType = double> class RandomSelect {
public:
/**
* Initialize in a cleared state (equivalent to having a single
* choice).
**********************************************************************/
RandomSelect() : _k(0), _wsum(0), _wmax(0) {}
/**
* Initialize with a weight vector \e w of elements of type \e WeightType.
* Internal calculations are carried out with type \e NumericType. \e
* NumericType needs to allow Choices() * MaxWeight() to be represented.
* Sensible combinations are:
* - \e WeightType integer, \e NumericType integer with
* digits(\e NumericType) &ge; digits(\e WeightType)
* - \e WeightType integer, \e NumericType real
* - \e WeightType real, \e NumericType real with digits(\e NumericType)
* &ge; digits(\e WeightType)
*
* @tparam WeightType the type of the weights.
* @param[in] w the vector of weights.
* @exception RandomErr if any of the weights are negative or if the total
* weight is not positive.
**********************************************************************/
template<typename WeightType>
RandomSelect(const std::vector<WeightType>& w) { Init(w.begin(), w.end()); }
/**
* Initialize with a weight given by a pair of iterators [\e a, \e b).
*
* @tparam InputIterator the type of the iterator.
* @param[in] a the beginning iterator.
* @param[in] b the ending iterator.
* @exception RandomErr if any of the weights are negative or if the total
* weight is not positive.
**********************************************************************/
template<typename InputIterator>
RandomSelect(InputIterator a, InputIterator b);
/**
* Clear the state (equivalent to having a single choice).
**********************************************************************/
void Init() throw()
{ _k = 0; _wsum = 0; _wmax = 0; _Q.clear(); _Y.clear(); }
/**
* Re-initialize with a weight vector \e w. Leave state unaltered in the
* case of an error.
*
* @tparam WeightType the type of the weights.
* @param[in] w the vector of weights.
**********************************************************************/
template<typename WeightType>
void Init(const std::vector<WeightType>& w) { Init(w.begin(), w.end()); }
/**
* Re-initialize with a weight given as a pair of iterators [\e a, \e b).
* Leave state unaltered in the case of an error.
*
* @tparam InputIterator the type of the iterator.
* @param[in] a the beginning iterator.
* @param[in] b the ending iterator.
**********************************************************************/
template<typename InputIterator>
void Init(InputIterator a, InputIterator b) {
RandomSelect<NumericType> t(a, b);
_Q.reserve(t._k);
_Y.reserve(t._k);
*this = t;
}
/**
* Return an index into the weight vector with probability proportional to
* the weight.
*
* @tparam Random the type of RandomCanonical generator.
* @param[in,out] r the RandomCanonical generator.
* @return the random index into the weight vector.
**********************************************************************/
template<class Random>
unsigned operator()(Random& r) const throw() {
if (_k <= 1)
return 0; // Special cases
const unsigned K = r.template Integer<unsigned>(_k);
// redundant casts to type NumericType to prevent warning from MS Project
return (std::numeric_limits<NumericType>::is_integer ?
r.template Prob<NumericType>(NumericType(_Q[K]),
NumericType(_wsum)) :
r.template Prob<NumericType>(NumericType(_Q[K]))) ?
K : _Y[K];
}
/**
* @return the sum of the weights.
**********************************************************************/
NumericType TotalWeight() const throw() { return _wsum; }
/**
* @return the maximum weight.
**********************************************************************/
NumericType MaxWeight() const throw() { return _wmax; }
/**
* @param[in] i the index in to the weight vector.
* @return the weight for sample \e i. Weight(i) / TotalWeight() gives the
* probability of sample \e i.
**********************************************************************/
NumericType Weight(unsigned i) const throw() {
if (i >= _k)
return NumericType(0);
else if (_k == 1)
return _wsum;
const NumericType n = std::numeric_limits<NumericType>::is_integer ?
_wsum : NumericType(1);
NumericType p = _Q[i];
for (unsigned j = _k; j;)
if (_Y[--j] == i)
p += n - _Q[j];
// If NumericType is integral, then p % _k == 0.
// assert(!std::numeric_limits<NumericType>::is_integer || p % _k == 0);
return (p / NumericType(_k)) * (_wsum / n);
}
/**
* @return the number of choices, i.e., the length of the weight vector.
**********************************************************************/
unsigned Choices() const throw() { return _k; }
private:
/**
* Size of weight vector
**********************************************************************/
unsigned _k;
/**
* Vector of cutoffs
**********************************************************************/
std::vector<NumericType> _Q;
/**
* Vector of aliases
**********************************************************************/
std::vector<unsigned> _Y;
/**
* The sum of the weights
**********************************************************************/
NumericType _wsum;
/**
* The maximum weight
**********************************************************************/
NumericType _wmax;
};
template<typename NumericType> template<typename InputIterator>
RandomSelect<NumericType>::RandomSelect(InputIterator a, InputIterator b) {
typedef typename std::iterator_traits<InputIterator>::value_type
WeightType;
// Disallow WeightType = real, NumericType = integer
STATIC_ASSERT(std::numeric_limits<WeightType>::is_integer ||
!std::numeric_limits<NumericType>::is_integer,
"RandomSelect: inconsistent WeightType and NumericType");
// If WeightType and NumericType are the same type, NumericType as precise
// as WeightType
STATIC_ASSERT(std::numeric_limits<WeightType>::is_integer !=
std::numeric_limits<NumericType>::is_integer ||
std::numeric_limits<NumericType>::digits >=
std::numeric_limits<WeightType>::digits,
"RandomSelect: NumericType insufficiently precise");
_wsum = 0;
_wmax = 0;
std::vector<NumericType> p;
for (InputIterator wptr = a; wptr != b; ++wptr) {
// Test *wptr < 0 without triggering compiler warning when *wptr =
// unsigned
if (!(*wptr > 0 || *wptr == 0))
// This also catches NaNs
throw RandomErr("RandomSelect: Illegal weight");
NumericType w = NumericType(*wptr);
if (w > (std::numeric_limits<NumericType>::max)() - _wsum)
throw RandomErr("RandomSelect: Overflow");
_wsum += w;
_wmax = w > _wmax ? w : _wmax;
p.push_back(w);
}
_k = unsigned(p.size());
if (_wsum <= 0)
throw RandomErr("RandomSelect: Zero total weight");
if (_k <= 1) {
// We treat k <= 1 as a special case in operator()
_Q.clear();
_Y.clear();
return;
}
if ((std::numeric_limits<NumericType>::max)()/NumericType(_k) <
NumericType(_wmax))
throw RandomErr("RandomSelect: Overflow");
std::vector<unsigned> j(_k);
_Q.resize(_k);
_Y.resize(_k);
// Pointers to the next empty low and high slots
unsigned u = 0;
unsigned v = _k - 1;
// Scale input and store in p and setup index array j. Note _wsum =
// mean(p). We could scale out _wsum here, but the following is exact when
// w[i] are low integers.
for (unsigned i = 0; i < _k; ++i) {
p[i] *= NumericType(_k);
j[p[i] > _wsum ? v-- : u++] = i;
}
// Pointers to the next low and high slots to use. Work towards the
// middle. This simplifies the loop exit test to u == v.
u = 0;
v = _k - 1;
// For integer NumericType, store the unnormalized probability in _Q and
// select using the exact Prob(_Q[k], _wsum). For real NumericType, store
// the normalized probability and select using Prob(_Q[k]). There will be
// a round off error in performing the division; but there is also the
// potential for round off errors in performing the arithmetic on p. There
// is therefore no point in simulating the division exactly using the
// slower Prob(real, real).
const NumericType n = std::numeric_limits<NumericType>::is_integer ?
NumericType(1) : _wsum;
while (true) {
// A loop invariant here is mean(p[j[u..v]]) == _wsum
_Q[j[u]] = p[j[u]] / n;
// If all arithmetic were exact this assignment could be:
// if (p[j[u]] < _wsum) _Y[j[u]] = j[v];
// But the following is safer:
_Y[j[u]] = j[p[j[u]] < _wsum ? v : u];
if (u == v) {
// The following assertion may fail because of roundoff errors
// assert( p[j[u]] == _wsum );
break;
}
// Update p, u, and v maintaining the loop invariant
p[j[v]] = p[j[v]] - (_wsum - p[j[u]]);
if (p[j[v]] > _wsum)
++u;
else
j[u] = j[v--];
}
return;
}
} // namespace RandomLib
#if defined(_MSC_VER)
# pragma warning (pop)
#endif
#endif // RANDOMLIB_RANDOMSELECT_HPP

View File

@ -1,137 +0,0 @@
/**
* \file RandomType.hpp
* \brief Class to hold bit-width and unsigned type
*
* This provides a simple class to couple a bit-width and an unsigned type
* capable of holding all the bits. In addition is offers static methods for
* I/O and checksumming.
*
* Copyright (c) Charles Karney (2006-2011) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* http://randomlib.sourceforge.net/
**********************************************************************/
#if !defined(RANDOMLIB_RANDOMTYPE_HPP)
#define RANDOMLIB_RANDOMTYPE_HPP 1
#include <limits>
#include <string>
#include <iostream>
namespace RandomLib {
/**
* \brief Class to hold bit-width and unsigned type
*
* This provides a simple class to couple a bit-width and an unsigned type
* capable of holding all the bits. In addition is offers static methods for
* I/O and checksumming.
*
* @tparam bits the number of significant bits.
* @tparam UIntType the C++ unsigned integer type capable of holding the bits.
**********************************************************************/
template<int bits, typename UIntType>
class RANDOMLIB_EXPORT RandomType {
public:
/**
* The unsigned C++ type
**********************************************************************/
typedef UIntType type;
/**
* The number of significant bits
**********************************************************************/
static const unsigned width = bits;
/**
* A mask for the significant bits.
**********************************************************************/
static const type mask =
~type(0) >> (std::numeric_limits<type>::digits - width);
/**
* The minimum representable value
**********************************************************************/
static const type min = type(0);
/**
* The maximum representable value
**********************************************************************/
static const type max = mask;
/**
* A combined masking and casting operation
*
* @tparam IntType the integer type of the \e x.
* @param[in] x the input integer.
* @return the masked and casted result.
**********************************************************************/
template<typename IntType> static type cast(IntType x) throw()
{ return type(x) & mask; }
/**
* Read a data value from a stream of 32-bit quantities (binary or text)
*
* @param[in,out] is the input stream.
* @param[in] bin true if the stream is binary.
* @param[out] x the data value read from the stream.
**********************************************************************/
static void Read32(std::istream& is, bool bin, type& x);
/**
* Write the data value to a stream of 32-bit quantities (binary or text)
*
* @param[in,out] os the output stream.
* @param[in] bin true if the stream is binary.
* @param[in,out] cnt controls the use of spaces and newlines for text
* output.
* @param[in] x the data value to be written to the stream.
*
* \e cnt should be zero on the first invocation of a series of writes.
* This function increments it by one on each call.
**********************************************************************/
static void Write32(std::ostream& os, bool bin, int& cnt, type x);
/**
* Accumulate a checksum of a integer into a 32-bit check. This implements
* a very simple checksum and is intended to avoid accidental corruption
* only.
*
* @param[in] n the number to be included in the checksum.
* @param[in,out] check the running checksum.
**********************************************************************/
static void CheckSum(type n, uint32_t& check) throw();
};
/**
* The standard unit for 32-bit quantities
**********************************************************************/
typedef RandomType<32, uint32_t> Random_u32;
/**
* The standard unit for 64-bit quantities
**********************************************************************/
typedef RandomType<64, uint64_t> Random_u64;
/**
* The integer type of constructing bitsets. This used to be unsigned long.
* C++11 has made this unsigned long long.
**********************************************************************/
#if defined(_MSC_VER) && _MSC_VER >= 1600
typedef unsigned long long bitset_uint_t;
#else
typedef unsigned long bitset_uint_t;
#endif
/// \cond SKIP
// Accumulate a checksum of a 32-bit quantity into check
template<>
inline void Random_u32::CheckSum(Random_u32::type n, Random_u32::type& check)
throw() {
// Circular shift left by one bit and add new word.
check = (check << 1 | (check >> 31 & Random_u32::type(1))) + n;
check &= Random_u32::mask;
}
// Accumulate a checksum of a 64-bit quantity into check
template<>
inline void Random_u64::CheckSum(Random_u64::type n, Random_u32::type& check)
throw() {
Random_u32::CheckSum(Random_u32::cast(n >> 32), check);
Random_u32::CheckSum(Random_u32::cast(n ), check);
}
/// \endcond
} // namespace RandomLib
#endif // RANDOMLIB_RANDOMTYPE_HPP

View File

@ -1,253 +0,0 @@
/**
* \file UniformInteger.hpp
* \brief Header for UniformInteger
*
* Partially sample a uniform integer distribution.
*
* Copyright (c) Charles Karney (2013) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* http://randomlib.sourceforge.net/
**********************************************************************/
#if !defined(RANDOMLIB_UNIFORMINTEGER_HPP)
#define RANDOMLIB_UNIFORMINTEGER_HPP 1
#include <limits>
namespace RandomLib {
/**
* \brief The partial uniform integer distribution.
*
* A class to sample in [0, \e m). For background, see:
* - D. E. Knuth and A. C. Yao, The Complexity of Nonuniform Random Number
* Generation, in "Algorithms and Complexity" (Academic Press, 1976),
* pp. 357--428.
* - J. Lumbroso, Optimal Discrete Uniform Generation from Coin Flips,
* and Applications, http://arxiv.org/abs/1304.1916 (2013)
* .
* Lumbroso's algorithm is a realization of the Knuth-Yao method for the case
* of uniform probabilities. This class generalizes the method to accept
* random digits in a base, \e b = 2<sup>\e bits</sup>. An important
* additional feature is that only sufficient random digits are drawn to
* narrow the allowed range to a power of b. Thus after
* <code>UniformInteger<int,1> u(r,5)</code>, \e u represents \verbatim
range prob
[0,4) 8/15
[0,2) 2/15
[2,4) 2/15
4 1/5 \endverbatim
* <code>u.Min()</code> and <code>u.Max()</code> give the extent of the
* closed range. The number of additional random digits needed to fix the
* value is given by <code>u.Entropy()</code>. The comparison operations may
* require additional digits to be drawn and so the range might be narrowed
* down. If you need a definite value then use <code>u(r)</code>.
*
* The DiscreteNormalAlt class uses UniformInteger to achieve an
* asymptotically ideal scaling wherein the number of random bits required
* per sample is constant + log<sub>2</sub>&sigma;. If Lumbroso's algorithm
* for sampling in [0,\e m) were used the log<sub>2</sub>&sigma; term would
* be multiplied by about 1.4.
*
* It is instructive to look at the Knuth-Yao discrete distribution
* generating (DDG) tree for the case \e m = 5 (the binary expansion of 1/5
* is 0.00110011...); Lumbroso's algorithm implements this tree.
* \image html ky-5.png "Knuth-Yao for \e m = 5"
*
* UniformInteger collapses all of the full subtrees above to their parent
* nodes to yield this tree where now some of the outcomes are ranges.
* \image html ky-5-collapse.png "Collapsed Knuth-Yao for \e m = 5"
*
* Averaging over many samples, the maximum number of digits required to
* construct a UniformInteger, i.e., invoking
* <code>UniformInteger(r,m)</code>, is (2\e b &minus; 1)/(\e b &minus; 1).
* (Note that this does not increase as \e m increases.) The maximum number
* of digits required to sample specific integers, i.e., invoking
* <code>UniformInteger(r,m)(r)</code>, is <i>b</i>/(\e b &minus; 1) +
* log<sub>\e b</sub>\e m. The worst cases are when \e m is slightly more
* than a power of \e b.
*
* The number of random bits required for sampling is shown as a function of
* the fractional part of log<sub>2</sub>\e m below. The red line shows what
* Lumbroso calls the "toll", the number of bits in excess of the entropy
* that are required for sampling.
* \image html
* uniform-bits.png "Random bits to sample in [0,\e m) for \e b = 2"
*
* @tparam IntType the type of the integer (must be signed).
* @tparam bits the number of bits in each digit used for sampling;
* the base for sampling is \e b = 2<sup>\e bits</sup>.
**********************************************************************/
template<typename IntType = int, int bits = 1> class UniformInteger {
public:
/**
* Constructor creating a partially sampled integer in [0, \e m)
*
* @param[in] r random object.
* @param[in] m constructed object represents an integer in [0, \e m).
* @param[in] flip if true, rearrange the ranges so that the widest ones
* are at near the upper end of [0, \e m) (default false).
*
* The samples enough random digits to obtain a uniform range whose size is
* a power of the base. The range can subsequently be narrowed by sampling
* additional digits.
**********************************************************************/
template<class Random>
UniformInteger(Random& r, IntType m, bool flip = false);
/**
* @return the minimum of the current range.
**********************************************************************/
IntType Min() const { return _a; }
/**
* @return the maximum of the current range.
**********************************************************************/
IntType Max() const { return _a + (IntType(1) << (_l * bits)) - 1; }
/**
* @return the entropy of the current range (in units of random digits).
*
* Max() + 1 - Min() = 2<sup>Entropy() * \e bits</sup>.
**********************************************************************/
IntType Entropy() const { return _l; }
/**
* Sample until the entropy vanishes, i.e., Min() = Max().
*
* @return the resulting integer sample.
**********************************************************************/
template<class Random> IntType operator()(Random& r)
{ while (_l) Refine(r); return _a; }
/**
* Negate the range, [Min(), Max()] &rarr; [&minus;Max(), &minus;Min()].
**********************************************************************/
void Negate() { _a = -Max(); }
/**
* Add a constant to the range
*
* @param[in] c the constant to be added.
*
* [Min(), Max()] &rarr; [Min() + \e c, Max() + \e c].
**********************************************************************/
void Add(IntType c) { _a += c; }
/**
* Compare with a fraction, *this &lt; <i>p</i>/<i>q</i>
*
* @tparam Random the type of the random generator.
* @param[in,out] r a random generator.
* @param[in] p the numerator of the fraction.
* @param[in] q the denominator of the fraction (require \e q &gt; 0).
* @return true if *this &lt; <i>p</i>/<i>q</i>.
**********************************************************************/
// test j < p/q (require q > 0)
template<class Random> bool LessThan(Random& r, IntType p, IntType q) {
for (;;) {
if ( (q * Max() < p)) return true;
if (!(q * Min() < p)) return false;
Refine(r);
}
}
/**
* Compare with a fraction, *this &le; <i>p</i>/<i>q</i>
*
* @tparam Random the type of the random generator.
* @param[in,out] r a random generator.
* @param[in] p the numerator of the fraction.
* @param[in] q the denominator of the fraction (require \e q &gt; 0).
* @return true if *this &le; <i>p</i>/<i>q</i>.
**********************************************************************/
template<class Random>
bool LessThanEqual(Random& r, IntType p, IntType q)
{ return LessThan(r, p + 1, q); }
/**
* Compare with a fraction, *this &gt; <i>p</i>/<i>q</i>
*
* @tparam Random the type of the random generator.
* @param[in,out] r a random generator.
* @param[in] p the numerator of the fraction.
* @param[in] q the denominator of the fraction (require \e q &gt; 0).
* @return true if *this &gt; <i>p</i>/<i>q</i>.
**********************************************************************/
template<class Random>
bool GreaterThan(Random& r, IntType p, IntType q)
{ return !LessThanEqual(r, p, q); }
/**
* Compare with a fraction, *this &ge; <i>p</i>/<i>q</i>
*
* @tparam Random the type of the random generator.
* @param[in,out] r a random generator.
* @param[in] p the numerator of the fraction.
* @param[in] q the denominator of the fraction (require \e q &gt; 0).
* @return true if *this &ge; <i>p</i>/<i>q</i>.
**********************************************************************/
template<class Random>
bool GreaterThanEqual(Random& r, IntType p, IntType q)
{ return !LessThan(r, p, q); }
/**
* Check that overflow will not happen.
*
* @param[in] mmax the largest \e m in the constructor.
* @param[in] qmax the largest \e q in LessThan().
* @return true if overflow will not happen.
*
* It is important that this check be carried out. If overflow occurs,
* incorrect results are obtained and the constructor may never terminate.
**********************************************************************/
static bool Check(IntType mmax, IntType qmax) {
return ( mmax - 1 <= ((std::numeric_limits<IntType>::max)() >> bits) &&
mmax - 1 <= (std::numeric_limits<IntType>::max)() / qmax );
}
private:
IntType _a, _l; // current range is _a + [0, 2^(bits*_l)).
template<class Random> static unsigned RandomDigit(Random& r) throw()
{ return unsigned(r.template Integer<bits>()); }
template<class Random> void Refine(Random& r) // only gets called if _l > 0.
{ _a += IntType(RandomDigit(r) << (bits * --_l)); }
};
template<typename IntType, int bits> template<class Random>
UniformInteger<IntType, bits>::UniformInteger(Random& r, IntType m, bool flip)
{
STATIC_ASSERT(std::numeric_limits<IntType>::is_integer,
"UniformInteger: invalid integer type IntType");
STATIC_ASSERT(std::numeric_limits<IntType>::is_signed,
"UniformInteger: IntType must be a signed type");
STATIC_ASSERT(bits > 0 && bits < std::numeric_limits<IntType>::digits &&
bits <= std::numeric_limits<unsigned>::digits,
"UniformInteger: bits out of range");
m = m < 1 ? 1 : m;
for (IntType v = 1, c = 0;;) {
_l = 0; _a = c;
for (IntType w = v, a = c, d = 1;;) {
// play out Lumbroso's algorithm without drawing random digits with w
// playing the role of v and c represented by the range [a, a + d).
// Return if both ends of range qualify as return values at the same
// time. Otherwise, fail and draw another random digit.
if (w >= m) {
IntType j = (a / m) * m; a -= j; w -= j;
if (w >= m) {
if (a + d <= m) { _a = !flip ? a : m - a - d; return; }
break;
}
}
w <<= bits; a <<= bits; d <<= bits; ++_l;
}
IntType j = (v / m) * m; v -= j; c -= j;
v <<= bits; c <<= bits; c += IntType(RandomDigit(r));
}
}
/**
* \relates UniformInteger
* Print a UniformInteger. Format is [\e min,\e max] unless the entropy is
* zero, in which case it's \e val.
**********************************************************************/
template<typename IntType, int bits>
std::ostream& operator<<(std::ostream& os,
const UniformInteger<IntType, bits>& u) {
if (u.Entropy())
os << "[" << u.Min() << "," << u.Max() << "]";
else
os << u.Min();
return os;
}
} // namespace RandomLib
#endif // RANDOMLIB_UNIFORMINTEGER_HPP

42
include/aes256.h Normal file
View File

@ -0,0 +1,42 @@
/*
* Byte-oriented AES-256 implementation.
* All lookup tables replaced with 'on the fly' calculations.
*
* Copyright (c) 2007-2009 Ilya O. Levin, http://www.literatecode.com
* Other contributors: Hal Finney
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef uint8_t
#define uint8_t unsigned char
#endif
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
uint8_t key[32];
uint8_t enckey[32];
uint8_t deckey[32];
} aes256_context;
void aes256_init(aes256_context *, uint8_t * /* key */);
void aes256_done(aes256_context *);
void aes256_encrypt_ecb(aes256_context *, uint8_t * /* plaintext */);
void aes256_decrypt_ecb(aes256_context *, uint8_t * /* cipertext */);
#ifdef __cplusplus
}
#endif

223
include/maxminddb.h Normal file
View File

@ -0,0 +1,223 @@
#ifdef __cplusplus
extern "C" {
#endif
#ifndef MAXMINDDB_H
#define MAXMINDDB_H
#ifndef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 200112L
#endif
#include <maxminddb_config.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/types.h>
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
/* libmaxminddb package version from configure */
#define PACKAGE_VERSION "1.1.4"
typedef ADDRESS_FAMILY sa_family_t;
#if defined(_MSC_VER)
/* MSVC doesn't define signed size_t, copy it from configure */
#define ssize_t int
/* MSVC doesn't support restricted pointers */
#define restrict
#endif
#else
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#endif
#define MMDB_DATA_TYPE_EXTENDED (0)
#define MMDB_DATA_TYPE_POINTER (1)
#define MMDB_DATA_TYPE_UTF8_STRING (2)
#define MMDB_DATA_TYPE_DOUBLE (3)
#define MMDB_DATA_TYPE_BYTES (4)
#define MMDB_DATA_TYPE_UINT16 (5)
#define MMDB_DATA_TYPE_UINT32 (6)
#define MMDB_DATA_TYPE_MAP (7)
#define MMDB_DATA_TYPE_INT32 (8)
#define MMDB_DATA_TYPE_UINT64 (9)
#define MMDB_DATA_TYPE_UINT128 (10)
#define MMDB_DATA_TYPE_ARRAY (11)
#define MMDB_DATA_TYPE_CONTAINER (12)
#define MMDB_DATA_TYPE_END_MARKER (13)
#define MMDB_DATA_TYPE_BOOLEAN (14)
#define MMDB_DATA_TYPE_FLOAT (15)
/* flags for open */
#define MMDB_MODE_MMAP (1)
#define MMDB_MODE_MASK (7)
/* error codes */
#define MMDB_SUCCESS (0)
#define MMDB_FILE_OPEN_ERROR (1)
#define MMDB_CORRUPT_SEARCH_TREE_ERROR (2)
#define MMDB_INVALID_METADATA_ERROR (3)
#define MMDB_IO_ERROR (4)
#define MMDB_OUT_OF_MEMORY_ERROR (5)
#define MMDB_UNKNOWN_DATABASE_FORMAT_ERROR (6)
#define MMDB_INVALID_DATA_ERROR (7)
#define MMDB_INVALID_LOOKUP_PATH_ERROR (8)
#define MMDB_LOOKUP_PATH_DOES_NOT_MATCH_DATA_ERROR (9)
#define MMDB_INVALID_NODE_NUMBER_ERROR (10)
#define MMDB_IPV6_LOOKUP_IN_IPV4_DATABASE_ERROR (11)
#if !(MMDB_UINT128_IS_BYTE_ARRAY)
#if MMDB_UINT128_USING_MODE
typedef unsigned int mmdb_uint128_t __attribute__ ((__mode__(TI)));
#else
typedef unsigned __int128 mmdb_uint128_t;
#endif
#endif
/* This is a pointer into the data section for a given IP address lookup */
typedef struct MMDB_entry_s {
struct MMDB_s *mmdb;
uint32_t offset;
} MMDB_entry_s;
typedef struct MMDB_lookup_result_s {
bool found_entry;
MMDB_entry_s entry;
uint16_t netmask;
} MMDB_lookup_result_s;
typedef struct MMDB_entry_data_s {
bool has_data;
union {
uint32_t pointer;
const char *utf8_string;
double double_value;
const uint8_t *bytes;
uint16_t uint16;
uint32_t uint32;
int32_t int32;
uint64_t uint64;
#if MMDB_UINT128_IS_BYTE_ARRAY
uint8_t uint128[16];
#else
mmdb_uint128_t uint128;
#endif
bool boolean;
float float_value;
};
/* This is a 0 if a given entry cannot be found. This can only happen
* when a call to MMDB_(v)get_value() asks for hash keys or array
* indices that don't exist. */
uint32_t offset;
/* This is the next entry in the data section, but it's really only
* relevant for entries that part of a larger map or array
* struct. There's no good reason for an end user to look at this
* directly. */
uint32_t offset_to_next;
/* This is only valid for strings, utf8_strings or binary data */
uint32_t data_size;
/* This is an MMDB_DATA_TYPE_* constant */
uint32_t type;
} MMDB_entry_data_s;
/* This is the return type when someone asks for all the entry data in a map or array */
typedef struct MMDB_entry_data_list_s {
MMDB_entry_data_s entry_data;
struct MMDB_entry_data_list_s *next;
} MMDB_entry_data_list_s;
typedef struct MMDB_description_s {
const char *language;
const char *description;
} MMDB_description_s;
typedef struct MMDB_metadata_s {
uint32_t node_count;
uint16_t record_size;
uint16_t ip_version;
const char *database_type;
struct {
size_t count;
const char **names;
} languages;
uint16_t binary_format_major_version;
uint16_t binary_format_minor_version;
uint64_t build_epoch;
struct {
size_t count;
MMDB_description_s **descriptions;
} description;
} MMDB_metadata_s;
typedef struct MMDB_ipv4_start_node_s {
uint16_t netmask;
uint32_t node_value;
} MMDB_ipv4_start_node_s;
typedef struct MMDB_s {
uint32_t flags;
const char *filename;
ssize_t file_size;
const uint8_t *file_content;
const uint8_t *data_section;
uint32_t data_section_size;
const uint8_t *metadata_section;
uint32_t metadata_section_size;
uint16_t full_record_byte_size;
uint16_t depth;
MMDB_ipv4_start_node_s ipv4_start_node;
MMDB_metadata_s metadata;
} MMDB_s;
typedef struct MMDB_search_node_s {
uint64_t left_record;
uint64_t right_record;
} MMDB_search_node_s;
/* *INDENT-OFF* */
/* --prototypes automatically generated by dev-bin/regen-prototypes.pl - don't remove this comment */
extern int MMDB_open(const char *const filename, uint32_t flags, MMDB_s *const mmdb);
extern MMDB_lookup_result_s MMDB_lookup_string(MMDB_s *const mmdb,
const char *const ipstr,
int *const gai_error,
int *const mmdb_error);
extern MMDB_lookup_result_s MMDB_lookup_sockaddr(
MMDB_s *const mmdb,
const struct sockaddr *const sockaddr,
int *const mmdb_error);
extern int MMDB_read_node(MMDB_s *const mmdb, uint32_t node_number,
MMDB_search_node_s *const node);
extern int MMDB_get_value(MMDB_entry_s *const start,
MMDB_entry_data_s *const entry_data,
...);
extern int MMDB_vget_value(MMDB_entry_s *const start,
MMDB_entry_data_s *const entry_data,
va_list va_path);
extern int MMDB_aget_value(MMDB_entry_s *const start,
MMDB_entry_data_s *const entry_data,
const char *const *const path);
extern int MMDB_get_metadata_as_entry_data_list(
MMDB_s *const mmdb, MMDB_entry_data_list_s **const entry_data_list);
extern int MMDB_get_entry_data_list(
MMDB_entry_s *start, MMDB_entry_data_list_s **const entry_data_list);
extern void MMDB_free_entry_data_list(MMDB_entry_data_list_s *const entry_data_list);
extern void MMDB_close(MMDB_s *const mmdb);
extern const char *MMDB_lib_version(void);
extern int MMDB_dump_entry_data_list(FILE *const stream,
MMDB_entry_data_list_s *const entry_data_list,
int indent);
extern const char *MMDB_strerror(int error_code);
/* --prototypes end - don't remove this comment-- */
/* *INDENT-ON* */
#endif /* MAXMINDDB_H */
#ifdef __cplusplus
}
#endif

View File

@ -33,7 +33,7 @@ Int32 Document::Cmp(const Document & o) const
{
if (m_Doc == o.m_Doc)
return 0;
else if (this > &o)
else if (m_Doc.m_Ptr > o.m_Doc.m_Ptr)
return 1;
else
return -1;

View File

@ -109,14 +109,6 @@ public:
return m_Doc;
}
/* --------------------------------------------------------------------------------------------
* See whether any data has been loaded into this document.
*/
bool IsEmpty() const
{
return m_Doc->IsEmpty();
}
/* --------------------------------------------------------------------------------------------
* Return the number of active references to this document instance.
*/
@ -125,6 +117,14 @@ public:
return m_Doc.Count();
}
/* --------------------------------------------------------------------------------------------
* See whether any data has been loaded into this document.
*/
bool IsEmpty() const
{
return m_Doc->IsEmpty();
}
/* --------------------------------------------------------------------------------------------
* Deallocate all memory stored by this document.
*/

View File

@ -18,7 +18,7 @@ Int32 Entries::Cmp(const Entries & o) const
{
if (m_Elem == o.m_Elem)
return 0;
else if (this > &o)
else if (m_List.size() > o.m_List.size())
return 1;
else
return -1;

120
modules/mmdb/Common.cpp Normal file
View File

@ -0,0 +1,120 @@
// ------------------------------------------------------------------------------------------------
#include "Common.hpp"
#include "Module.hpp"
// ------------------------------------------------------------------------------------------------
#include <cfloat>
#include <climits>
#include <cstdlib>
#include <cstdarg>
// ------------------------------------------------------------------------------------------------
#include <sqrat.h>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
static SQChar g_Buffer[4096]; // Common buffer to reduce memory allocations.
// ------------------------------------------------------------------------------------------------
SStr GetTempBuff()
{
return g_Buffer;
}
// ------------------------------------------------------------------------------------------------
Uint32 GetTempBuffSize()
{
return sizeof(g_Buffer);
}
// ------------------------------------------------------------------------------------------------
void SqThrowF(CSStr str, ...)
{
// Initialize the argument list
va_list args;
va_start (args, str);
// Write the requested contents
if (snprintf(g_Buffer, sizeof(g_Buffer), str, args) < 0)
strcpy(g_Buffer, "Unknown error has occurred");
// Release the argument list
va_end(args);
// Throw the exception with the resulted message
throw Sqrat::Exception(g_Buffer);
}
// ------------------------------------------------------------------------------------------------
CSStr FmtStr(CSStr str, ...)
{
// Initialize the argument list
va_list args;
va_start (args, str);
// Write the requested contents
if (snprintf(g_Buffer, sizeof(g_Buffer), str, args) < 0)
g_Buffer[0] = 0; /* make sure the string is terminated */
// Release the argument list
va_end(args);
// Return the data from the buffer
return g_Buffer;
}
// ------------------------------------------------------------------------------------------------
StackGuard::StackGuard(HSQUIRRELVM vm)
: m_Top(sq_gettop(vm)), m_VM(vm)
{
/* ... */
}
// ------------------------------------------------------------------------------------------------
StackGuard::~StackGuard()
{
sq_pop(m_VM, sq_gettop(m_VM) - m_Top);
}
// ------------------------------------------------------------------------------------------------
DbRef::Pointer DbRef::Create()
{
return reinterpret_cast< Pointer >(malloc(sizeof(Type)));
}
// ------------------------------------------------------------------------------------------------
void DbRef::Destroy(Pointer db)
{
if (db)
free(db);
}
// ------------------------------------------------------------------------------------------------
const char NumLimit< char >::Min = CHAR_MIN;
const signed char NumLimit< signed char >::Min = SCHAR_MIN;
const unsigned char NumLimit< unsigned char >::Min = 0;
const signed short NumLimit< signed short >::Min = SHRT_MIN;
const unsigned short NumLimit< unsigned short >::Min = 0;
const signed int NumLimit< signed int >::Min = INT_MIN;
const unsigned int NumLimit< unsigned int >::Min = 0;
const signed long NumLimit< signed long >::Min = LONG_MIN;
const unsigned long NumLimit< unsigned long >::Min = 0;
const signed long long NumLimit< signed long long >::Min = LLONG_MIN;
const unsigned long long NumLimit< unsigned long long >::Min = 0;
const float NumLimit< float >::Min = FLT_MIN;
const double NumLimit< double >::Min = DBL_MIN;
const long double NumLimit< long double >::Min = LDBL_MIN;
// ------------------------------------------------------------------------------------------------
const char NumLimit< char >::Max = CHAR_MAX;
const signed char NumLimit< signed char >::Max = SCHAR_MAX;
const unsigned char NumLimit< unsigned char >::Max = UCHAR_MAX;
const signed short NumLimit< signed short >::Max = SHRT_MAX;
const unsigned short NumLimit< unsigned short >::Max = USHRT_MAX;
const signed int NumLimit< signed int >::Max = INT_MAX;
const unsigned int NumLimit< unsigned int >::Max = UINT_MAX;
const signed long NumLimit< signed long >::Max = LONG_MAX;
const unsigned long NumLimit< unsigned long >::Max = ULONG_MAX;
const signed long long NumLimit< signed long long >::Max = LLONG_MAX;
const unsigned long long NumLimit< unsigned long long >::Max = ULLONG_MAX;
const float NumLimit< float >::Max = FLT_MAX;
const double NumLimit< double >::Max = DBL_MAX;
const long double NumLimit< long double >::Max = LDBL_MAX;
} // Namespace:: SqMod

453
modules/mmdb/Common.hpp Normal file
View File

@ -0,0 +1,453 @@
#ifndef _SQMMDB_COMMON_HPP_
#define _SQMMDB_COMMON_HPP_
// ------------------------------------------------------------------------------------------------
#include "ModBase.hpp"
// ------------------------------------------------------------------------------------------------
#include <cassert>
#include <cmath>
// ------------------------------------------------------------------------------------------------
#include <maxminddb.h>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* SOFTWARE INFORMATION
*/
#define SQMMDB_NAME "Squirrel MaxmindDB Module"
#define SQMMDB_AUTHOR "Sandu Liviu Catalin (S.L.C)"
#define SQMMDB_COPYRIGHT "Copyright (C) 2016 Sandu Liviu Catalin"
#define SQMMDB_HOST_NAME "SqModMMDBHost"
#define SQMMDB_VERSION 001
#define SQMMDB_VERSION_STR "0.0.1"
#define SQMMDB_VERSION_MAJOR 0
#define SQMMDB_VERSION_MINOR 0
#define SQMMDB_VERSION_PATCH 1
/* ------------------------------------------------------------------------------------------------
* Forward declarations.
*/
class Database;
class SockAddr;
class EntryDataList;
class LookupResult;
/* ------------------------------------------------------------------------------------------------
* Retrieve the temporary buffer.
*/
SStr GetTempBuff();
/* ------------------------------------------------------------------------------------------------
* Retrieve the size of the temporary buffer.
*/
Uint32 GetTempBuffSize();
/* ------------------------------------------------------------------------------------------------
* Throw a formatted exception.
*/
void SqThrowF(CSStr str, ...);
/* ------------------------------------------------------------------------------------------------
* Generate a formatted string.
*/
CSStr FmtStr(CSStr str, ...);
/* ------------------------------------------------------------------------------------------------
* Implements RAII to restore the VM stack to it's initial size on function exit.
*/
struct StackGuard
{
/* --------------------------------------------------------------------------------------------
* Base constructor.
*/
StackGuard(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Destructor.
*/
~StackGuard();
private:
/* --------------------------------------------------------------------------------------------
* Copy constructor.
*/
StackGuard(const StackGuard &);
/* --------------------------------------------------------------------------------------------
* Move constructor.
*/
StackGuard(StackGuard &&);
/* --------------------------------------------------------------------------------------------
* Copy assignment operator.
*/
StackGuard & operator = (const StackGuard &);
/* --------------------------------------------------------------------------------------------
* Move assignment operator.
*/
StackGuard & operator = (StackGuard &&);
private:
// --------------------------------------------------------------------------------------------
Int32 m_Top; /* The top of the stack when this instance was created. */
HSQUIRRELVM m_VM; /* The VM where the stack should be restored. */
};
/* ------------------------------------------------------------------------------------------------
* Manages a reference counted INI document instance.
*/
class DbRef
{
// --------------------------------------------------------------------------------------------
friend class Database;
public:
// --------------------------------------------------------------------------------------------
typedef MMDB_s Type; // The managed type.
// --------------------------------------------------------------------------------------------
typedef Type* Pointer; // Pointer to the managed type.
typedef const Type* ConstPtr; // Constant pointer to the managed type.
// --------------------------------------------------------------------------------------------
typedef Type& Reference; // Reference to the managed type.
typedef const Type& ConstRef; // Constant reference to the managed type.
// --------------------------------------------------------------------------------------------
typedef unsigned int Counter; // Reference counter type.
private:
// --------------------------------------------------------------------------------------------
Pointer m_Ptr; // The document reader, writer and manager instance.
Counter* m_Ref; // Reference count to the managed instance.
/* --------------------------------------------------------------------------------------------
* Creates a database structure.
*/
static Pointer Create();
/* --------------------------------------------------------------------------------------------
* Destroyes the specified database structure.
*/
static void Destroy(Pointer db);
/* --------------------------------------------------------------------------------------------
* Grab a strong reference to a document instance.
*/
void Grab()
{
if (m_Ptr)
++(*m_Ref);
}
/* --------------------------------------------------------------------------------------------
* Drop a strong reference to a document instance.
*/
void Drop()
{
if (m_Ptr && --(*m_Ref) == 0)
{
MMDB_close(m_Ptr);
Destroy(m_Ptr);
delete m_Ref;
m_Ptr = NULL;
m_Ref = NULL;
}
}
/* --------------------------------------------------------------------------------------------
* Base constructor.
*/
DbRef(bool make)
: m_Ptr(make ? Create() : NULL), m_Ref(m_Ptr ? new Counter(1) : NULL)
{
/* ... */
}
public:
/* --------------------------------------------------------------------------------------------
* Default constructor (null).
*/
DbRef()
: m_Ptr(NULL), m_Ref(NULL)
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Copy constructor.
*/
DbRef(const DbRef & o)
: m_Ptr(o.m_Ptr), m_Ref(o.m_Ref)
{
Grab();
}
/* --------------------------------------------------------------------------------------------
* Move constructor.
*/
DbRef(DbRef && o)
: m_Ptr(o.m_Ptr), m_Ref(o.m_Ref)
{
o.m_Ptr = NULL;
o.m_Ref = NULL;
}
/* --------------------------------------------------------------------------------------------
* Destructor.
*/
~DbRef()
{
Drop();
}
/* --------------------------------------------------------------------------------------------
* Copy assignment operator.
*/
DbRef & operator = (const DbRef & o)
{
if (m_Ptr != o.m_Ptr)
{
Drop();
m_Ptr = o.m_Ptr;
m_Ref = o.m_Ref;
Grab();
}
return *this;
}
/* --------------------------------------------------------------------------------------------
* Move assignment operator.
*/
DbRef & operator = (DbRef && o)
{
if (m_Ptr != o.m_Ptr)
{
m_Ptr = o.m_Ptr;
m_Ref = o.m_Ref;
o.m_Ptr = NULL;
o.m_Ref = NULL;
}
return *this;
}
/* --------------------------------------------------------------------------------------------
* Perform an equality comparison between two document instances.
*/
bool operator == (const DbRef & o) const
{
return (m_Ptr == o.m_Ptr);
}
/* --------------------------------------------------------------------------------------------
* Perform an inequality comparison between two document instances.
*/
bool operator != (const DbRef & o) const
{
return (m_Ptr != o.m_Ptr);
}
/* --------------------------------------------------------------------------------------------
* Implicit conversion to boolean for use in boolean operations.
*/
operator bool () const
{
return m_Ptr;
}
/* --------------------------------------------------------------------------------------------
* Implicit conversion to the managed instance pointer.
*/
operator Pointer ()
{
return m_Ptr;
}
/* --------------------------------------------------------------------------------------------
* Implicit conversion to the managed instance pointer.
*/
operator ConstPtr () const
{
return m_Ptr;
}
/* --------------------------------------------------------------------------------------------
* Implicit conversion to the managed instance reference.
*/
operator Reference ()
{
assert(m_Ptr);
return *m_Ptr;
}
/* --------------------------------------------------------------------------------------------
* Implicit conversion to the managed instance reference.
*/
operator ConstRef () const
{
assert(m_Ptr);
return *m_Ptr;
}
/* --------------------------------------------------------------------------------------------
* Member operator for dereferencing the managed pointer.
*/
Pointer operator -> () const
{
assert(m_Ptr);
return m_Ptr;
}
/* --------------------------------------------------------------------------------------------
* Indirection operator for obtaining a reference of the managed pointer.
*/
Reference operator * () const
{
assert(m_Ptr);
return *m_Ptr;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the raw handle structure pointer.
*/
Pointer DbPtr()
{
return m_Ptr;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the raw handle structure pointer.
*/
Pointer DbPtr() const
{
return m_Ptr;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the number of active references to the managed instance.
*/
Counter Count() const
{
return (m_Ptr && m_Ref) ? (*m_Ref) : 0;
}
};
// ------------------------------------------------------------------------------------------------
template < typename T > struct NumLimit;
// ------------------------------------------------------------------------------------------------
template <> struct NumLimit< char > { static const char Min, Max; };
template <> struct NumLimit< signed char > { static const signed char Min, Max; };
template <> struct NumLimit< unsigned char > { static const unsigned char Min, Max; };
template <> struct NumLimit< signed short > { static const signed short Min, Max; };
template <> struct NumLimit< unsigned short > { static const unsigned short Min, Max; };
template <> struct NumLimit< signed int > { static const signed int Min, Max; };
template <> struct NumLimit< unsigned int > { static const unsigned int Min, Max; };
template <> struct NumLimit< signed long > { static const signed long Min, Max; };
template <> struct NumLimit< unsigned long > { static const unsigned long Min, Max; };
template <> struct NumLimit< signed long long > { static const signed long long Min, Max; };
template <> struct NumLimit< unsigned long long > { static const unsigned long long Min, Max; };
template <> struct NumLimit< float > { static const float Min, Max; };
template <> struct NumLimit< double > { static const double Min, Max; };
template <> struct NumLimit< long double > { static const long double Min, Max; };
// ------------------------------------------------------------------------------------------------
template< typename T > inline bool EpsEq(const T a, const T b)
{
return abs(a - b) <= 0;
}
template <> inline bool EpsEq(const Float32 a, const Float32 b)
{
return fabs(a - b) <= 0.000001f;
}
template <> inline bool EpsEq(const Float64 a, const Float64 b)
{
return fabs(a - b) <= 0.000000001d;
}
// ------------------------------------------------------------------------------------------------
template< typename T > inline bool EpsLt(const T a, const T b)
{
return !EpsEq(a, b) && (a < b);
}
template <> inline bool EpsLt(const Float32 a, const Float32 b)
{
return !EpsEq(a, b) && (a - b) < 0.000001f;
}
template <> inline bool EpsLt(const Float64 a, const Float64 b)
{
return !EpsEq(a, b) && (a - b) < 0.000000001d;
}
// ------------------------------------------------------------------------------------------------
template< typename T > inline bool EpsGt(const T a, const T b)
{
return !EpsEq(a, b) && (a > b);
}
template <> inline bool EpsGt(const Float32 a, const Float32 b)
{
return !EpsEq(a, b) && (a - b) > 0.000001f;
}
template <> inline bool EpsGt(const Float64 a, const Float64 b)
{
return !EpsEq(a, b) && (a - b) > 0.000000001d;
}
// ------------------------------------------------------------------------------------------------
template< typename T > inline bool EpsLtEq(const T a, const T b)
{
return !EpsEq(a, b) || (a < b);
}
template <> inline bool EpsLtEq(const Float32 a, const Float32 b)
{
return !EpsEq(a, b) || (a - b) < 0.000001f;
}
template <> inline bool EpsLtEq(const Float64 a, const Float64 b)
{
return !EpsEq(a, b) || (a - b) < 0.000000001d;
}
// ------------------------------------------------------------------------------------------------
template< typename T > inline bool EpsGtEq(const T a, const T b)
{
return !EpsEq(a, b) || (a > b);
}
template <> inline bool EpsGtEq(const Float32 a, const Float32 b)
{
return !EpsEq(a, b) || (a - b) > 0.000001f;
}
template <> inline bool EpsGtEq(const Float64 a, const Float64 b)
{
return !EpsEq(a, b) || (a - b) > 0.000000001d;
}
// ------------------------------------------------------------------------------------------------
template< typename T > inline T Clamp(T val, T min, T max)
{
return val < min ? min : (val > max ? max : val);
}
} // Namespace:: SqMod
#endif // _SQMMDB_COMMON_HPP_

116
modules/mmdb/Database.cpp Normal file
View File

@ -0,0 +1,116 @@
// ------------------------------------------------------------------------------------------------
#include "Database.hpp"
#include "SockAddr.hpp"
#include "LookupResult.hpp"
#include "Module.hpp"
// ------------------------------------------------------------------------------------------------
#include <sqrat.h>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
SQInteger Database::Typename(HSQUIRRELVM vm)
{
static const SQChar name[] = _SC("SqMMDBDatabase");
sq_pushstring(vm, name, sizeof(name));
return 1;
}
// ------------------------------------------------------------------------------------------------
void Database::Validate() const
{
// Is the document handle valid?
if (!m_Db)
SqThrowF("Invalid Maxmind database reference");
}
// ------------------------------------------------------------------------------------------------
Int32 Database::Cmp(const Database & o) const
{
if (m_Db == o.m_Db)
return 0;
else if (m_Db.m_Ptr > o.m_Db.m_Ptr)
return 1;
else
return -1;
}
// ------------------------------------------------------------------------------------------------
void Database::Open(CSStr filepath)
{
Open(filepath, 0);
}
// ------------------------------------------------------------------------------------------------
void Database::Open(CSStr filepath, Uint32 flags)
{
// Is there a database handle available?
if (!m_Db)
m_Db = DbRef(true); // Create a database handle
// Check if the database handle could be allocated one more time
if (!m_Db)
SqThrowF("Unable to create a Maxmind database reference");
// Are there any other references?
else if (m_Db.Count() > 1)
// To load new values now, would mean to cause undefined behavior in existing references
SqThrowF("Loading is disabled while database is referenced");
// Validate the specified file path
else if (!filepath || strlen(filepath) <= 0)
SqThrowF("Invalid database file path");
// Let's attempt to open the specified database
const Int32 status = MMDB_open(filepath, flags, m_Db.m_Ptr);
// Validate the result of the operation
if (status != MMDB_SUCCESS)
{
// Release the database reference
m_Db.Drop();
// Now it's safe to throw the error
SqThrowF("Unable to open the specified database [%s]", MMDB_strerror(status));
}
}
// ------------------------------------------------------------------------------------------------
LookupResult Database::LookupString(CSStr addr)
{
// Validate the database handle
Validate();
// Validate the specified string
if (!addr || strlen(addr) <= 0)
SqThrowF("Invalid address string");
// Dummy variables to obtain the status codes
int gai_error, mmdb_error;
// Attempt to perform the actual lookup
MMDB_lookup_result_s result = MMDB_lookup_string(m_Db, addr, &gai_error, &mmdb_error);
// Validate the result of the getaddrinfo() function call
if (gai_error != 0)
SqThrowF("Unable to resolve address (%s) because [%s]", addr, gai_strerror(gai_error));
// Validate the lookup status code
else if (mmdb_error != MMDB_SUCCESS)
SqThrowF("Unable to lookup address (%s) because [%s]", addr, MMDB_strerror(mmdb_error));
// Now it's safe to return the lookup result
return LookupResult(m_Db, result);
}
// ------------------------------------------------------------------------------------------------
LookupResult Database::LookupSockAddr(SockAddr & addr)
{
// Validate the database handle
Validate();
// Validate the specified socket address
if (!addr.IsValid())
SqThrowF("Invalid address instance");
// Dummy variable to obtain the status codes
int mmdb_error;
// Attempt to perform the actual lookup
MMDB_lookup_result_s result = MMDB_lookup_sockaddr(m_Db, addr.GetHandle()->ai_addr, &mmdb_error);
// Validate the lookup status code
if (mmdb_error != MMDB_SUCCESS)
SqThrowF("Unable to lookup address (%s) because [%s]",
addr.GetAddress(), MMDB_strerror(mmdb_error));
// Now it's safe to return the lookup result
return LookupResult(m_Db, result);
}
} // Namespace:: SqMod

132
modules/mmdb/Database.hpp Normal file
View File

@ -0,0 +1,132 @@
#ifndef _SQMMDB_DATABASE_HPP_
#define _SQMMDB_DATABASE_HPP_
// ------------------------------------------------------------------------------------------------
#include "Common.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Class that can read/write and alter the contents of INI files.
*/
class Database
{
protected:
/* --------------------------------------------------------------------------------------------
* Copy constructor. (disabled)
*/
Database(const Database &);
/* --------------------------------------------------------------------------------------------
* Copy assignment operator. (disabled)
*/
Database & operator = (const Database &);
/* --------------------------------------------------------------------------------------------
* Validate the document reference and throw an error if invalid.
*/
void Validate() const;
private:
// ---------------------------------------------------------------------------------------------
DbRef m_Db; /* The main INI document instance. */
public:
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
Database()
: m_Db()
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Base constructor.
*/
Database(CSStr filepath)
: m_Db()
{
Open(filepath, 0);
}
/* --------------------------------------------------------------------------------------------
* Base constructor.
*/
Database(CSStr filepath, Uint32 flags)
: m_Db()
{
Open(filepath, flags);
}
/* --------------------------------------------------------------------------------------------
* Destructor.
*/
~Database()
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Used by the script engine to compare two instances of this type.
*/
Int32 Cmp(const Database & o) const;
/* --------------------------------------------------------------------------------------------
* Used by the script engine to convert an instance of this type to a string.
*/
CSStr ToString() const
{
return _SC("");
}
/* --------------------------------------------------------------------------------------------
* Used by the script engine to retrieve the name from instances of this type.
*/
static SQInteger Typename(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* See whether this instance references a valid INI document.
*/
bool IsValid() const
{
return m_Db;
}
/* --------------------------------------------------------------------------------------------
* Return the number of active references to this document instance.
*/
Uint32 GetRefCount() const
{
return m_Db.Count();
}
/* --------------------------------------------------------------------------------------------
* Attempt to open the specified database.
*/
void Open(CSStr filepath);
/* --------------------------------------------------------------------------------------------
* Attempt to open the specified database.
*/
void Open(CSStr filepath, Uint32 addr);
/* --------------------------------------------------------------------------------------------
* Look up an IP address that is passed in as a null-terminated string.
*/
LookupResult LookupString(CSStr addr);
/* --------------------------------------------------------------------------------------------
* Looks up an IP address that has already been resolved by getaddrinfo().
*/
LookupResult LookupSockAddr(SockAddr & sockaddr);
};
} // Namespace:: SqMod
#endif // _SQMMDB_DATABASE_HPP_

View File

@ -0,0 +1,382 @@
// ------------------------------------------------------------------------------------------------
#include "EntryDataList.hpp"
#include "Module.hpp"
// ------------------------------------------------------------------------------------------------
#include <cstdio>
#include <cstdlib>
// ------------------------------------------------------------------------------------------------
#include <sqrat.h>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
SQInteger EntryDataList::Typename(HSQUIRRELVM vm)
{
static const SQChar name[] = _SC("SqMMDBEntryDataList");
sq_pushstring(vm, name, sizeof(name));
return 1;
}
// ------------------------------------------------------------------------------------------------
void EntryDataList::Validate() const
{
// Is the document handle valid?
if (!m_Db)
SqThrowF("Invalid Maxmind database reference");
// Do we have a valid list?
else if (!m_List)
SqThrowF("Invalid entry data list");
}
// ------------------------------------------------------------------------------------------------
void EntryDataList::ValidateElem() const
{
// Is the document handle valid?
if (!m_Db)
SqThrowF("Invalid Maxmind database reference");
// Do we have a valid list?
else if (!m_List)
SqThrowF("Invalid entry data list");
// Do we have a valid element?
else if (!m_Elem)
SqThrowF("Invalid entry data element");
}
// ------------------------------------------------------------------------------------------------
void EntryDataList::ValidateData() const
{
// Is the document handle valid?
if (!m_Db)
SqThrowF("Invalid Maxmind database reference");
// Do we have a valid list?
else if (!m_List)
SqThrowF("Invalid entry data list");
// Do we have a valid element?
else if (!m_Elem)
SqThrowF("Invalid entry data element");
// Do we have some valid data?
else if (!m_Elem->entry_data.has_data)
SqThrowF("Entry data element has no data");
}
// ------------------------------------------------------------------------------------------------
CSStr EntryDataList::AsTypeStr(Uint32 id)
{
switch (id)
{
case MMDB_DATA_TYPE_EXTENDED: return _SC("extended");
case MMDB_DATA_TYPE_POINTER: return _SC("pointer");
case MMDB_DATA_TYPE_UTF8_STRING: return _SC("string");
case MMDB_DATA_TYPE_DOUBLE: return _SC("double");
case MMDB_DATA_TYPE_BYTES: return _SC("bytes");
case MMDB_DATA_TYPE_UINT16: return _SC("uint16");
case MMDB_DATA_TYPE_UINT32: return _SC("uint32");
case MMDB_DATA_TYPE_MAP: return _SC("map");
case MMDB_DATA_TYPE_INT32: return _SC("int32");
case MMDB_DATA_TYPE_UINT64: return _SC("uint64");
case MMDB_DATA_TYPE_UINT128: return _SC("uint128");
case MMDB_DATA_TYPE_ARRAY: return _SC("array");
case MMDB_DATA_TYPE_CONTAINER: return _SC("container");
case MMDB_DATA_TYPE_END_MARKER: return _SC("endmarker");
case MMDB_DATA_TYPE_BOOLEAN: return _SC("boolean");
case MMDB_DATA_TYPE_FLOAT: return _SC("float");
default: return _SC("unknonw");
}
}
// ------------------------------------------------------------------------------------------------
EntryDataList::~EntryDataList()
{
// Do we have to free any list?
if (m_List)
MMDB_free_entry_data_list(m_List);
}
// ------------------------------------------------------------------------------------------------
Int32 EntryDataList::Cmp(const EntryDataList & o) const
{
if (m_List == o.m_List)
return 0;
else if (m_List > o.m_List)
return 1;
else
return -1;
}
// ------------------------------------------------------------------------------------------------
Uint32 EntryDataList::GetCount() const
{
// Do we even have a list?
if (!m_List)
return 0;
// Get the start of the list
Pointer elem = m_List;
// Prepare a counter
Uint32 count = 1;
// Loop through list elements
while ((elem = elem->next)) ++count;
// Return the counter
return count;
}
// ------------------------------------------------------------------------------------------------
bool EntryDataList::Next()
{
// Validate the database and list handle
Validate();
// Do we have a valid element currently?
if (m_Elem)
return (m_Elem = m_Elem->next);
// Nothing to advance
return false;
}
// ------------------------------------------------------------------------------------------------
bool EntryDataList::Advance(Int32 n)
{
// Validate the database and list handle
Validate();
// Do we have a valid element currently?
if (m_Elem)
// Attempt to skip as many elements as possible
while ((n > 0) && (m_Elem = m_Elem->next)) --n;
// Return whether we have a valid element
return m_Elem;
}
// ------------------------------------------------------------------------------------------------
void EntryDataList::Reset()
{
// Validate the database and list handle
Validate();
// Go back to the first element
m_Elem = m_List;
}
// ------------------------------------------------------------------------------------------------
CSStr EntryDataList::GetString() const
{
// Validate the database, list and element handle
ValidateData();
// Attempt to perform the requested conversion
switch (m_Elem->entry_data.type)
{
case MMDB_DATA_TYPE_UTF8_STRING:
return m_Elem->entry_data.utf8_string;
case MMDB_DATA_TYPE_DOUBLE:
return FmtStr("%f", m_Elem->entry_data.double_value);
case MMDB_DATA_TYPE_UINT16:
return FmtStr("%u", m_Elem->entry_data.uint16);
case MMDB_DATA_TYPE_UINT32:
return FmtStr("%u", m_Elem->entry_data.uint32);
case MMDB_DATA_TYPE_INT32:
return FmtStr("%d", m_Elem->entry_data.int32);
case MMDB_DATA_TYPE_UINT64:
return FmtStr("%llu", m_Elem->entry_data.uint64);
case MMDB_DATA_TYPE_BOOLEAN:
return m_Elem->entry_data.boolean ? _SC("true") : _SC("false");
case MMDB_DATA_TYPE_FLOAT:
return FmtStr("%f", m_Elem->entry_data.float_value);
default:
SqThrowF("Unsupported conversion from (%s) to (string)", AsTypeStr(m_Elem->entry_data.type));
}
// Shouldn't really reach this point
return _SC("");
}
// ------------------------------------------------------------------------------------------------
SQInteger EntryDataList::GetInteger() const
{
// Validate the database, list and element handle
ValidateData();
// Attempt to perform the requested conversion
switch (m_Elem->entry_data.type)
{
#ifdef _SQ64
case MMDB_DATA_TYPE_UTF8_STRING:
return strtoll(m_Elem->entry_data.utf8_string, NULL, 10);
case MMDB_DATA_TYPE_DOUBLE:
return llround(m_Elem->entry_data.double_value);
case MMDB_DATA_TYPE_UINT16:
return m_Elem->entry_data.uint16;
case MMDB_DATA_TYPE_UINT32:
return m_Elem->entry_data.uint32;
case MMDB_DATA_TYPE_INT32:
return m_Elem->entry_data.int32;
case MMDB_DATA_TYPE_UINT64:
return Clamp(m_Elem->entry_data.uint64, 0, Uint64(NumLimit< SQInteger >::Max));
case MMDB_DATA_TYPE_BOOLEAN:
return m_Elem->entry_data.boolean ? 1 : 0;
case MMDB_DATA_TYPE_FLOAT:
return llround(m_Elem->entry_data.float_value);
default:
SqThrowF("Unsupported conversion from (%s) to (int32)", AsTypeStr(m_Elem->entry_data.type));
#else
case MMDB_DATA_TYPE_UTF8_STRING:
return strtol(m_Elem->entry_data.utf8_string, NULL, 10);
case MMDB_DATA_TYPE_DOUBLE:
return lround(m_Elem->entry_data.double_value);
case MMDB_DATA_TYPE_UINT16:
return m_Elem->entry_data.uint16;
case MMDB_DATA_TYPE_UINT32:
return Clamp(m_Elem->entry_data.uint32, 0U, Uint32(NumLimit< SQInteger >::Max));
case MMDB_DATA_TYPE_INT32:
return m_Elem->entry_data.int32;
case MMDB_DATA_TYPE_UINT64:
return Clamp(m_Elem->entry_data.uint64, 0ULL, Uint64(NumLimit< SQInteger >::Max));
case MMDB_DATA_TYPE_BOOLEAN:
return m_Elem->entry_data.boolean ? 1 : 0;
case MMDB_DATA_TYPE_FLOAT:
return lround(m_Elem->entry_data.float_value);
default:
SqThrowF("Unsupported conversion from (%s) to (int64)", AsTypeStr(m_Elem->entry_data.type));
#endif // _SQ64
}
// Shouldn't really reach this point
return 0;
}
// ------------------------------------------------------------------------------------------------
SQFloat EntryDataList::GetFloat() const
{
// Validate the database, list and element handle
ValidateData();
// Attempt to perform the requested conversion
switch (m_Elem->entry_data.type)
{
#ifdef SQUSEDOUBLE
case MMDB_DATA_TYPE_UTF8_STRING:
return static_cast< SQFloat >(strtod(m_Elem->entry_data.utf8_string, NULL));
#else
return static_cast< SQFloat >(strtof(m_Elem->entry_data.utf8_string, NULL));
#endif // SQUSEDOUBLE
case MMDB_DATA_TYPE_DOUBLE:
return static_cast< SQFloat >(m_Elem->entry_data.double_value);
case MMDB_DATA_TYPE_UINT16:
return static_cast< SQFloat >(m_Elem->entry_data.uint16);
case MMDB_DATA_TYPE_UINT32:
return static_cast< SQFloat >(round(m_Elem->entry_data.uint32));
case MMDB_DATA_TYPE_INT32:
return static_cast< SQFloat >(round(m_Elem->entry_data.int32));
case MMDB_DATA_TYPE_UINT64:
return static_cast< SQFloat >(round(m_Elem->entry_data.uint64));
case MMDB_DATA_TYPE_BOOLEAN:
return m_Elem->entry_data.boolean ? 1.0 : 0.0;
case MMDB_DATA_TYPE_FLOAT:
return static_cast< SQFloat >(m_Elem->entry_data.float_value);
default:
SqThrowF("Unsupported conversion from (%s) to (float)", AsTypeStr(m_Elem->entry_data.type));
}
// Shouldn't really reach this point
return 0.0;
}
// ------------------------------------------------------------------------------------------------
Object EntryDataList::GetLong() const
{
// Validate the database, list and element handle
ValidateData();
// Where the long number is retrieved
Uint64 longint = 0;
Int64 slong = 0;
// Attempt to perform the requested conversion
switch (m_Elem->entry_data.type)
{
case MMDB_DATA_TYPE_UTF8_STRING:
longint = strtoull(m_Elem->entry_data.utf8_string, NULL, 10);
break;
case MMDB_DATA_TYPE_DOUBLE:
{
slong = llround(m_Elem->entry_data.double_value);
longint = slong >= 0 ? slong : 0;
} break;
case MMDB_DATA_TYPE_UINT16:
longint = m_Elem->entry_data.uint16;
break;
case MMDB_DATA_TYPE_UINT32:
longint = m_Elem->entry_data.uint32;
break;
case MMDB_DATA_TYPE_INT32:
longint = m_Elem->entry_data.int32 >= 0 ? m_Elem->entry_data.int32 : 0;
break;
case MMDB_DATA_TYPE_UINT64:
longint = m_Elem->entry_data.uint64;
break;
case MMDB_DATA_TYPE_BOOLEAN:
longint = m_Elem->entry_data.boolean ? 1 : 0;
break;
case MMDB_DATA_TYPE_FLOAT:
{
slong = llround(m_Elem->entry_data.float_value);
longint = slong >= 0 ? slong : 0;
}
break;
default:
SqThrowF("Unsupported conversion from (%s) to (uint64)", AsTypeStr(m_Elem->entry_data.type));
}
// Obtain the initial stack size
const StackGuard sg(_SqVM);
// Push a long integer instance with the requested value on the stack
_SqMod->PushULongObject(_SqVM, longint);
// Get the object from the stack and return it
return Var< Object >(_SqVM, -1).value;
}
// ------------------------------------------------------------------------------------------------
bool EntryDataList::GetBool() const
{
// Validate the database, list and element handle
ValidateData();
// Attempt to perform the requested conversion
switch (m_Elem->entry_data.type)
{
case MMDB_DATA_TYPE_UTF8_STRING:
return !!(m_Elem->entry_data.utf8_string);
case MMDB_DATA_TYPE_DOUBLE:
return EpsGt(m_Elem->entry_data.double_value, 0.0d);
case MMDB_DATA_TYPE_UINT16:
return (m_Elem->entry_data.uint16 > 0);
case MMDB_DATA_TYPE_UINT32:
return (m_Elem->entry_data.uint32 > 0);
case MMDB_DATA_TYPE_INT32:
return (m_Elem->entry_data.int32 > 0);
case MMDB_DATA_TYPE_UINT64:
return (m_Elem->entry_data.uint64 > 0);
case MMDB_DATA_TYPE_BOOLEAN:
return m_Elem->entry_data.boolean;
case MMDB_DATA_TYPE_FLOAT:
return EpsGt(m_Elem->entry_data.float_value, 0.0f);
default:
SqThrowF("Unsupported conversion from (%s) to (boolean)", AsTypeStr(m_Elem->entry_data.type));
}
// Shouldn't really reach this point
return false;
}
// ------------------------------------------------------------------------------------------------
void EntryDataList::DumpTo(CSStr filepath, Int32 indent) const
{
// Validate the database and list handle
Validate();
// Validate the specified file path
if (!filepath || strlen(filepath) <= 0)
SqThrowF("Invalid file path");
// Attempt to open the specified file
FILE * fp = fopen(filepath, "w");
// Validate the file handle
if (!fp)
SqThrowF("Unable to open file %s", filepath);
// Attempt to dump the entry data list
Int32 status = MMDB_dump_entry_data_list(fp, m_List, indent);
// Close the file handle
fclose(fp);
// Validate the result of the operation
if (status != MMDB_SUCCESS)
// Now it's safe to throw the error
SqThrowF("Unable to dump the list [%s]", MMDB_strerror(status));
}
} // Namespace:: SqMod

View File

@ -0,0 +1,291 @@
#ifndef _SQMMDB_LOOKUPRESULT_HPP_
#define _SQMMDB_LOOKUPRESULT_HPP_
// ------------------------------------------------------------------------------------------------
#include "Common.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Class that can be used to traverse a list of results.
*/
class EntryDataList
{
protected:
// --------------------------------------------------------------------------------------------
typedef MMDB_entry_data_list_s Type; // The managed type.
// --------------------------------------------------------------------------------------------
typedef Type* Pointer; // Pointer to the managed type.
typedef const Type* ConstPtr; // Constant pointer to the managed type.
// --------------------------------------------------------------------------------------------
typedef Type& Reference; // Reference to the managed type.
typedef const Type& ConstRef; // Constant reference to the managed type.
/* --------------------------------------------------------------------------------------------
* Validate the database pointer and list handle and throw an error if invalid.
*/
void Validate() const;
/* --------------------------------------------------------------------------------------------
* Do a regular validation and also validate the currently processed element.
*/
void ValidateElem() const;
/* --------------------------------------------------------------------------------------------
* Do a regular validation and also validate the currently processed element data.
*/
void ValidateData() const;
/* --------------------------------------------------------------------------------------------
* Used to retrieve the string representation of the specified type identifier.
*/
static CSStr AsTypeStr(Uint32 id);
private:
// ---------------------------------------------------------------------------------------------
DbRef m_Db; /* The database from which this list comes from. */
Pointer m_List; /* The managed entry data list. */
Pointer m_Elem; /* The currently processed element from the list. */
/* --------------------------------------------------------------------------------------------
* Base constructor.
*/
EntryDataList(const DbRef & db, Pointer list)
: m_Db(db), m_List(list), m_Elem(list)
{
/* ... */
}
public:
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
EntryDataList();
/* --------------------------------------------------------------------------------------------
* Copy constructor. (disabled)
*/
EntryDataList(const EntryDataList &) = delete;
/* --------------------------------------------------------------------------------------------
* Move constructor.
*/
EntryDataList(EntryDataList && o)
: m_Db(o.m_Db)
, m_List(o.m_List)
, m_Elem(o.m_Elem)
{
o.m_List = nullptr;
o.m_Elem = nullptr;
}
/* --------------------------------------------------------------------------------------------
* Destructor.
*/
~EntryDataList();
/* --------------------------------------------------------------------------------------------
* Copy assignment operator. (disabled)
*/
EntryDataList & operator = (const EntryDataList &) = delete;
/* --------------------------------------------------------------------------------------------
* Move assignment operator.
*/
EntryDataList & operator = (EntryDataList && o)
{
if (m_List != o.m_List)
{
m_Db = o.m_Db;
m_List = o.m_List;
m_Elem = o.m_Elem;
o.m_List = nullptr;
o.m_Elem = nullptr;
}
return *this;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the internal entry data list structure pointer.
*/
Pointer GetHandle()
{
return m_List;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the internal entry data list structure pointer.
*/
Pointer GetHandle() const
{
return m_List;
}
/* --------------------------------------------------------------------------------------------
* Used by the script engine to compare two instances of this type.
*/
Int32 Cmp(const EntryDataList & o) const;
/* --------------------------------------------------------------------------------------------
* Used by the script engine to convert an instance of this type to a string.
*/
CSStr ToString() const
{
return m_Elem ? AsTypeStr(m_Elem->entry_data.type) : _SC("invalid");
}
/* --------------------------------------------------------------------------------------------
* Used by the script engine to retrieve the name from instances of this type.
*/
static SQInteger Typename(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* See whether this instance references a valid database and entry data list structure.
*/
bool IsValid() const
{
return m_Db && m_List;
}
/* --------------------------------------------------------------------------------------------
* See whether a valid element is currently processed.
*/
bool HaveElement() const
{
return m_Elem;
}
/* --------------------------------------------------------------------------------------------
* Used to retrieve the type of the current element as a string.
*/
CSStr TypeStr() const
{
// Validate the database and list handle
Validate();
// return the requested information
return m_Elem ? AsTypeStr(m_Elem->entry_data.type) : _SC("invalid");
}
/* --------------------------------------------------------------------------------------------
* Return the total entries in the list.
*/
Uint32 GetCount() const;
/* --------------------------------------------------------------------------------------------
* Go to the next element.
*/
bool Next();
/* --------------------------------------------------------------------------------------------
* Advance a certain number of elements.
*/
bool Advance(Int32 n);
/* --------------------------------------------------------------------------------------------
* Go back to the first element in the list.
*/
void Reset();
/* --------------------------------------------------------------------------------------------
* See whether a valid element is currently processed.
*/
bool HasData() const
{
// Validate the database, list and element handle
ValidateElem();
// Return the requested information
return m_Elem->entry_data.has_data;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the type identifier of the current element.
*/
SQInteger GetType() const
{
// Validate the database, list and element handle
ValidateElem();
// Return the requested information
return static_cast< SQInteger >(m_Elem->entry_data.type);
}
/* --------------------------------------------------------------------------------------------
* Retrieve the offset of the current element.
*/
SQInteger GetOffset() const
{
// Validate the database, list and element handle
ValidateElem();
// Return the requested information
return static_cast< SQInteger >(m_Elem->entry_data.offset);
}
/* --------------------------------------------------------------------------------------------
* Retrieve the offset of the next element.
*/
SQInteger GetOffsetToNext() const
{
// Validate the database, list and element handle
ValidateElem();
// Return the requested information
return static_cast< SQInteger >(m_Elem->entry_data.offset_to_next);
}
/* --------------------------------------------------------------------------------------------
* Retrieve the offset of the next element.
*/
SQInteger DataSize() const
{
// Validate the database, list and element handle
ValidateElem();
// Return the requested information
return static_cast< SQInteger >(m_Elem->entry_data.data_size);
}
/* --------------------------------------------------------------------------------------------
* Retrieve the value from the current element as a string.
*/
CSStr GetString() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the value from the current element as a native integer.
*/
SQInteger GetInteger() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the value from the current element as a floating point.
*/
SQFloat GetFloat() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the value from the current element as a long integer.
*/
Object GetLong() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the value from the current element as a boolean.
*/
bool GetBool() const;
/* --------------------------------------------------------------------------------------------
* Dumpt the contents of the list to the specified list.
*/
void DumpTo(CSStr filepath)
{
DumpTo(filepath, 0);
}
/* --------------------------------------------------------------------------------------------
* Dumpt the contents of the list to the specified list.
*/
void DumpTo(CSStr filepath, Int32 indent) const;
};
} // Namespace:: SqMod
#endif // _SQMMDB_LOOKUPRESULT_HPP_

View File

@ -0,0 +1,54 @@
// ------------------------------------------------------------------------------------------------
#include "LookupResult.hpp"
#include "Module.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
SQInteger LookupResult::Typename(HSQUIRRELVM vm)
{
static const SQChar name[] = _SC("SqMMDBLookupResult");
sq_pushstring(vm, name, sizeof(name));
return 1;
}
// ------------------------------------------------------------------------------------------------
void LookupResult::Validate() const
{
// Is the document handle valid?
if (!m_Db)
SqThrowF("Invalid Maxmind database reference");
}
// ------------------------------------------------------------------------------------------------
LookupResult::LookupResult()
: m_Db(), m_Result()
{
memset(&m_Result, 0, sizeof(Type));
}
// ------------------------------------------------------------------------------------------------
Int32 LookupResult::Cmp(const LookupResult & o) const
{
if (m_Db == o.m_Db)
return 0;
else if (m_Db.DbPtr() > o.m_Db.DbPtr())
return 1;
else
return -1;
}
// ------------------------------------------------------------------------------------------------
EntryDataList LookupResult::GetValueA(CSStr path, Array & arr) const
{
}
// ------------------------------------------------------------------------------------------------
EntryDataList LookupResult::GetValueT(CSStr path, Table & tbl) const
{
}
} // Namespace:: SqMod

View File

@ -0,0 +1,164 @@
#ifndef _SQMMDB_LOOKUPRESULT_HPP_
#define _SQMMDB_LOOKUPRESULT_HPP_
// ------------------------------------------------------------------------------------------------
#include "Common.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Class that can hold and be used to work with lookup results.
*/
class LookupResult
{
// --------------------------------------------------------------------------------------------
friend class Database; // Only a valid database instance can construct this type.
protected:
// --------------------------------------------------------------------------------------------
typedef MMDB_lookup_result_s Type; // The managed type.
// --------------------------------------------------------------------------------------------
typedef Type* Pointer; // Pointer to the managed type.
typedef const Type* ConstPtr; // Constant pointer to the managed type.
// --------------------------------------------------------------------------------------------
typedef Type& Reference; // Reference to the managed type.
typedef const Type& ConstRef; // Constant reference to the managed type.
/* --------------------------------------------------------------------------------------------
* Validate the database pointer and throw an error if invalid.
*/
void Validate() const;
private:
// ---------------------------------------------------------------------------------------------
DbRef m_Db; /* The database from which this result comes from. */
Type m_Result; /* The managed result structure. */
/* --------------------------------------------------------------------------------------------
* Construct and take ownership of a certain result.
*/
LookupResult(const DbRef & db, Reference result)
: m_Db(db), m_Result(result)
{
/* ... */
}
public:
/* --------------------------------------------------------------------------------------------
* Default constructor. (null)
*/
LookupResult();
/* --------------------------------------------------------------------------------------------
* Copy constructor.
*/
LookupResult(const LookupResult &) = default;
/* --------------------------------------------------------------------------------------------
* Move constructor.
*/
LookupResult(LookupResult &&) = default;
/* --------------------------------------------------------------------------------------------
* Destructor.
*/
~LookupResult()
{
/* We let the smart reference deal with deallocations if necessary. */
}
/* --------------------------------------------------------------------------------------------
* Copy assignment operator.
*/
LookupResult & operator = (const LookupResult &) = default;
/* --------------------------------------------------------------------------------------------
* Move assignment operator.
*/
LookupResult & operator = (LookupResult &&) = default;
/* --------------------------------------------------------------------------------------------
* Retrieve the internal result structure reference.
*/
Reference GetHandle()
{
return m_Result;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the internal result structure reference.
*/
ConstRef GetHandle() const
{
return m_Result;
}
/* --------------------------------------------------------------------------------------------
* Used by the script engine to compare two instances of this type.
*/
Int32 Cmp(const LookupResult & o) const;
/* --------------------------------------------------------------------------------------------
* Used by the script engine to convert an instance of this type to a string.
*/
CSStr ToString() const
{
return FmtStr("%u", m_Result.entry.offset);
}
/* --------------------------------------------------------------------------------------------
* Used by the script engine to retrieve the name from instances of this type.
*/
static SQInteger Typename(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* See whether this instance references a valid database and result structure.
*/
bool IsValid() const
{
return m_Db && m_Result.found_entry;
}
/* --------------------------------------------------------------------------------------------
* See whether the result contains a valid entry in the associated database.
*/
bool FoundEntry() const
{
// Validate the database handle
Validate();
// Return the requested information
return m_Result.found_entry;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the net-mask from the result structure.
*/
SQInteger GetNetMask() const
{
// Validate the database handle
Validate();
// Return the requested information
return static_cast< SQInteger >(m_Result.netmask);
}
/* --------------------------------------------------------------------------------------------
* Lookup data in the associated result using an array as the path.
*/
EntryDataList GetValueA(CSStr path, Array & arr) const;
/* --------------------------------------------------------------------------------------------
* Lookup data in the associated result using a table as the path.
*/
EntryDataList GetValueT(CSStr path, Table & tbl) const;
};
} // Namespace:: SqMod
#endif // _SQMMDB_LOOKUPRESULT_HPP_

302
modules/mmdb/Module.cpp Normal file
View File

@ -0,0 +1,302 @@
// --------------------------------------------------------------------------------------------
#include "Module.hpp"
#include "Common.hpp"
// --------------------------------------------------------------------------------------------
#include <sqrat.h>
// --------------------------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
// --------------------------------------------------------------------------------------------
#if defined(WIN32) || defined(_WIN32)
#include <Windows.h>
#endif
namespace SqMod {
// --------------------------------------------------------------------------------------------
PluginFuncs* _Func = NULL;
PluginCallbacks* _Clbk = NULL;
PluginInfo* _Info = NULL;
// --------------------------------------------------------------------------------------------
HSQAPI _SqAPI = NULL;
HSQEXPORTS _SqMod = NULL;
HSQUIRRELVM _SqVM = NULL;
/* ------------------------------------------------------------------------------------------------
* Bind speciffic functions to certain server events.
*/
void BindCallbacks();
/* ------------------------------------------------------------------------------------------------
* Undo changes made with BindCallbacks().
*/
void UnbindCallbacks();
/* --------------------------------------------------------------------------------------------
* Register the module API under the specified virtual machine.
*/
void RegisterAPI(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Initialize the plugin by obtaining the API provided by the host plugin.
*/
void OnSquirrelInitialize()
{
// Attempt to import the plugin API exported by the host plugin
_SqMod = sq_api_import(_Func);
// Did we failed to obtain the plugin exports?
if(!_SqMod)
OutputError("Failed to attach [%s] on host plugin.", SQMMDB_NAME);
else
{
// Obtain the Squirrel API
_SqAPI = _SqMod->GetSquirrelAPI();
// Expand the Squirrel API into global functions
sq_api_expand(_SqAPI);
}
}
/* --------------------------------------------------------------------------------------------
* Load the module on the virtual machine provided by the host module.
*/
void OnSquirrelLoad()
{
// Make sure that we have a valid plugin API
if (!_SqMod)
return; /* Unable to proceed. */
// Obtain the Squirrel API and VM
_SqVM = _SqMod->GetSquirrelVM();
// Make sure that a valid virtual machine exists
if (!_SqVM)
return; /* Unable to proceed. */
// Set this as the default database
DefaultVM::Set(_SqVM);
// Register the module API
RegisterAPI(_SqVM);
// Notify about the current status
OutputMessage("Registered: %s", SQMMDB_NAME);
}
/* --------------------------------------------------------------------------------------------
* The virtual machine is about to be terminated and script resources should be released.
*/
void OnSquirrelTerminate()
{
OutputMessage("Terminating: %s", SQMMDB_NAME);
// Release the current database (if any)
DefaultVM::Set(NULL);
// Release script resources...
}
/* --------------------------------------------------------------------------------------------
* Validate the module API to make sure we don't run into issues.
*/
bool CheckAPIVer(CCStr ver)
{
// Obtain the numeric representation of the API version
long vernum = strtol(ver, NULL, 10);
// Check against version mismatch
if (vernum == SQMOD_API_VER)
return true;
// Log the incident
OutputError("API version mismatch on %s", SQMMDB_NAME);
OutputMessage("=> Requested: %ld Have: %ld", vernum, SQMOD_API_VER);
// Invoker should not attempt to communicate through the module API
return false;
}
/* --------------------------------------------------------------------------------------------
* React to command sent by other plugins.
*/
static int OnInternalCommand(unsigned int type, const char * text)
{
switch(type)
{
case SQMOD_INITIALIZE_CMD:
if (CheckAPIVer(text))
OnSquirrelInitialize();
break;
case SQMOD_LOAD_CMD:
OnSquirrelLoad();
break;
case SQMOD_TERMINATE_CMD:
OnSquirrelTerminate();
break;
default: break;
}
return 1;
}
/* --------------------------------------------------------------------------------------------
* The server was initialized and this plugin was loaded successfully.
*/
static int OnInitServer()
{
return 1;
}
static void OnShutdownServer(void)
{
// The server may still send callbacks
UnbindCallbacks();
}
// ------------------------------------------------------------------------------------------------
void BindCallbacks()
{
_Clbk->OnInitServer = OnInitServer;
_Clbk->OnInternalCommand = OnInternalCommand;
_Clbk->OnShutdownServer = OnShutdownServer;
}
// ------------------------------------------------------------------------------------------------
void UnbindCallbacks()
{
_Clbk->OnInitServer = NULL;
_Clbk->OnInternalCommand = NULL;
_Clbk->OnShutdownServer = NULL;
}
// --------------------------------------------------------------------------------------------
void RegisterAPI(HSQUIRRELVM vm)
{
}
// --------------------------------------------------------------------------------------------
void OutputMessageImpl(const char * msg, va_list args)
{
#if defined(WIN32) || defined(_WIN32)
HANDLE hstdout = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO csb_before;
GetConsoleScreenBufferInfo( hstdout, &csb_before);
SetConsoleTextAttribute(hstdout, FOREGROUND_GREEN);
printf("[SQMOD] ");
SetConsoleTextAttribute(hstdout, FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY);
vprintf(msg, args);
puts("");
SetConsoleTextAttribute(hstdout, csb_before.wAttributes);
#else
printf("%c[0;32m[SQMOD]%c[0;37m", 27, 27, msg);
vprintf(msg, args);
puts("");
#endif
}
// --------------------------------------------------------------------------------------------
void OutputErrorImpl(const char * msg, va_list args)
{
#if defined(WIN32) || defined(_WIN32)
HANDLE hstdout = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO csb_before;
GetConsoleScreenBufferInfo( hstdout, &csb_before);
SetConsoleTextAttribute(hstdout, FOREGROUND_RED | FOREGROUND_INTENSITY);
printf("[SQMOD] ");
SetConsoleTextAttribute(hstdout, FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY);
vprintf(msg, args);
puts("");
SetConsoleTextAttribute(hstdout, csb_before.wAttributes);
#else
printf("%c[0;32m[SQMOD]%c[0;37m", 27, 27, msg);
vprintf(msg, args);
puts("");
#endif
}
// --------------------------------------------------------------------------------------------
void OutputDebug(const char * msg, ...)
{
#ifdef _DEBUG
// Initialize the arguments list
va_list args;
va_start(args, msg);
// Call the output function
OutputMessageImpl(msg, args);
// Finalize the arguments list
va_end(args);
#else
SQMOD_UNUSED_VAR(msg);
#endif
}
// --------------------------------------------------------------------------------------------
void OutputMessage(const char * msg, ...)
{
// Initialize the arguments list
va_list args;
va_start(args, msg);
// Call the output function
OutputMessageImpl(msg, args);
// Finalize the arguments list
va_end(args);
}
// --------------------------------------------------------------------------------------------
void OutputError(const char * msg, ...)
{
// Initialize the arguments list
va_list args;
va_start(args, msg);
// Call the output function
OutputErrorImpl(msg, args);
// Finalize the arguments list
va_end(args);
}
} // Namespace:: SqMod
// --------------------------------------------------------------------------------------------
SQMOD_API_EXPORT unsigned int VcmpPluginInit(PluginFuncs* functions, PluginCallbacks* callbacks, PluginInfo* info)
{
using namespace SqMod;
// Output plugin header
puts("");
OutputMessage("--------------------------------------------------------------------");
OutputMessage("Plugin: %s", SQMMDB_NAME);
OutputMessage("Author: %s", SQMMDB_AUTHOR);
OutputMessage("Legal: %s", SQMMDB_COPYRIGHT);
OutputMessage("--------------------------------------------------------------------");
puts("");
// Attempt to find the host plugin ID
int host_plugin_id = functions->FindPlugin((char *)(SQMOD_HOST_NAME));
// See if our plugin was loaded after the host plugin
if (host_plugin_id < 0)
{
OutputError("%s could find the host plugin", SQMMDB_NAME);
// Don't load!
return SQMOD_FAILURE;
}
// Should never reach this point but just in case
else if (host_plugin_id > (info->nPluginId))
{
OutputError("%s loaded after the host plugin", SQMMDB_NAME);
// Don't load!
return SQMOD_FAILURE;
}
// Store server proxies
_Func = functions;
_Clbk = callbacks;
_Info = info;
// Assign plugin information
_Info->uPluginVer = SQMMDB_VERSION;
strcpy(_Info->szName, SQMMDB_HOST_NAME);
// Bind callbacks
BindCallbacks();
// Notify that the plugin was successfully loaded
OutputMessage("Successfully loaded %s", SQMMDB_NAME);
// Dummy spacing
puts("");
// Done!
return SQMOD_SUCCESS;
}

41
modules/mmdb/Module.hpp Normal file
View File

@ -0,0 +1,41 @@
#ifndef _SQMMDB_MODULE_HPP_
#define _SQMMDB_MODULE_HPP_
// ------------------------------------------------------------------------------------------------
#include "SqMod.h"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Proxies to comunicate with the server.
*/
extern PluginFuncs* _Func;
extern PluginCallbacks* _Clbk;
extern PluginInfo* _Info;
/* ------------------------------------------------------------------------------------------------
* Proxies to comunicate with the Squirrel plugin.
*/
extern HSQAPI _SqAPI;
extern HSQEXPORTS _SqMod;
extern HSQUIRRELVM _SqVM;
/* ------------------------------------------------------------------------------------------------
* Output a message only if the _DEBUG was defined.
*/
void OutputDebug(const char * msg, ...);
/* ------------------------------------------------------------------------------------------------
* Output a formatted user message to the console.
*/
void OutputMessage(const char * msg, ...);
/* ------------------------------------------------------------------------------------------------
* Output a formatted error message to the console.
*/
void OutputError(const char * msg, ...);
} // Namespace:: SqMod
#endif // _SQMMDB_MODULE_HPP_

68
modules/mmdb/SockAddr.cpp Normal file
View File

@ -0,0 +1,68 @@
// ------------------------------------------------------------------------------------------------
#include "Sockaddr.hpp"
#include "Module.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
SQInteger SockAddr::Typename(HSQUIRRELVM vm)
{
static const SQChar name[] = _SC("SqMMDBSockAddr");
sq_pushstring(vm, name, sizeof(name));
return 1;
}
// ------------------------------------------------------------------------------------------------
void SockAddr::Validate() const
{
// Is the document handle valid?
if (!m_Handle)
SqThrowF("Invalid sockaddr structure handle");
}
// ------------------------------------------------------------------------------------------------
SockAddr::SockAddr(CSStr addr)
: m_Handle(NULL), m_Addres(_SC(""))
{
struct addrinfo hints;
// Configure the hints structure
hints.ai_family = AF_UNSPEC;
hints.ai_flags = AI_NUMERICHOST;
// We set ai_socktype so that we only get one result back
hints.ai_socktype = SOCK_STREAM;
// Attempt to obtain information about the specified address
Int32 status = getaddrinfo(addr, NULL, &hints, &m_Handle);
// Validate the success of the operation
if (!status)
{
// See if we must free any handles (just in case)
if (m_Handle)
freeaddrinfo(m_Handle);
// Now it's safe to throw the error
SqThrowF("Unable to query the specified address for information [%s]", gai_strerror(status));
}
// Save the specified string address
m_Addres.assign(addr ? addr : _SC(""));
}
// ------------------------------------------------------------------------------------------------
SockAddr::~SockAddr()
{
if (m_Handle)
freeaddrinfo(m_Handle);
}
// ------------------------------------------------------------------------------------------------
Int32 SockAddr::Cmp(const SockAddr & o) const
{
if (m_Handle == o.m_Handle)
return 0;
else if (m_Handle > o.m_Handle)
return 1;
else
return -1;
}
} // Namespace:: SqMod

147
modules/mmdb/Sockaddr.hpp Normal file
View File

@ -0,0 +1,147 @@
#ifndef _SQMMDB_SOCKADDR_HPP_
#define _SQMMDB_SOCKADDR_HPP_
// ------------------------------------------------------------------------------------------------
#include "Common.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Class that can obtain information from string addresses and be used repeatedly thereafter.
*/
class SockAddr
{
protected:
// --------------------------------------------------------------------------------------------
typedef struct addrinfo Type; // The managed type.
// --------------------------------------------------------------------------------------------
typedef Type* Pointer; // Pointer to the managed type.
typedef const Type* ConstPtr; // Constant pointer to the managed type.
// --------------------------------------------------------------------------------------------
typedef Type& Reference; // Reference to the managed type.
typedef const Type& ConstRef; // Constant reference to the managed type.
/* --------------------------------------------------------------------------------------------
* Validate the sockaddr pointer and throw an error if invalid.
*/
void Validate() const;
private:
// ---------------------------------------------------------------------------------------------
Pointer m_Handle; /* The managed sockaddr structure. */
String m_Addres; /* The address that was queried for information. */
public:
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
SockAddr()
: m_Handle(NULL), m_Addres(_SC(""))
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Base constructor.
*/
SockAddr(CSStr addr);
/* --------------------------------------------------------------------------------------------
* Copy constructor. (disabled)
*/
SockAddr(const SockAddr &) = delete;
/* --------------------------------------------------------------------------------------------
* Move constructor.
*/
SockAddr(SockAddr && o)
: m_Handle(o.m_Handle)
, m_Addres(o.m_Addres)
{
o.m_Handle = nullptr;
}
/* --------------------------------------------------------------------------------------------
* Destructor.
*/
~SockAddr();
/* --------------------------------------------------------------------------------------------
* Copy assignment operator. (disabled)
*/
SockAddr & operator = (const SockAddr &) = delete;
/* --------------------------------------------------------------------------------------------
* Move assignment operator.
*/
SockAddr & operator = (SockAddr && o)
{
if (m_Handle != o.m_Handle)
{
m_Handle = o.m_Handle;
m_Addres = o.m_Addres;
o.m_Handle = nullptr;
}
return *this;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the internal addrinfo structure pointer.
*/
Pointer GetHandle()
{
return m_Handle;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the internal addrinfo structure pointer.
*/
Pointer GetHandle() const
{
return m_Handle;
}
/* --------------------------------------------------------------------------------------------
* Used by the script engine to compare two instances of this type.
*/
Int32 Cmp(const SockAddr & o) const;
/* --------------------------------------------------------------------------------------------
* Used by the script engine to convert an instance of this type to a string.
*/
CSStr ToString() const
{
return m_Addres.c_str();
}
/* --------------------------------------------------------------------------------------------
* Used by the script engine to retrieve the name from instances of this type.
*/
static SQInteger Typename(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* See whether this instance references a valid addrinfo structure.
*/
bool IsValid() const
{
return m_Handle;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the associated string address.
*/
CSStr GetAddress() const
{
return m_Addres.c_str();
}
};
} // Namespace:: SqMod
#endif // _SQMMDB_SOCKADDR_HPP_

View File

@ -389,7 +389,7 @@ SQInteger Connection::ExecF(HSQUIRRELVM vm)
SQRESULT ret = sqstd_format(vm, 3, &len, &sql);
// Did the format failed?
if (SQ_FAILED(ret))
return ret;
return ret; // Propagate the exception
// Attempt to execute the resulted query
if ((inst.value->m_Handle = sqlite3_exec(inst.value->m_Handle, sql, NULL, NULL, NULL)) != SQLITE_OK)
{
@ -399,7 +399,7 @@ SQInteger Connection::ExecF(HSQUIRRELVM vm)
// Push the result onto the stack
sq_pushinteger(vm, sqlite3_changes(inst.value->m_Handle));
}
// All methods of retrieving the message value failed
// All methods of retrieving the string value failed
else
return sq_throwerror(vm, "Unable to extract the query string");
// At this point we should have a return value on the stack
@ -455,14 +455,14 @@ SQInteger Connection::QueueF(HSQUIRRELVM vm)
SQRESULT ret = sqstd_format(vm, 3, &len, &sql);
// Did the format failed?
if (SQ_FAILED(ret))
return ret;
return ret; // Propagate the exception
// Is there even a query to queue?
else if (IsQueryEmpty(sql))
return sq_throwerror(vm,"No query to queue");
// Attempt to queue the specified query
inst.value->m_Handle->mQueue.push_back(sql);
}
// All methods of retrieving the message value failed
// All methods of retrieving the string value failed
else
return sq_throwerror(vm, "Unable to extract the query string");
// This function does not return a value
@ -519,7 +519,7 @@ SQInteger Connection::QueryF(HSQUIRRELVM vm)
SQRESULT ret = sqstd_format(vm, 3, &len, &sql);
// Did the format failed?
if (SQ_FAILED(ret))
return ret;
return ret; // Propagate the exception
// Attempt to create a statement with the specified query
try
{
@ -530,7 +530,7 @@ SQInteger Connection::QueryF(HSQUIRRELVM vm)
return sq_throwerror(vm, e.Message().c_str());
}
}
// All methods of retrieving the message value failed
// All methods of retrieving the string value failed
else
return sq_throwerror(vm, "Unable to extract the query string");
// At this point we should have a return value on the stack

View File

@ -58,17 +58,19 @@ extern "C" {
#define SQMOD_TERMINATE_CMD 0xDEADC0DE
#define SQMOD_API_VER 1
/*primitive functions*/
//primitive functions
typedef HSQAPI (*SqEx_GetSquirrelAPI) (void);
typedef HSQUIRRELVM (*SqEx_GetSquirrelVM) (void);
/*logging utilities*/
//logging utilities
typedef void (*SqEx_LogMessage) (const SQChar * fmt, ...);
/*long numbers*/
//script loading
typedef SQRESULT (*SqEx_LoadScript) (const SQChar * filepath);
//long numbers
typedef SQRESULT (*SqEx_GetSLongValue) (HSQUIRRELVM vm, SQInteger idx, SqInt64 * num);
typedef void (*SqEx_PushSLongObject) (HSQUIRRELVM vm, SqInt64 num);
typedef SQRESULT (*SqEx_GetULongValue) (HSQUIRRELVM vm, SQInteger idx, SqUint64 * num);
typedef void (*SqEx_PushULongObject) (HSQUIRRELVM vm, SqUint64 num);
/*time utilities*/
//time utilities
typedef SqInt64 (*SqEx_GetCurrentSysTime) (void);
typedef SqInt64 (*SqEx_GetEpochTimeMicro) (void);
typedef SqInt64 (*SqEx_GetEpochTimeMilli) (void);
@ -80,11 +82,11 @@ extern "C" {
*/
typedef struct
{
unsigned int uStructSize;
/*primitive functions*/
unsigned int StructSize;
//primitive functions
SqEx_GetSquirrelAPI GetSquirrelAPI;
SqEx_GetSquirrelVM GetSquirrelVM;
/*logging utilities*/
//logging utilities
SqEx_LogMessage LogDbg;
SqEx_LogMessage LogUsr;
SqEx_LogMessage LogScs;
@ -99,6 +101,8 @@ extern "C" {
SqEx_LogMessage LogSWrn;
SqEx_LogMessage LogSErr;
SqEx_LogMessage LogSFtl;
//script loading
SqEx_LoadScript LoadScript;
/*long numbers*/
SqEx_GetSLongValue GetSLongValue;
SqEx_PushSLongObject PushSLongObject;

View File

@ -14,6 +14,14 @@ const AABB AABB::MAX = AABB(Vector3::MIN, Vector3::MAX);
// ------------------------------------------------------------------------------------------------
SQChar AABB::Delim = ',';
// ------------------------------------------------------------------------------------------------
SQInteger AABB::Typename(HSQUIRRELVM vm)
{
static SQChar name[] = _SC("AABB");
sq_pushstring(vm, name, sizeof(name));
return 1;
}
// ------------------------------------------------------------------------------------------------
AABB::AABB()
: min(-1.0), max(1.0)
@ -49,27 +57,6 @@ AABB::AABB(const Vector3 & vmin, const Vector3 & vmax)
/* ... */
}
// ------------------------------------------------------------------------------------------------
AABB::AABB(const AABB & b)
: min(b.min), max(b.max)
{
/* ... */
}
// ------------------------------------------------------------------------------------------------
AABB::~AABB()
{
/* ... */
}
// ------------------------------------------------------------------------------------------------
AABB & AABB::operator = (const AABB & b)
{
min = b.min;
max = b.max;
return *this;
}
// ------------------------------------------------------------------------------------------------
AABB & AABB::operator = (Value s)
{
@ -304,7 +291,7 @@ Int32 AABB::Cmp(const AABB & o) const
// ------------------------------------------------------------------------------------------------
CSStr AABB::ToString() const
{
return ToStringF("%f,%f,%f,%f,%f,%f", min.x, min.y, min.z, max.x, max.y, max.z);
return ToStrF("%f,%f,%f,%f,%f,%f", min.x, min.y, min.z, max.x, max.y, max.z);
}
// ------------------------------------------------------------------------------------------------
@ -392,6 +379,7 @@ void Register_AABB(HSQUIRRELVM vm)
.Prop(_SC("abs"), &AABB::Abs)
/* Core Metamethods */
.Func(_SC("_tostring"), &AABB::ToString)
.SquirrelFunc(_SC("_typename"), &AABB::Typename)
.Func(_SC("_cmp"), &AABB::Cmp)
/* Metamethods */
.Func<AABB (AABB::*)(const AABB &) const>(_SC("_add"), &AABB::operator +)

View File

@ -8,304 +8,328 @@
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
*
* Class used to represent an axis aligned bounding box in three-dimensional space.
*/
struct AABB
{
/* --------------------------------------------------------------------------------------------
* ...
* The type of value used by components of type.
*/
typedef float Value;
/* --------------------------------------------------------------------------------------------
* ...
* Helper instances for common values mostly used as return types or comparison.
*/
static const AABB NIL;
static const AABB MIN;
static const AABB MAX;
static const AABB MIN;
static const AABB MAX;
/* --------------------------------------------------------------------------------------------
* ...
* The delimiter character to be used when extracting values from strings.
*/
static SQChar Delim;
/* --------------------------------------------------------------------------------------------
* ...
* The minimum and maximum components of this type.
*/
Vector3 min, max;
/* --------------------------------------------------------------------------------------------
*
* Default constructor.
*/
AABB();
/* --------------------------------------------------------------------------------------------
* ...
* Construct a an equally sized and perfectly shaped box from a scalar value.
*/
AABB(Value sv);
/* --------------------------------------------------------------------------------------------
* ...
* Construct a an equally sized but imperfectly shaped box from individual components of a
* three-dimensional point.
*/
AABB(Value xv, Value yv, Value zv);
/* --------------------------------------------------------------------------------------------
* ...
* Construct a an unequally sized and imperfectly shaped box from individual components of two
* three-dimensional points.
*/
AABB(Value xmin, Value ymin, Value zmin, Value xmax, Value ymax, Value zmax);
/* --------------------------------------------------------------------------------------------
* ...
* Construct a an unequally sized and imperfectly shaped box from two three-dimensional
* vectors representing two three-dimensional points.
*/
AABB(const Vector3 & vmin, const Vector3 & vmax);
/* --------------------------------------------------------------------------------------------
*
* Copy constructor.
*/
AABB(const AABB & o);
AABB(const AABB & o) = default;
/* --------------------------------------------------------------------------------------------
*
* Move constructor.
*/
~AABB();
AABB(AABB && o) = default;
/* --------------------------------------------------------------------------------------------
*
* Destructor.
*/
AABB & operator = (const AABB & o);
~AABB() = default;
/* --------------------------------------------------------------------------------------------
* ...
* Copy assignment operator.
*/
AABB & operator = (const AABB & o) = default;
/* --------------------------------------------------------------------------------------------
* Move assignment operator.
*/
AABB & operator = (AABB && o) = default;
/* --------------------------------------------------------------------------------------------
* Scalar value assignment operator.
*/
AABB & operator = (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Three-dimensional vector assignment operator.
*/
AABB & operator = (const Vector3 & v);
/* --------------------------------------------------------------------------------------------
* ...
* Four-dimensional vector assignment operator threated as a three-dimensional vector.
*/
AABB & operator = (const Vector4 & v);
/* --------------------------------------------------------------------------------------------
* ...
* Addition assignment operator.
*/
AABB & operator += (const AABB & b);
/* --------------------------------------------------------------------------------------------
* ...
* Subtraction assignment operator.
*/
AABB & operator -= (const AABB & b);
/* --------------------------------------------------------------------------------------------
* ...
* Multiplication assignment operator.
*/
AABB & operator *= (const AABB & b);
/* --------------------------------------------------------------------------------------------
* ...
* Division assignment operator.
*/
AABB & operator /= (const AABB & b);
/* --------------------------------------------------------------------------------------------
* ...
* Modulo assignment operator.
*/
AABB & operator %= (const AABB & b);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value addition assignment operator.
*/
AABB & operator += (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value subtraction assignment operator.
*/
AABB & operator -= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value multiplication assignment operator.
*/
AABB & operator *= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value division assignment operator.
*/
AABB & operator /= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value modulo assignment operator.
*/
AABB & operator %= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Pre-increment operator.
*/
AABB & operator ++ ();
/* --------------------------------------------------------------------------------------------
* ...
* Pre-decrement operator.
*/
AABB & operator -- ();
/* --------------------------------------------------------------------------------------------
* ...
* Post-increment operator.
*/
AABB operator ++ (int);
/* --------------------------------------------------------------------------------------------
* ...
* Post-decrement operator.
*/
AABB operator -- (int);
/* --------------------------------------------------------------------------------------------
* ...
* Addition operator.
*/
AABB operator + (const AABB & b) const;
/* --------------------------------------------------------------------------------------------
* ...
* Subtraction operator.
*/
AABB operator - (const AABB & b) const;
/* --------------------------------------------------------------------------------------------
* ...
* Multiplication operator.
*/
AABB operator * (const AABB & b) const;
/* --------------------------------------------------------------------------------------------
* ...
* Division operator.
*/
AABB operator / (const AABB & b) const;
/* --------------------------------------------------------------------------------------------
* ...
* Modulo operator.
*/
AABB operator % (const AABB & b) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value addition operator.
*/
AABB operator + (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value subtraction operator.
*/
AABB operator - (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value multiplication operator.
*/
AABB operator * (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value division operator.
*/
AABB operator / (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value modulo operator.
*/
AABB operator % (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Unary plus operator.
*/
AABB operator + () const;
/* --------------------------------------------------------------------------------------------
* ...
* Unary minus operator.
*/
AABB operator - () const;
/* --------------------------------------------------------------------------------------------
* ...
* Equality comparison operator.
*/
bool operator == (const AABB & b) const;
/* --------------------------------------------------------------------------------------------
* ...
* Inequality comparison operator.
*/
bool operator != (const AABB & b) const;
/* --------------------------------------------------------------------------------------------
* ...
* Less than comparison operator.
*/
bool operator < (const AABB & b) const;
/* --------------------------------------------------------------------------------------------
* ...
* Greater than comparison operator.
*/
bool operator > (const AABB & b) const;
/* --------------------------------------------------------------------------------------------
* ...
* Less than or equal comparison operator.
*/
bool operator <= (const AABB & b) const;
/* --------------------------------------------------------------------------------------------
* ...
* Greater than or equal comparison operator.
*/
bool operator >= (const AABB & b) const;
/* --------------------------------------------------------------------------------------------
* ...
* Used by the script engine to compare two instances of this type.
*/
Int32 Cmp(const AABB & b) const;
/* --------------------------------------------------------------------------------------------
* ...
* Used by the script engine to convert an instance of this type to a string.
*/
CSStr ToString() const;
/* --------------------------------------------------------------------------------------------
* ...
* Used by the script engine to retrieve the name from instances of this type.
*/
static SQInteger Typename(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Set an equally sized and perfectly shaped box from a scalar value.
*/
void Set(Value ns);
/* --------------------------------------------------------------------------------------------
* ...
* Set an equally sized but imperfectly shaped box from individual components of a
* three-dimensional point.
*/
void Set(Value nx, Value ny, Value nz);
/* --------------------------------------------------------------------------------------------
* ...
* Set an unequally sized and imperfectly shaped box from individual components of two
* three-dimensional points.
*/
void Set(Value xmin, Value ymin, Value zmin, Value xmax, Value ymax, Value zmax);
/* --------------------------------------------------------------------------------------------
* ...
* Set the same box from another instance of this type.
*/
void Set(const AABB & b);
/* --------------------------------------------------------------------------------------------
* ...
* Set an equally sized and imperfectly shaped box from a single three-dimensional vector
* representing a single three-dimensional point.
*/
void Set(const Vector3 & v);
/* --------------------------------------------------------------------------------------------
* ...
* Set an unequally sized and imperfectly shaped box from two three-dimensional vectors
* representing two three-dimensional points.
*/
void Set(const Vector3 & nmin, const Vector3 & nmax);
/* --------------------------------------------------------------------------------------------
* ...
* Set an equally sized and imperfectly shaped box from a single four-dimensional vector
* representing a single three-dimensional point.
*/
void Set(const Vector4 & v);
/* --------------------------------------------------------------------------------------------
* ...
* Set an unequally sized and imperfectly shaped box from two four-dimensional vectors
* representing two three-dimensional points.
*/
void Set(const Vector4 & nmin, const Vector4 & nmax);
/* --------------------------------------------------------------------------------------------
* ...
* Set the values extracted from the specified string using the specified delimiter.
*/
void Set(CSStr values, SQChar delim);
/* --------------------------------------------------------------------------------------------
* ...
* Clear the component values to default.
*/
void Clear()
{
@ -314,7 +338,7 @@ static const AABB MAX;
}
/* --------------------------------------------------------------------------------------------
* ...
* Retrieve a new instance of this type with absolute component values.
*/
AABB Abs() const;
};

View File

@ -1,10 +1,10 @@
// ------------------------------------------------------------------------------------------------
#include "Base/Buffer.hpp"
#include "Buffer.hpp"
// ------------------------------------------------------------------------------------------------
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <cstdlib>
#include <cstring>
#include <cstdarg>
#include <exception>
#include <stdexcept>
@ -14,7 +14,7 @@ namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Compute the next power of two for the specified number.
*/
static inline unsigned int NPow2(unsigned int num)
inline unsigned int NextPow2(unsigned int num)
{
--num;
num |= num >> 1;
@ -40,9 +40,7 @@ void ThrowMemExcept(const char * msg, ...)
int ret = vsnprintf(buffer, sizeof(buffer), msg, args);
// Check for formatting errors
if (ret < 0)
{
throw std::runtime_error("Unknown memory error");
}
// Throw the actual exception
throw std::runtime_error(buffer);
}
@ -53,12 +51,10 @@ void ThrowMemExcept(const char * msg, ...)
static Buffer::Pointer AllocMem(Buffer::SzType size)
{
// Attempt to allocate memory directly
Buffer::Pointer ptr = (Buffer::Pointer)malloc(size);
Buffer::Pointer ptr = reinterpret_cast< Buffer::Pointer >(malloc(size));
// Validate the allocated memory
if (!ptr)
{
ThrowMemExcept("Unable to allocate (%u) bytes of memory", size);
}
// Return the allocated memory
return ptr;
}
@ -75,36 +71,36 @@ class MemCat
public:
// --------------------------------------------------------------------------------------------
typedef Buffer::Value Value;
typedef Buffer::Value Value; // The type of value used to represent a byte.
// --------------------------------------------------------------------------------------------
typedef Buffer::Reference Reference;
typedef Buffer::ConstRef ConstRef;
typedef Buffer::Reference Reference; // A reference to the stored value type.
typedef Buffer::ConstRef ConstRef; // A const reference to the stored value type.
// --------------------------------------------------------------------------------------------
typedef Buffer::Pointer Pointer;
typedef Buffer::ConstPtr ConstPtr;
typedef Buffer::Pointer Pointer; // A pointer to the stored value type.
typedef Buffer::ConstPtr ConstPtr; // A const pointer to the stored value type.
// --------------------------------------------------------------------------------------------
typedef Buffer::SzType SzType;
typedef Buffer::SzType SzType; // The type used to represent size in general.
private:
/* --------------------------------------------------------------------------------------------
*
* Structure used to store a memory chunk in the linked list.
*/
struct Node
{
// ----------------------------------------------------------------------------------------
SzType mCap;
Pointer mPtr;
Node* mNext;
SzType mCap; /* The size of the memory chunk. */
Pointer mPtr; /* Pointer to the memory chunk. */
Node* mNext; /* The next node in the list. */
/* ----------------------------------------------------------------------------------------
* Base constructor.
*/
Node(Node * next)
: mCap(0), mPtr(NULL), mNext(next)
: mCap(0), mPtr(nullptr), mNext(next)
{
/* ... */
}
@ -120,7 +116,7 @@ private:
* Default constructor.
*/
MemCat()
: m_Head(NULL)
: m_Head(nullptr)
{
/* ... */
}
@ -130,20 +126,18 @@ private:
*/
~MemCat()
{
for (Node * node = m_Head, * next = NULL; node; node = next)
for (Node * node = m_Head, * next = nullptr; node; node = next)
{
// Free the memory (if any)
if (node->mPtr)
{
free(node->mPtr);
}
// Save the next node
next = node->mNext;
// Release the node instance
delete node;
}
// Explicitly set the head node to null
m_Head = NULL;
m_Head = nullptr;
}
/* --------------------------------------------------------------------------------------------
@ -151,20 +145,18 @@ private:
*/
void Clear()
{
for (Node * node = m_Head, * next = NULL; node; node = next)
for (Node * node = m_Head, * next = nullptr; node; node = next)
{
// Free the memory (if any)
if (node->mPtr)
{
free(node->mPtr);
}
// Save the next node
next = node->mNext;
// Release the node instance
Push(node);
}
// Explicitly set the head node to null
m_Head = NULL;
m_Head = nullptr;
}
/* --------------------------------------------------------------------------------------------
@ -174,21 +166,17 @@ private:
{
// NOTE: Function assumes (size > 0)
// Find a buffer large enough to satisfy the requested size
for (Node * node = m_Head, * prev = NULL; node; prev = node, node = node->mNext)
for (Node * node = m_Head, * prev = nullptr; node; prev = node, node = node->mNext)
{
// Is this buffer large enough?
if (node->mCap >= size)
{
// Was there a previous node?
if (prev)
{
prev->mNext = node->mNext;
}
// Probably this was the head
else
{
m_Head = node->mNext;
}
// Assign the memory
ptr = node->mPtr;
// Assign the size
@ -200,10 +188,11 @@ private:
}
}
// Round up the size to a power of two number
size = (size & (size - 1)) ? NPow2(size) : size;
size = (size & (size - 1)) ? NextPow2(size) : size;
// Allocate the memory directly
ptr = AllocMem(size);
// See if the memory could be allocated
// (shouldn't reach this point if allocation failed)
if (!ptr)
{
// Revert the size
@ -219,9 +208,7 @@ private:
void Drop(Pointer & ptr, SzType & size)
{
if (!ptr)
{
ThrowMemExcept("Cannot store invalid memory buffer");
}
// Request a node instance
Node * node = Pull();
// Assign the specified memory
@ -245,9 +232,7 @@ private:
s_Nodes = new Node(s_Nodes);
// Validate the head node
if (!s_Nodes)
{
ThrowMemExcept("Unable to allocate memory nodes");
}
}
}
@ -256,10 +241,9 @@ private:
*/
static Node * Pull()
{
// Are there any nodes available?
if (!s_Nodes)
{
Make();
}
Make(); // Make some!
// Grab the head node
Node * node = s_Nodes;
// Promote the next node as the head
@ -275,9 +259,7 @@ private:
{
// See if the node is even valid
if (!node)
{
ThrowMemExcept("Attempting to push invalid node");
}
// Demote the current head node
node->mNext = s_Nodes;
// Promote as the head node
@ -286,7 +268,7 @@ private:
};
// ------------------------------------------------------------------------------------------------
MemCat::Node * MemCat::s_Nodes = NULL;
MemCat::Node * MemCat::s_Nodes = nullptr;
/* ------------------------------------------------------------------------------------------------
* Lightweight memory allocator to reduce the overhead of small allocations.
@ -294,8 +276,8 @@ MemCat::Node * MemCat::s_Nodes = NULL;
class Memory
{
// --------------------------------------------------------------------------------------------
friend class Buffer;
friend class MemRef;
friend class Buffer; // Allow the buffer type to access the memory categories.
friend class MemRef; // Allow the memory manager reference to create new instances.
private:
@ -316,7 +298,7 @@ private:
*/
~Memory()
{
for (MemCat::Node * node = MemCat::s_Nodes, * next = NULL; node; node = next)
for (MemCat::Node * node = MemCat::s_Nodes, * next = nullptr; node; node = next)
{
// Save the next node
next = node->mNext;
@ -324,13 +306,15 @@ private:
delete node;
}
// Explicitly set the head node to null
MemCat::s_Nodes = NULL;
MemCat::s_Nodes = nullptr;
}
private:
// --------------------------------------------------------------------------------------------
MemCat m_Small, m_Medium, m_Large;
MemCat m_Small; // Small memory allocations of <= 1024 bytes.
MemCat m_Medium; // Medium memory allocations of <= 4096 bytes.
MemCat m_Large; // Large memory allocations of <= 4096 bytes.
};
// ------------------------------------------------------------------------------------------------
@ -340,9 +324,7 @@ MemRef MemRef::s_Mem;
void MemRef::Grab()
{
if (m_Ptr)
{
++(*m_Ref);
}
}
// ------------------------------------------------------------------------------------------------
@ -352,8 +334,8 @@ void MemRef::Drop()
{
delete m_Ptr;
delete m_Ref;
m_Ptr = NULL;
m_Ref = NULL;
m_Ptr = nullptr;
m_Ref = nullptr;
}
}
@ -369,13 +351,9 @@ const MemRef & MemRef::Get()
return s_Mem;
}
// ------------------------------------------------------------------------------------------------
Buffer::Pointer Buffer::s_Ptr = NULL;
Buffer::SzType Buffer::s_Cap = 0;
// ------------------------------------------------------------------------------------------------
Buffer::Buffer(const Buffer & o)
: m_Ptr(NULL)
: m_Ptr(nullptr)
, m_Cap(0)
, m_Mem(o.m_Mem)
{
@ -389,10 +367,9 @@ Buffer::Buffer(const Buffer & o)
// ------------------------------------------------------------------------------------------------
Buffer::~Buffer()
{
// Do we have a buffer?
if (m_Ptr)
{
Release();
}
Release(); // Release it!
}
// ------------------------------------------------------------------------------------------------
@ -400,24 +377,25 @@ Buffer & Buffer::operator = (const Buffer & o)
{
if (m_Ptr != o.m_Ptr)
{
// Can we work in the current buffer?
if (m_Cap && o.m_Cap <= m_Cap)
{
// It's safe to copy the data
memcpy(m_Ptr, o.m_Ptr, m_Cap);
}
// Do we even have data to copy?
else if (!o.m_Cap)
{
// Do we have a buffer?
if (m_Ptr)
{
Release();
}
Release(); // Release it!
}
else
{
// Do we have a buffer?
if (m_Ptr)
{
Release();
}
Release(); // Release it!
// Request a larger buffer
Request(o.m_Cap);
// Now it's safe to copy the data
memcpy(m_Ptr, o.m_Ptr, o.m_Cap);
}
}
@ -433,67 +411,51 @@ void Buffer::Request(SzType n)
if (!m_Mem)
{
// Round up the size to a power of two number
n = (n & (n - 1)) ? NPow2(n) : n;
n = (n & (n - 1)) ? NextPow2(n) : n;
// Allocate the memory directly
m_Ptr = AllocMem(n);
}
// Find out in which category does this buffer reside
else if (n <= 1024)
{
m_Mem->m_Small.Grab(m_Ptr, n);
}
else if (n <= 4096)
{
m_Mem->m_Medium.Grab(m_Ptr, n);
}
else
{
m_Mem->m_Large.Grab(m_Ptr, n);
}
// If no errors occured then we can set the size
m_Cap= n;
// If no errors occurred then we can set the size
m_Cap = n;
}
// ------------------------------------------------------------------------------------------------
void Buffer::Release()
{
// TODO: Implement a limit on how much memory can actually be pooled.
// Is there a memory manager available?
if (!m_Mem)
{
// Deallocate the memory directly
free(m_Ptr);
}
free(m_Ptr); // Deallocate the memory directly
// Find out to which category does this buffer belong
else if (m_Cap <= 1024)
{
m_Mem->m_Small.Drop(m_Ptr, m_Cap);
}
else if (m_Cap <= 4096)
{
m_Mem->m_Medium.Drop(m_Ptr, m_Cap);
}
else
{
m_Mem->m_Large.Drop(m_Ptr, m_Cap);
}
// Explicitly reset the buffer
m_Ptr = NULL;
m_Ptr = nullptr;
m_Cap = 0;
}
// ------------------------------------------------------------------------------------------------
Buffer::SzType Buffer::Write(SzType pos, ConstPtr data, SzType size)
{
// Make sure the pos is not out of bounds
// Make sure the position is not out of bounds
if (pos > m_Cap || !data || !size)
{
return 0;
}
// See if the buffer size must be adjusted
else if ((pos + size) >= m_Cap)
{
// Backup current data
Buffer bkp = Adjust< Value >(pos + size);
// Allocate a larger memory chunk and backup old data
Buffer bkp(Adjust< Value >(NextPow2(pos + size)));
// Copy data back from the old buffer
memcpy(m_Ptr, bkp.m_Ptr, bkp.m_Cap);
}
@ -506,48 +468,44 @@ Buffer::SzType Buffer::Write(SzType pos, ConstPtr data, SzType size)
// ------------------------------------------------------------------------------------------------
Buffer::SzType Buffer::WriteF(SzType pos, const char * fmt, ...)
{
// Make sure the pos is not out of bounds
if (pos > m_Cap)
{
return 0;
}
// Initialize the arguments list
// Initialize the variable argument list
va_list args;
va_start(args, fmt);
// Initial attempt to write to the current buffer
// (if empty, it should tell us the necessary size)
int ret = vsnprintf(m_Ptr + pos, m_Cap - pos, fmt, args);
// Do we need a bigger buffer?
if ((pos + ret) >= m_Cap)
{
// Backup current data
Buffer bkp = Adjust< Value >(pos + ret);
// Copy data back from the old buffer
memcpy(m_Ptr, bkp.m_Ptr, bkp.m_Cap);
// Argument list was modified during the initial format
va_end(args);
va_start(args, fmt);
// Resume writting the requested information
ret = vsnprintf(m_Ptr + pos, m_Cap - pos, fmt, args);
}
// Finalize the arguments list
// Call the function that takes the variable argument list
SzType ret = WriteF(pos, fmt, args);
// Finalize the variable argument list
va_end(args);
// Return the size of the written data in bytes
return (ret < 0) ? 0 : (SzType)ret;
// Return the result
return ret;
}
// ------------------------------------------------------------------------------------------------
Buffer::SzType Buffer::WriteF(SzType pos, const char * fmt, va_list args)
{
// Make sure the pos is not out of bounds
// Make sure the position is not out of bounds
if (pos > m_Cap)
{
return 0;
}
// Backup the variable argument list
va_list args_cpy;
va_copy(args_cpy, args);
// Attempt to write to the current buffer
int ret = vsnprintf(m_Ptr + pos, m_Cap - pos, fmt, args);
// Return the size of the written data in bytes
return (ret < 0) ? 0 : (SzType)ret;
// (if empty, it should tell us the necessary size)
int ret = vsnprintf(m_Ptr + pos, m_Cap, fmt, args);
// Do we need a bigger buffer?
if ((pos + ret) >= m_Cap)
{
// Allocate a larger memory chunk and backup old data
Buffer bkp(Adjust< Value >(NextPow2(pos + ret)));
// Copy data back from the old buffer
memcpy(m_Ptr, bkp.m_Ptr, bkp.m_Cap);
// Retry writing the requested information
ret = vsnprintf(m_Ptr + pos, m_Cap, fmt, args_cpy);
}
// Return the value 0 if data could not be written
if (ret < 0)
return 0;
// Return the number of written characters
return static_cast< SzType >(ret);
}
} // Namespace:: SQMod
} // Namespace:: SqMod

View File

@ -2,7 +2,10 @@
#define _BASE_BUFFER_HPP_
// ------------------------------------------------------------------------------------------------
#include <assert.h>
#include <cassert>
// ------------------------------------------------------------------------------------------------
#include <utility>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
@ -64,6 +67,17 @@ public:
Grab();
}
/* --------------------------------------------------------------------------------------------
* Move constructor.
*/
MemRef(MemRef && o)
: m_Ptr(o.m_Ptr), m_Ref(o.m_Ref)
{
o.m_Ptr = nullptr;
o.m_Ref = nullptr;
}
/* --------------------------------------------------------------------------------------------
* Destructor.
*/
@ -87,6 +101,22 @@ public:
return *this;
}
/* --------------------------------------------------------------------------------------------
* Move assignment operator.
*/
MemRef & operator = (MemRef && o)
{
if (m_Ptr != o.m_Ptr)
{
Drop();
m_Ptr = o.m_Ptr;
m_Ref = o.m_Ref;
o.m_Ptr = nullptr;
o.m_Ref = nullptr;
}
return *this;
}
/* --------------------------------------------------------------------------------------------
* Perform an equality comparison between two memory managers.
*/
@ -116,7 +146,7 @@ public:
*/
Memory * operator -> () const
{
assert(m_Ptr != NULL);
assert(m_Ptr);
return m_Ptr;
}
@ -125,7 +155,7 @@ public:
*/
Memory & operator * () const
{
assert(m_Ptr != NULL);
assert(m_Ptr);
return *m_Ptr;
}
};
@ -134,43 +164,58 @@ public:
void ThrowMemExcept(const char * msg, ...);
/* ------------------------------------------------------------------------------------------------
* Reusable buffer memory for quick allocations.
* Reusable and re-scalable buffer memory for quick memory allocations.
*/
class Buffer
{
public:
// --------------------------------------------------------------------------------------------
typedef char Value; /* The type of value used to represent a byte. */
typedef char Value; // The type of value used to represent a byte.
// --------------------------------------------------------------------------------------------
typedef Value & Reference; /* A reference to the stored value type. */
typedef const Value & ConstRef; /* A const reference to the stored value type. */
typedef Value & Reference; // A reference to the stored value type.
typedef const Value & ConstRef; // A const reference to the stored value type.
// --------------------------------------------------------------------------------------------
typedef Value * Pointer; /* A pointer to the stored value type. */
typedef const Value * ConstPtr; /* A const pointer to the stored value type. */
typedef Value * Pointer; // A pointer to the stored value type.
typedef const Value * ConstPtr; // A const pointer to the stored value type.
// --------------------------------------------------------------------------------------------
typedef unsigned int SzType; /* The type used to represent size in general. */
typedef unsigned int SzType; // The type used to represent size in general.
private:
/* --------------------------------------------------------------------------------------------
* Construct and take ownership of the specified buffer.
*/
Buffer(Pointer & ptr, SzType & cap, const MemRef & mem)
: m_Ptr(ptr)
, m_Cap(cap)
, m_Mem(mem)
{
ptr = nullptr;
cap = 0;
}
public:
/* --------------------------------------------------------------------------------------------
* Default constructor (null). Not null of a previous buffer was marked as movable.
*/
Buffer()
: m_Ptr(s_Ptr)
, m_Cap(s_Cap)
: m_Ptr(nullptr)
, m_Cap(0)
, m_Mem(MemRef::Get())
{
s_Ptr = NULL;
s_Cap = 0;
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Explicit size constructor.
*/
Buffer(SzType n)
: m_Ptr(NULL)
: m_Ptr(nullptr)
, m_Cap(0)
, m_Mem(MemRef::Get())
{
@ -182,6 +227,15 @@ public:
*/
Buffer(const Buffer & o);
/* --------------------------------------------------------------------------------------------
* Move constructor.
*/
Buffer(Buffer && o)
: m_Ptr(o.m_Ptr), m_Cap(o.m_Cap), m_Mem(o.m_Mem)
{
o.m_Ptr = nullptr;
}
/* --------------------------------------------------------------------------------------------
* Destructor.
*/
@ -192,6 +246,23 @@ public:
*/
Buffer & operator = (const Buffer & o);
/* --------------------------------------------------------------------------------------------
* Copy assignment operator.
*/
Buffer & operator = (Buffer && o)
{
if (m_Ptr != o.m_Ptr)
{
if (m_Ptr)
Release();
m_Ptr = o.m_Ptr;
m_Cap = o.m_Cap;
m_Mem = o.m_Mem;
o.m_Ptr = nullptr;
}
return *this;
}
/* --------------------------------------------------------------------------------------------
* Equality comparison operator.
*/
@ -251,7 +322,7 @@ public:
/* --------------------------------------------------------------------------------------------
* Retrieve the internal buffer casted as a different type.
*/
template < typename T > T * Get()
template < typename T = Value> T * Get()
{
return reinterpret_cast< T * >(m_Ptr);
}
@ -259,7 +330,7 @@ public:
/* --------------------------------------------------------------------------------------------
* Retrieve the internal buffer casted as a different type.
*/
template < typename T > const T * Get() const
template < typename T = Value> const T * Get() const
{
return reinterpret_cast< const T * >(m_Ptr);
}
@ -267,7 +338,7 @@ public:
/* --------------------------------------------------------------------------------------------
* Retrieve the a certain element.
*/
template < typename T > T & At(SzType n)
template < typename T = Value> T & At(SzType n)
{
assert(n < m_Cap);
return reinterpret_cast< T * >(m_Ptr)[n];
@ -276,7 +347,7 @@ public:
/* --------------------------------------------------------------------------------------------
* Retrieve the a certain element.
*/
template < typename T > const T & At(SzType n) const
template < typename T = Value> const T & At(SzType n) const
{
assert(n < m_Cap);
return reinterpret_cast< const T * >(m_Ptr)[n];
@ -285,7 +356,7 @@ public:
/* --------------------------------------------------------------------------------------------
* Retrieve the internal buffer casted as a different type.
*/
template < typename T > T * Begin()
template < typename T = Value> T * Begin()
{
return reinterpret_cast< T * >(m_Ptr);
}
@ -293,7 +364,7 @@ public:
/* --------------------------------------------------------------------------------------------
* Retrieve the internal buffer casted as a different type.
*/
template < typename T > const T * Begin() const
template < typename T = Value> const T * Begin() const
{
return reinterpret_cast< const T * >(m_Ptr);
}
@ -301,7 +372,7 @@ public:
/* --------------------------------------------------------------------------------------------
* Retrieve the internal buffer casted as a different type.
*/
template < typename T > T * End()
template < typename T = Value> T * End()
{
return reinterpret_cast< T * >(m_Ptr) + (m_Cap / sizeof(T));
}
@ -309,7 +380,7 @@ public:
/* --------------------------------------------------------------------------------------------
* Retrieve the internal buffer casted as a different type.
*/
template < typename T > const T * End() const
template < typename T = Value> const T * End() const
{
return reinterpret_cast< const T * >(m_Ptr) + (m_Cap / sizeof(T));
}
@ -333,7 +404,7 @@ public:
/* --------------------------------------------------------------------------------------------
* Retrieve maximum elements it can hold for a certain type.
*/
template < typename T > static SzType Max()
template < typename T = Value> static SzType Max()
{
return (0xFFFFFFFF / sizeof(T));
}
@ -341,7 +412,7 @@ public:
/* --------------------------------------------------------------------------------------------
* Retrieve the current buffer capacity in element count.
*/
template < typename T > SzType Size() const
template < typename T = Value> SzType Size() const
{
return (m_Cap / sizeof(T));
}
@ -357,32 +428,28 @@ public:
/* --------------------------------------------------------------------------------------------
* Makes sure there is enough capacity to hold the specified element count.
*/
template < typename T > Buffer Adjust(SzType n)
template < typename T = Value> Buffer Adjust(SzType n)
{
// Do we meet the minimum size?
if (n < 8)
{
n = 8;
}
n = 8; // Adjust to minimum size
// See if the requested capacity doesn't exceed the limit
if (n > Max< T >())
{
ThrowMemExcept("Requested buffer of (%u) elements exceeds the (%u) limit", n, Max< T >());
}
// Is there an existing buffer?
else if (n && !m_Cap)
{
// Request the memory
Request(n * sizeof(T));
}
Request(n * sizeof(T)); // Request the memory
// Should the size be increased?
else if (n > m_Cap)
{
// Backup the current memory
Move();
Buffer bkp(m_Ptr, m_Cap, m_Mem);
// Request the memory
Request(n * sizeof(T));
// Return the backup
return std::move(bkp);
}
// Return an empty buffer or the backup (if any)
// Return an empty buffer
return Buffer();
}
@ -392,9 +459,7 @@ public:
void Reset()
{
if (m_Ptr)
{
Release();
}
}
/* --------------------------------------------------------------------------------------------
@ -437,17 +502,6 @@ protected:
*/
void Release();
/* --------------------------------------------------------------------------------------------
* Moves the internal buffer to the global members to be taken over by the next instance.
*/
void Move()
{
s_Ptr = m_Ptr;
s_Cap = m_Cap;
m_Ptr = NULL;
m_Cap = 0;
}
private:
// --------------------------------------------------------------------------------------------
@ -456,10 +510,6 @@ private:
// --------------------------------------------------------------------------------------------
MemRef m_Mem;
// --------------------------------------------------------------------------------------------
static Pointer s_Ptr; /* Pointer to a moved memory buffer. */
static SzType s_Cap; /* The total size of the moved buffer. */
};
} // Namespace:: SqMod

View File

@ -14,6 +14,14 @@ const Circle Circle::MAX = Circle(NumLimit< Circle::Value >::Max);
// ------------------------------------------------------------------------------------------------
SQChar Circle::Delim = ',';
// ------------------------------------------------------------------------------------------------
SQInteger Circle::Typename(HSQUIRRELVM vm)
{
static SQChar name[] = _SC("Circle");
sq_pushstring(vm, name, sizeof(name));
return 1;
}
// ------------------------------------------------------------------------------------------------
Circle::Circle()
: pos(0.0, 0.0), rad(0.0)
@ -42,27 +50,6 @@ Circle::Circle(Value xv, Value yv, Value rv)
/* ... */
}
// ------------------------------------------------------------------------------------------------
Circle::Circle(const Circle & o)
: pos(o.pos), rad(o.rad)
{
}
// ------------------------------------------------------------------------------------------------
Circle::~Circle()
{
/* ... */
}
// ------------------------------------------------------------------------------------------------
Circle & Circle::operator = (const Circle & o)
{
pos = o.pos;
rad = o.rad;
return *this;
}
// ------------------------------------------------------------------------------------------------
Circle & Circle::operator = (Value r)
{
@ -341,7 +328,7 @@ Int32 Circle::Cmp(const Circle & o) const
// ------------------------------------------------------------------------------------------------
CSStr Circle::ToString() const
{
return ToStringF("%f,%f,%f", pos.x, pos.y, rad);
return ToStrF("%f,%f,%f", pos.x, pos.y, rad);
}
// ------------------------------------------------------------------------------------------------
@ -395,35 +382,28 @@ void Circle::Generate()
void Circle::Generate(Value min, Value max, bool r)
{
if (EpsLt(max, min))
{
SqThrow("max value is lower than min value");
}
SqThrowF("max value is lower than min value");
else if (r)
{
rad = GetRandomFloat32(min, max);
}
else
{
pos.Generate(min, max);
}
}
void Circle::Generate(Value xmin, Value xmax, Value ymin, Value ymax)
{
if (EpsLt(xmax, xmin) || EpsLt(ymax, ymin))
SqThrowF("max value is lower than min value");
pos.Generate(xmin, xmax, ymin, ymax);
}
void Circle::Generate(Value xmin, Value xmax, Value ymin, Value ymax, Value rmin, Value rmax)
{
if (EpsLt(rmax, rmin))
{
SqThrow("max value is lower than min value");
}
else
{
pos.Generate(xmin, xmax, ymin, ymax);
rad = GetRandomFloat32(rmin, rmax);
}
if (EpsLt(xmax, xmin) || EpsLt(ymax, ymin) || EpsLt(rmax, rmin))
SqThrowF("max value is lower than min value");
pos.Generate(xmin, xmax, ymin, ymax);
rad = GetRandomFloat32(rmin, rmax);
}
// ------------------------------------------------------------------------------------------------
@ -452,6 +432,7 @@ void Register_Circle(HSQUIRRELVM vm)
.Prop(_SC("abs"), &Circle::Abs)
/* Core Metamethods */
.Func(_SC("_tostring"), &Circle::ToString)
.SquirrelFunc(_SC("_typename"), &Circle::Typename)
.Func(_SC("_cmp"), &Circle::Cmp)
/* Metamethods */
.Func<Circle (Circle::*)(const Circle &) const>(_SC("_add"), &Circle::operator +)

View File

@ -9,355 +9,370 @@
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
*
* Class used to represent a two-dimensional circle.
*/
struct Circle
{
/* --------------------------------------------------------------------------------------------
* ...
* The type of value used by components of type.
*/
typedef float Value;
/* --------------------------------------------------------------------------------------------
* ...
* Helper instances for common values mostly used as return types or comparison.
*/
static const Circle NIL;
static const Circle MIN;
static const Circle MAX;
/* --------------------------------------------------------------------------------------------
* ...
* The delimiter character to be used when extracting values from strings.
*/
static SQChar Delim;
/* --------------------------------------------------------------------------------------------
* ...
* The position and radius components of this type.
*/
Vector2 pos;
Value rad;
/* --------------------------------------------------------------------------------------------
*
* Default constructor.
*/
Circle();
/* --------------------------------------------------------------------------------------------
* ...
* Construct a circle at position 0,0 using the specified radius.
*/
Circle(Value rv);
/* --------------------------------------------------------------------------------------------
* ...
* Construct a circle at the specified position using the specified radius.
*/
Circle(const Vector2 & pv, Value rv);
/* --------------------------------------------------------------------------------------------
* ...
* Construct a circle at the specified position using the specified radius.
*/
Circle(Value xv, Value yv, Value rv);
/* --------------------------------------------------------------------------------------------
*
* Copy constructor.
*/
Circle(const Circle & o);
Circle(const Circle & o) = default;
/* --------------------------------------------------------------------------------------------
*
* Move constructor.
*/
~Circle();
Circle(Circle && o) = default;
/* --------------------------------------------------------------------------------------------
*
* Destructor.
*/
Circle & operator = (const Circle & o);
~Circle() = default;
/* --------------------------------------------------------------------------------------------
* ...
* Copy assignment operator.
*/
Circle & operator = (const Circle & o) = default;
/* --------------------------------------------------------------------------------------------
* Move assignment operator.
*/
Circle & operator = (Circle && o) = default;
/* --------------------------------------------------------------------------------------------
* Radius assignment operator.
*/
Circle & operator = (Value r);
/* --------------------------------------------------------------------------------------------
* ...
* Position assignment operator.
*/
Circle & operator = (const Vector2 & p);
/* --------------------------------------------------------------------------------------------
* ...
* Addition assignment operator.
*/
Circle & operator += (const Circle & c);
/* --------------------------------------------------------------------------------------------
* ...
* Subtraction assignment operator.
*/
Circle & operator -= (const Circle & c);
/* --------------------------------------------------------------------------------------------
* ...
* Multiplication assignment operator.
*/
Circle & operator *= (const Circle & c);
/* --------------------------------------------------------------------------------------------
* ...
* Division assignment operator.
*/
Circle & operator /= (const Circle & c);
/* --------------------------------------------------------------------------------------------
* ...
* Modulo assignment operator.
*/
Circle & operator %= (const Circle & c);
/* --------------------------------------------------------------------------------------------
* ...
* Radius addition assignment operator.
*/
Circle & operator += (Value r);
/* --------------------------------------------------------------------------------------------
* ...
* Radius subtraction assignment operator.
*/
Circle & operator -= (Value r);
/* --------------------------------------------------------------------------------------------
* ...
* Radius multiplication assignment operator.
*/
Circle & operator *= (Value r);
/* --------------------------------------------------------------------------------------------
* ...
* Radius division assignment operator.
*/
Circle & operator /= (Value r);
/* --------------------------------------------------------------------------------------------
* ...
* Radius modulo assignment operator.
*/
Circle & operator %= (Value r);
/* --------------------------------------------------------------------------------------------
* ...
* Position addition assignment operator.
*/
Circle & operator += (const Vector2 & p);
/* --------------------------------------------------------------------------------------------
* ...
* Position subtraction assignment operator.
*/
Circle & operator -= (const Vector2 & p);
/* --------------------------------------------------------------------------------------------
* ...
* Position multiplication assignment operator.
*/
Circle & operator *= (const Vector2 & p);
/* --------------------------------------------------------------------------------------------
* ...
* Position division assignment operator.
*/
Circle & operator /= (const Vector2 & p);
/* --------------------------------------------------------------------------------------------
* ...
* Position modulo assignment operator.
*/
Circle & operator %= (const Vector2 & p);
/* --------------------------------------------------------------------------------------------
* ...
* Pre-increment operator.
*/
Circle & operator ++ ();
/* --------------------------------------------------------------------------------------------
* ...
* Pre-decrement operator.
*/
Circle & operator -- ();
/* --------------------------------------------------------------------------------------------
* ...
* Post-increment operator.
*/
Circle operator ++ (int);
/* --------------------------------------------------------------------------------------------
* ...
* Post-decrement operator.
*/
Circle operator -- (int);
/* --------------------------------------------------------------------------------------------
* ...
* Addition operator.
*/
Circle operator + (const Circle & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Subtraction operator.
*/
Circle operator - (const Circle & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Multiplication operator.
*/
Circle operator * (const Circle & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Division operator.
*/
Circle operator / (const Circle & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Modulo operator.
*/
Circle operator % (const Circle & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Radius addition operator.
*/
Circle operator + (Value r) const;
/* --------------------------------------------------------------------------------------------
* ...
* Radius subtraction operator.
*/
Circle operator - (Value r) const;
/* --------------------------------------------------------------------------------------------
* ...
* Radius multiplication operator.
*/
Circle operator * (Value r) const;
/* --------------------------------------------------------------------------------------------
* ...
* Radius division operator.
*/
Circle operator / (Value r) const;
/* --------------------------------------------------------------------------------------------
* ...
* Radius modulo operator.
*/
Circle operator % (Value r) const;
/* --------------------------------------------------------------------------------------------
* ...
* Position addition operator.
*/
Circle operator + (const Vector2 & p) const;
/* --------------------------------------------------------------------------------------------
* ...
* Position subtraction operator.
*/
Circle operator - (const Vector2 & p) const;
/* --------------------------------------------------------------------------------------------
* ...
* Position multiplication operator.
*/
Circle operator * (const Vector2 & p) const;
/* --------------------------------------------------------------------------------------------
* ...
* Position division operator.
*/
Circle operator / (const Vector2 & p) const;
/* --------------------------------------------------------------------------------------------
* ...
* Position modulo operator.
*/
Circle operator % (const Vector2 & p) const;
/* --------------------------------------------------------------------------------------------
* ...
* Unary plus operator.
*/
Circle operator + () const;
/* --------------------------------------------------------------------------------------------
* ...
* Unary minus operator.
*/
Circle operator - () const;
/* --------------------------------------------------------------------------------------------
* ...
* Equality comparison operator.
*/
bool operator == (const Circle & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Inequality comparison operator.
*/
bool operator != (const Circle & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Less than comparison operator.
*/
bool operator < (const Circle & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Greater than comparison operator.
*/
bool operator > (const Circle & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Less than or equal comparison operator.
*/
bool operator <= (const Circle & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Greater than or equal comparison operator.
*/
bool operator >= (const Circle & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Used by the script engine to compare two instances of this type.
*/
Int32 Cmp(const Circle & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Used by the script engine to convert an instance of this type to a string.
*/
CSStr ToString() const;
/* --------------------------------------------------------------------------------------------
* ...
* Used by the script engine to retrieve the name from instances of this type.
*/
static SQInteger Typename(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Set the specified radius.
*/
void Set(Value nr);
/* --------------------------------------------------------------------------------------------
* ...
* Copy the circle from another instance of this type.
*/
void Set(const Circle & nc);
/* --------------------------------------------------------------------------------------------
* ...
* Set the position from the specified position.
*/
void Set(const Vector2 & np);
/* --------------------------------------------------------------------------------------------
* ...
* Set the specified position and radius.
*/
void Set(const Vector2 & np, Value nr);
/* --------------------------------------------------------------------------------------------
* ...
* Set the specified position.
*/
void Set(Value nx, Value ny);
/* --------------------------------------------------------------------------------------------
* ...
* Set the specified position and radius.
*/
void Set(Value nx, Value ny, Value nr);
/* --------------------------------------------------------------------------------------------
* ...
* Set the values extracted from the specified string using the specified delimiter.
*/
void Set(CSStr values, SQChar delim);
/* --------------------------------------------------------------------------------------------
* ...
* Generate a randomly sized and positioned circle.
*/
void Generate();
/* --------------------------------------------------------------------------------------------
* ...
* Generate a randomly sized or positioned circle within the specified bounds.
*/
void Generate(Value min, Value max, bool r);
/* --------------------------------------------------------------------------------------------
* ...
* Generate a randomly positioned circle within the specified bounds.
*/
void Generate(Value xmin, Value xmax, Value ymin, Value ymax);
/* --------------------------------------------------------------------------------------------
* ...
* Generate a randomly sized and positioned circle within the specified bounds.
*/
void Generate(Value xmin, Value xmax, Value ymin, Value ymax, Value rmin, Value rmax);
/* --------------------------------------------------------------------------------------------
* ...
* Clear the component values to default.
*/
void Clear()
{
@ -365,7 +380,7 @@ struct Circle
}
/* --------------------------------------------------------------------------------------------
* ...
* Retrieve a new instance of this type with absolute component values.
*/
Circle Abs() const;
};

View File

@ -15,6 +15,14 @@ const Color3 Color3::MAX = Color3(NumLimit< Color3::Value >::Max);
// ------------------------------------------------------------------------------------------------
SQChar Color3::Delim = ',';
// ------------------------------------------------------------------------------------------------
SQInteger Color3::Typename(HSQUIRRELVM vm)
{
static SQChar name[] = _SC("Color3");
sq_pushstring(vm, name, sizeof(name));
return 1;
}
// ------------------------------------------------------------------------------------------------
Color3::Color3()
: r(0), g(0), b(0)
@ -36,28 +44,6 @@ Color3::Color3(Value rv, Value gv, Value bv)
/* ... */
}
// ------------------------------------------------------------------------------------------------
Color3::Color3(const Color3 & o)
: r(o.r), g(o.g), b(o.b)
{
/* ... */
}
// ------------------------------------------------------------------------------------------------
Color3::~Color3()
{
/* ... */
}
// ------------------------------------------------------------------------------------------------
Color3 & Color3::operator = (const Color3 & o)
{
r = o.r;
g = o.g;
b = o.b;
return *this;
}
// ------------------------------------------------------------------------------------------------
Color3 & Color3::operator = (Value s)
{
@ -449,7 +435,7 @@ Int32 Color3::Cmp(const Color3 & o) const
// ------------------------------------------------------------------------------------------------
CSStr Color3::ToString() const
{
return ToStringF("%u,%u,%u", r, g, b);
return ToStrF("%u,%u,%u", r, g, b);
}
// ------------------------------------------------------------------------------------------------
@ -502,9 +488,9 @@ Uint32 Color3::GetRGB() const
void Color3::SetRGB(Uint32 p)
{
r = Value((p >> 16) & 0xFF);
g = Value((p >> 8) & 0xFF);
b = Value((p) & 0xFF);
r = static_cast< Value >((p >> 16) & 0xFF);
g = static_cast< Value >((p >> 8) & 0xFF);
b = static_cast< Value >((p) & 0xFF);
}
// ------------------------------------------------------------------------------------------------
@ -515,9 +501,9 @@ Uint32 Color3::GetRGBA() const
void Color3::SetRGBA(Uint32 p)
{
r = Value((p >> 24) & 0xFF);
g = Value((p >> 16) & 0xFF);
b = Value((p >> 8) & 0xFF);
r = static_cast< Value >((p >> 24) & 0xFF);
g = static_cast< Value >((p >> 16) & 0xFF);
b = static_cast< Value >((p >> 8) & 0xFF);
}
// ------------------------------------------------------------------------------------------------
@ -528,9 +514,9 @@ Uint32 Color3::GetARGB() const
void Color3::SetARGB(Uint32 p)
{
r = Value((p >> 16) & 0xFF);
g = Value((p >> 8) & 0xFF);
b = Value((p) & 0xFF);
r = static_cast< Value >((p >> 16) & 0xFF);
g = static_cast< Value >((p >> 8) & 0xFF);
b = static_cast< Value >((p) & 0xFF);
}
// ------------------------------------------------------------------------------------------------
@ -544,29 +530,21 @@ void Color3::Generate()
void Color3::Generate(Value min, Value max)
{
if (max < min)
{
SqThrow("max value is lower than min value");
}
else
{
r = GetRandomUint8(min, max);
g = GetRandomUint8(min, max);
b = GetRandomUint8(min, max);
}
SqThrowF("max value is lower than min value");
r = GetRandomUint8(min, max);
g = GetRandomUint8(min, max);
b = GetRandomUint8(min, max);
}
void Color3::Generate(Value rmin, Value rmax, Value gmin, Value gmax, Value bmin, Value bmax)
{
if (rmax < rmin || gmax < gmin || bmax < bmin)
{
SqThrow("max value is lower than min value");
}
else
{
r = GetRandomUint8(rmin, rmax);
g = GetRandomUint8(gmin, gmax);
b = GetRandomUint8(bmin, bmax);
}
SqThrowF("max value is lower than min value");
r = GetRandomUint8(rmin, rmax);
g = GetRandomUint8(gmin, gmax);
b = GetRandomUint8(bmin, bmax);
}
// ------------------------------------------------------------------------------------------------
@ -578,9 +556,9 @@ void Color3::Random()
// ------------------------------------------------------------------------------------------------
void Color3::Inverse()
{
r = Value(~r);
g = Value(~g);
b = Value(~b);
r = static_cast< Value >(~r);
g = static_cast< Value >(~g);
b = static_cast< Value >(~b);
}
// ================================================================================================
@ -606,6 +584,7 @@ void Register_Color3(HSQUIRRELVM vm)
.Prop(_SC("str"), &Color3::SetCol)
/* Core Metamethods */
.Func(_SC("_tostring"), &Color3::ToString)
.SquirrelFunc(_SC("_typename"), &Color3::Typename)
.Func(_SC("_cmp"), &Color3::Cmp)
/* Metamethods */
.Func<Color3 (Color3::*)(const Color3 &) const>(_SC("_add"), &Color3::operator +)

View File

@ -8,434 +8,449 @@
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
*
* Class used to represent an opaque RGB color.
*/
struct Color3
{
/* --------------------------------------------------------------------------------------------
* ...
* The type of value used by components of type.
*/
typedef unsigned char Value;
/* --------------------------------------------------------------------------------------------
* ...
* Helper instances for common values mostly used as return types or comparison.
*/
static const Color3 NIL;
static const Color3 MIN;
static const Color3 MAX;
/* --------------------------------------------------------------------------------------------
* ...
* The delimiter character to be used when extracting values from strings.
*/
static SQChar Delim;
/* --------------------------------------------------------------------------------------------
* ...
* The red, green and blue components of this type.
*/
Value r, g, b;
/* --------------------------------------------------------------------------------------------
*
* Default constructor.
*/
Color3();
/* --------------------------------------------------------------------------------------------
* ...
* Construct a color with all components with the same specified color.
*/
Color3(Value sv);
/* --------------------------------------------------------------------------------------------
* ...
* Construct with individually specified red, green and blue colors.
*/
Color3(Value rv, Value gv, Value bv);
/* --------------------------------------------------------------------------------------------
*
* Copy constructor.
*/
Color3(const Color3 & o);
Color3(const Color3 & o) = default;
/* --------------------------------------------------------------------------------------------
*
* Move constructor.
*/
~Color3();
Color3(Color3 && o) = default;
/* --------------------------------------------------------------------------------------------
*
* Destructor.
*/
Color3 & operator = (const Color3 & o);
~Color3() = default;
/* --------------------------------------------------------------------------------------------
* ...
* Copy assignment operator.
*/
Color3 & operator = (const Color3 & o) = default;
/* --------------------------------------------------------------------------------------------
* Copy assignment operator.
*/
Color3 & operator = (Color3 && o) = default;
/* --------------------------------------------------------------------------------------------
* Scalar value assignment operator.
*/
Color3 & operator = (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Named color assignment operator.
*/
Color3 & operator = (CSStr name);
/* --------------------------------------------------------------------------------------------
* ...
* Transparent color assignment operator.
*/
Color3 & operator = (const Color4 & c);
/* --------------------------------------------------------------------------------------------
* ...
* Addition assignment operator.
*/
Color3 & operator += (const Color3 & c);
/* --------------------------------------------------------------------------------------------
* ...
* Subtraction assignment operator.
*/
Color3 & operator -= (const Color3 & c);
/* --------------------------------------------------------------------------------------------
* ...
* Multiplication assignment operator.
*/
Color3 & operator *= (const Color3 & c);
/* --------------------------------------------------------------------------------------------
* ...
* Division assignment operator.
*/
Color3 & operator /= (const Color3 & c);
/* --------------------------------------------------------------------------------------------
* ...
* Modulo assignment operator.
*/
Color3 & operator %= (const Color3 & c);
/* --------------------------------------------------------------------------------------------
* ...
* Bitwise AND assignment operator.
*/
Color3 & operator &= (const Color3 & c);
/* --------------------------------------------------------------------------------------------
* ...
* Bitwise OR assignment operator.
*/
Color3 & operator |= (const Color3 & c);
/* --------------------------------------------------------------------------------------------
* ...
* Bitwise XOR assignment operator.
*/
Color3 & operator ^= (const Color3 & c);
/* --------------------------------------------------------------------------------------------
* ...
* Bitwise left shift assignment operator.
*/
Color3 & operator <<= (const Color3 & c);
/* --------------------------------------------------------------------------------------------
* ...
* Bitwise right shift assignment operator.
*/
Color3 & operator >>= (const Color3 & c);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value addition assignment operator.
*/
Color3 & operator += (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value subtraction assignment operator.
*/
Color3 & operator -= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value multiplication assignment operator.
*/
Color3 & operator *= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value division assignment operator.
*/
Color3 & operator /= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value modulo assignment operator.
*/
Color3 & operator %= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value bitwise AND assignment operator.
*/
Color3 & operator &= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value bitwise OR assignment operator.
*/
Color3 & operator |= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value bitwise XOR assignment operator.
*/
Color3 & operator ^= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value bitwise left shift assignment operator.
*/
Color3 & operator <<= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value bitwise right shift assignment operator.
*/
Color3 & operator >>= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Pre-increment operator.
*/
Color3 & operator ++ ();
/* --------------------------------------------------------------------------------------------
* ...
* Pre-decrement operator.
*/
Color3 & operator -- ();
/* --------------------------------------------------------------------------------------------
* ...
* Post-increment operator.
*/
Color3 operator ++ (int);
/* --------------------------------------------------------------------------------------------
* ...
* Post-decrement operator.
*/
Color3 operator -- (int);
/* --------------------------------------------------------------------------------------------
* ...
* Addition operator.
*/
Color3 operator + (const Color3 & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Subtraction operator.
*/
Color3 operator - (const Color3 & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Multiplication operator.
*/
Color3 operator * (const Color3 & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Division operator.
*/
Color3 operator / (const Color3 & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Modulo operator.
*/
Color3 operator % (const Color3 & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Bitwise AND operator.
*/
Color3 operator & (const Color3 & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Bitwise OR operator.
*/
Color3 operator | (const Color3 & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Bitwise XOR operator.
*/
Color3 operator ^ (const Color3 & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Bitwise shift left operator.
*/
Color3 operator << (const Color3 & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Bitwise shift right operator.
*/
Color3 operator >> (const Color3 & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value addition operator.
*/
Color3 operator + (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value subtraction operator.
*/
Color3 operator - (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value multiplication operator.
*/
Color3 operator * (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value division operator.
*/
Color3 operator / (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value modulo operator.
*/
Color3 operator % (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value bitwise AND operator.
*/
Color3 operator & (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value bitwise OR operator.
*/
Color3 operator | (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value bitwise XOR operator.
*/
Color3 operator ^ (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value bitwise shift left operator.
*/
Color3 operator << (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value bitwise shift right operator.
*/
Color3 operator >> (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Unary plus operator.
*/
Color3 operator + () const;
/* --------------------------------------------------------------------------------------------
* ...
* Unary minus operator.
*/
Color3 operator - () const;
/* --------------------------------------------------------------------------------------------
* ...
* Bitwise NOT operator.
*/
Color3 operator ~ () const;
/* --------------------------------------------------------------------------------------------
* ...
* Equality comparison operator.
*/
bool operator == (const Color3 & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Inequality comparison operator.
*/
bool operator != (const Color3 & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Less than comparison operator.
*/
bool operator < (const Color3 & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Greater than comparison operator.
*/
bool operator > (const Color3 & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Less than or equal comparison operator.
*/
bool operator <= (const Color3 & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Greater than or equal comparison operator.
*/
bool operator >= (const Color3 & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Implicit conversion to transparent color.
*/
operator Color4 () const;
/* --------------------------------------------------------------------------------------------
* ...
* Used by the script engine to compare two instances of this type.
*/
Int32 Cmp(const Color3 & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Used by the script engine to convert an instance of this type to a string.
*/
CSStr ToString() const;
/* --------------------------------------------------------------------------------------------
* ...
* Used by the script engine to retrieve the name from instances of this type.
*/
static SQInteger Typename(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Set all components to the specified scalar value.
*/
void Set(Value ns);
/* --------------------------------------------------------------------------------------------
* ...
* Set all components to the specified values.
*/
void Set(Value nr, Value ng, Value nb);
/* --------------------------------------------------------------------------------------------
* ...
* Copy the values from another instance of this type.
*/
void Set(const Color3 & c);
/* --------------------------------------------------------------------------------------------
* ...
* Copy the values from an opaque color.
*/
void Set(const Color4 & c);
/* --------------------------------------------------------------------------------------------
* ...
* Set the values extracted from the specified string using the specified delimiter.
*/
void Set(CSStr str, SQChar delim);
/* --------------------------------------------------------------------------------------------
* ...
* Set the values from the identified color.
*/
void SetCol(CSStr name);
/* --------------------------------------------------------------------------------------------
* ...
* Get the component values packed inside an integer value.
*/
Uint32 GetRGB() const;
/* --------------------------------------------------------------------------------------------
* ...
* Set the component values wxtracted from an integer value.
*/
void SetRGB(Uint32 p);
/* --------------------------------------------------------------------------------------------
* ...
* Get the component values packed inside an integer value.
*/
Uint32 GetRGBA() const;
/* --------------------------------------------------------------------------------------------
* ...
* Set the component values wxtracted from an integer value.
*/
void SetRGBA(Uint32 p);
/* --------------------------------------------------------------------------------------------
* ...
* Get the component values packed inside an integer value.
*/
Uint32 GetARGB() const;
/* --------------------------------------------------------------------------------------------
* ...
* Set the component values wxtracted from an integer value.
*/
void SetARGB(Uint32 p);
/* --------------------------------------------------------------------------------------------
* ...
* Generate random values for all components of this instance.
*/
void Generate();
/* --------------------------------------------------------------------------------------------
* ...
* Generate random values for all components of this instance within the specified bounds.
*/
void Generate(Value min, Value max);
/* --------------------------------------------------------------------------------------------
* ...
* Generate random values for all components of this instance within the specified bounds.
*/
void Generate(Value rmin, Value rmax, Value gmin, Value gmax, Value bmin, Value bmax);
/* --------------------------------------------------------------------------------------------
* ...
* Clear the component values to default.
*/
void Clear()
{
@ -443,12 +458,12 @@ struct Color3
}
/* --------------------------------------------------------------------------------------------
* ...
* Set the component values to a randomly chosen color.
*/
void Random();
/* --------------------------------------------------------------------------------------------
* ...
* Inverse the color.
*/
void Inverse();
};

View File

@ -15,6 +15,14 @@ const Color4 Color4::MAX = Color4(NumLimit< Color4::Value >::Max);
// ------------------------------------------------------------------------------------------------
SQChar Color4::Delim = ',';
// ------------------------------------------------------------------------------------------------
SQInteger Color4::Typename(HSQUIRRELVM vm)
{
static SQChar name[] = _SC("Color4");
sq_pushstring(vm, name, sizeof(name));
return 1;
}
// ------------------------------------------------------------------------------------------------
Color4::Color4()
: r(0), g(0), b(0), a(0)
@ -24,7 +32,7 @@ Color4::Color4()
// ------------------------------------------------------------------------------------------------
Color4::Color4(Value sv)
: r(sv), g(sv), b(sv), a(sv)
: r(sv), g(sv), b(sv), a(0)
{
/* ... */
}
@ -43,29 +51,6 @@ Color4::Color4(Value rv, Value gv, Value bv, Value av)
/* ... */
}
// ------------------------------------------------------------------------------------------------
Color4::Color4(const Color4 & o)
: r(o.r), g(o.g), b(o.b), a(o.a)
{
/* ... */
}
// ------------------------------------------------------------------------------------------------
Color4::~Color4()
{
/* ... */
}
// ------------------------------------------------------------------------------------------------
Color4 & Color4::operator = (const Color4 & o)
{
r = o.r;
g = o.g;
b = o.b;
a = o.a;
return *this;
}
// ------------------------------------------------------------------------------------------------
Color4 & Color4::operator = (Value s)
{
@ -482,7 +467,7 @@ Int32 Color4::Cmp(const Color4 & o) const
// ------------------------------------------------------------------------------------------------
CSStr Color4::ToString() const
{
return ToStringF("%u,%u,%u,%u", r, g, b, a);
return ToStrF("%u,%u,%u,%u", r, g, b, a);
}
// ------------------------------------------------------------------------------------------------
@ -546,9 +531,9 @@ Uint32 Color4::GetRGB() const
void Color4::SetRGB(Uint32 p)
{
r = Value((p >> 16) & 0xFF);
g = Value((p >> 8) & 0xFF);
b = Value((p) & 0xFF);
r = static_cast< Value >((p >> 16) & 0xFF);
g = static_cast< Value >((p >> 8) & 0xFF);
b = static_cast< Value >((p) & 0xFF);
}
// ------------------------------------------------------------------------------------------------
@ -559,10 +544,10 @@ Uint32 Color4::GetRGBA() const
void Color4::SetRGBA(Uint32 p)
{
r = Value((p >> 24) & 0xFF);
g = Value((p >> 16) & 0xFF);
b = Value((p >> 8) & 0xFF);
a = Value((p) & 0xFF);
r = static_cast< Value >((p >> 24) & 0xFF);
g = static_cast< Value >((p >> 16) & 0xFF);
b = static_cast< Value >((p >> 8) & 0xFF);
a = static_cast< Value >((p) & 0xFF);
}
// ------------------------------------------------------------------------------------------------
@ -573,10 +558,10 @@ Uint32 Color4::GetARGB() const
void Color4::SetARGB(Uint32 p)
{
a = Value((p >> 24) & 0xFF);
r = Value((p >> 16) & 0xFF);
g = Value((p >> 8) & 0xFF);
b = Value((p) & 0xFF);
a = static_cast< Value >((p >> 24) & 0xFF);
r = static_cast< Value >((p >> 16) & 0xFF);
g = static_cast< Value >((p >> 8) & 0xFF);
b = static_cast< Value >((p) & 0xFF);
}
// ------------------------------------------------------------------------------------------------
@ -591,31 +576,23 @@ void Color4::Generate()
void Color4::Generate(Value min, Value max)
{
if (max < min)
{
SqThrow("max value is lower than min value");
}
else
{
r = GetRandomUint8(min, max);
g = GetRandomUint8(min, max);
b = GetRandomUint8(min, max);
a = GetRandomUint8(min, max);
}
SqThrowF("max value is lower than min value");
r = GetRandomUint8(min, max);
g = GetRandomUint8(min, max);
b = GetRandomUint8(min, max);
a = GetRandomUint8(min, max);
}
void Color4::Generate(Value rmin, Value rmax, Value gmin, Value gmax, Value bmin, Value bmax, Value amin, Value amax)
{
if (rmax < rmin || gmax < gmin || bmax < bmin || amax < amin)
{
SqThrow("max value is lower than min value");
}
else
{
r = GetRandomUint8(rmin, rmax);
g = GetRandomUint8(gmin, gmax);
b = GetRandomUint8(bmin, bmax);
a = GetRandomUint8(bmin, bmax);
}
SqThrowF("max value is lower than min value");
r = GetRandomUint8(rmin, rmax);
g = GetRandomUint8(gmin, gmax);
b = GetRandomUint8(bmin, bmax);
a = GetRandomUint8(bmin, bmax);
}
// ------------------------------------------------------------------------------------------------
@ -627,10 +604,10 @@ void Color4::Random()
// ------------------------------------------------------------------------------------------------
void Color4::Inverse()
{
r = Value(~r);
g = Value(~g);
b = Value(~b);
a = Value(~a);
r = static_cast< Value >(~r);
g = static_cast< Value >(~g);
b = static_cast< Value >(~b);
a = static_cast< Value >(~a);
}
// ================================================================================================
@ -658,6 +635,7 @@ void Register_Color4(HSQUIRRELVM vm)
.Prop(_SC("str"), &Color4::SetCol)
/* Core Metamethods */
.Func(_SC("_tostring"), &Color4::ToString)
.SquirrelFunc(_SC("_typename"), &Color4::Typename)
.Func(_SC("_cmp"), &Color4::Cmp)
/* Metamethods */
.Func<Color4 (Color4::*)(const Color4 &) const>(_SC("_add"), &Color4::operator +)

View File

@ -8,444 +8,459 @@
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
*
* Class used to represent a transparent RGBA color.
*/
struct Color4
{
/* --------------------------------------------------------------------------------------------
* ...
* The type of value used by components of type.
*/
typedef unsigned char Value;
/* --------------------------------------------------------------------------------------------
* ...
* Helper instances for common values mostly used as return types or comparison.
*/
static const Color4 NIL;
static const Color4 MIN;
static const Color4 MAX;
/* --------------------------------------------------------------------------------------------
* ...
* The delimiter character to be used when extracting values from strings.
*/
static SQChar Delim;
/* --------------------------------------------------------------------------------------------
* ...
* The red, green and blue components of this type.
*/
Value r, g, b, a;
/* --------------------------------------------------------------------------------------------
*
* Default constructor.
*/
Color4();
/* --------------------------------------------------------------------------------------------
* ...
* Construct a color with all components with the same specified color.
*/
Color4(Value sv);
/* --------------------------------------------------------------------------------------------
* ...
* Construct with individually specified red, green and blue colors.
*/
Color4(Value rv, Value gv, Value bv);
/* --------------------------------------------------------------------------------------------
* ...
* Construct with individually specified red, green, blue and alpha colors.
*/
Color4(Value rv, Value gv, Value bv, Value av);
/* --------------------------------------------------------------------------------------------
*
* Copy constructor.
*/
Color4(const Color4 & o);
Color4(const Color4 & o) = default;
/* --------------------------------------------------------------------------------------------
*
* Move constructor.
*/
~Color4();
Color4(Color4 && o) = default;
/* --------------------------------------------------------------------------------------------
*
* Destructor.
*/
Color4 & operator = (const Color4 & o);
~Color4() = default;
/* --------------------------------------------------------------------------------------------
* ...
* Copy assignment operator.
*/
Color4 & operator = (const Color4 & o) = default;
/* --------------------------------------------------------------------------------------------
* Move assignment operator.
*/
Color4 & operator = (Color4 && o) = default;
/* --------------------------------------------------------------------------------------------
* Scalar value assignment operator.
*/
Color4 & operator = (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Named color assignment operator.
*/
Color4 & operator = (CSStr name);
/* --------------------------------------------------------------------------------------------
* ...
* Opaque color assignment operator.
*/
Color4 & operator = (const Color3 & c);
/* --------------------------------------------------------------------------------------------
* ...
* Addition assignment operator.
*/
Color4 & operator += (const Color4 & c);
/* --------------------------------------------------------------------------------------------
* ...
* Subtraction assignment operator.
*/
Color4 & operator -= (const Color4 & c);
/* --------------------------------------------------------------------------------------------
* ...
* Multiplication assignment operator.
*/
Color4 & operator *= (const Color4 & c);
/* --------------------------------------------------------------------------------------------
* ...
* Division assignment operator.
*/
Color4 & operator /= (const Color4 & c);
/* --------------------------------------------------------------------------------------------
* ...
* Modulo assignment operator.
*/
Color4 & operator %= (const Color4 & c);
/* --------------------------------------------------------------------------------------------
* ...
* Bitwise AND assignment operator.
*/
Color4 & operator &= (const Color4 & c);
/* --------------------------------------------------------------------------------------------
* ...
* Bitwise OR assignment operator.
*/
Color4 & operator |= (const Color4 & c);
/* --------------------------------------------------------------------------------------------
* ...
* Bitwise XOR assignment operator.
*/
Color4 & operator ^= (const Color4 & c);
/* --------------------------------------------------------------------------------------------
* ...
* Bitwise left shift assignment operator.
*/
Color4 & operator <<= (const Color4 & c);
/* --------------------------------------------------------------------------------------------
* ...
* Bitwise right shift assignment operator.
*/
Color4 & operator >>= (const Color4 & c);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value addition assignment operator.
*/
Color4 & operator += (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value subtraction assignment operator.
*/
Color4 & operator -= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value multiplication assignment operator.
*/
Color4 & operator *= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value division assignment operator.
*/
Color4 & operator /= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value modulo assignment operator.
*/
Color4 & operator %= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value bitwise AND assignment operator.
*/
Color4 & operator &= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value bitwise OR assignment operator.
*/
Color4 & operator |= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value bitwise XOR assignment operator.
*/
Color4 & operator ^= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value bitwise left shift assignment operator.
*/
Color4 & operator <<= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value bitwise right shift assignment operator.
*/
Color4 & operator >>= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Pre-increment operator.
*/
Color4 & operator ++ ();
/* --------------------------------------------------------------------------------------------
* ...
* Pre-decrement operator.
*/
Color4 & operator -- ();
/* --------------------------------------------------------------------------------------------
* ...
* Post-increment operator.
*/
Color4 operator ++ (int);
/* --------------------------------------------------------------------------------------------
* ...
* Post-decrement operator.
*/
Color4 operator -- (int);
/* --------------------------------------------------------------------------------------------
* ...
* Addition operator.
*/
Color4 operator + (const Color4 & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Subtraction operator.
*/
Color4 operator - (const Color4 & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Multiplication operator.
*/
Color4 operator * (const Color4 & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Division operator.
*/
Color4 operator / (const Color4 & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Modulo operator.
*/
Color4 operator % (const Color4 & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Bitwise AND operator.
*/
Color4 operator & (const Color4 & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Bitwise OR operator.
*/
Color4 operator | (const Color4 & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Bitwise XOR operator.
*/
Color4 operator ^ (const Color4 & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Bitwise shift left operator.
*/
Color4 operator << (const Color4 & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Bitwise shift right operator.
*/
Color4 operator >> (const Color4 & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value addition operator.
*/
Color4 operator + (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value subtraction operator.
*/
Color4 operator - (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value multiplication operator.
*/
Color4 operator * (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value division operator.
*/
Color4 operator / (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value modulo operator.
*/
Color4 operator % (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value bitwise AND operator.
*/
Color4 operator & (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value bitwise OR operator.
*/
Color4 operator | (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value bitwise XOR operator.
*/
Color4 operator ^ (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value bitwise shift left operator.
*/
Color4 operator << (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value bitwise shift right operator.
*/
Color4 operator >> (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Unary plus operator.
*/
Color4 operator + () const;
/* --------------------------------------------------------------------------------------------
* ...
* Unary minus operator.
*/
Color4 operator - () const;
/* --------------------------------------------------------------------------------------------
* ...
* Bitwise NOT operator.
*/
Color4 operator ~ () const;
/* --------------------------------------------------------------------------------------------
* ...
* Equality comparison operator.
*/
bool operator == (const Color4 & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Inequality comparison operator.
*/
bool operator != (const Color4 & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Less than comparison operator.
*/
bool operator < (const Color4 & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Greater than comparison operator.
*/
bool operator > (const Color4 & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Less than or equal comparison operator.
*/
bool operator <= (const Color4 & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Greater than or equal comparison operator.
*/
bool operator >= (const Color4 & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Implicit conversion to opaque color.
*/
operator Color3 () const;
/* --------------------------------------------------------------------------------------------
* ...
* Used by the script engine to compare two instances of this type.
*/
Int32 Cmp(const Color4 & c) const;
/* --------------------------------------------------------------------------------------------
* ...
* Used by the script engine to convert an instance of this type to a string.
*/
CSStr ToString() const;
/* --------------------------------------------------------------------------------------------
* ...
* Used by the script engine to retrieve the name from instances of this type.
*/
static SQInteger Typename(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Set all components to the specified scalar value.
*/
void Set(Value ns);
/* --------------------------------------------------------------------------------------------
* ...
* Set all components to the specified values.
*/
void Set(Value nr, Value ng, Value nb);
/* --------------------------------------------------------------------------------------------
* ...
* Set all components to the specified values.
*/
void Set(Value nr, Value ng, Value nb, Value na);
/* --------------------------------------------------------------------------------------------
* ...
* Copy the values from another instance of this type.
*/
void Set(const Color4 & c);
/* --------------------------------------------------------------------------------------------
* ...
* Copy the values from an opaque color.
*/
void Set(const Color3 & c);
/* --------------------------------------------------------------------------------------------
* ...
* Set the values extracted from the specified string using the specified delimiter.
*/
void Set(CSStr name, SQChar delim);
/* --------------------------------------------------------------------------------------------
* ...
* Set the values from the identified color.
*/
void SetCol(CSStr name);
/* --------------------------------------------------------------------------------------------
* ...
* Get the component values packed inside an integer value.
*/
Uint32 GetRGB() const;
/* --------------------------------------------------------------------------------------------
* ...
* Set the component values wxtracted from an integer value.
*/
void SetRGB(Uint32 p);
/* --------------------------------------------------------------------------------------------
* ...
* Get the component values packed inside an integer value.
*/
Uint32 GetRGBA() const;
/* --------------------------------------------------------------------------------------------
* ...
* Set the component values wxtracted from an integer value.
*/
void SetRGBA(Uint32 p);
/* --------------------------------------------------------------------------------------------
* ...
* Get the component values packed inside an integer value.
*/
Uint32 GetARGB() const;
/* --------------------------------------------------------------------------------------------
* ...
* Set the component values wxtracted from an integer value.
*/
void SetARGB(Uint32 p);
/* --------------------------------------------------------------------------------------------
* ...
* Generate random values for all components of this instance.
*/
void Generate();
/* --------------------------------------------------------------------------------------------
* ...
* Generate random values for all components of this instance within the specified bounds.
*/
void Generate(Value min, Value max);
/* --------------------------------------------------------------------------------------------
* ...
* Generate random values for all components of this instance within the specified bounds.
*/
void Generate(Value rmin, Value rmax, Value gmin, Value gmax, Value bmin, Value bmax, Value amin, Value amax);
/* --------------------------------------------------------------------------------------------
* ...
* Clear the component values to default.
*/
void Clear()
{
@ -453,12 +468,12 @@ struct Color4
}
/* --------------------------------------------------------------------------------------------
* ...
* Set the component values to a randomly chosen color.
*/
void Random();
/* --------------------------------------------------------------------------------------------
* ...
* Inverse the color.
*/
void Inverse();
};

View File

@ -16,6 +16,14 @@ const Quaternion Quaternion::MAX = Quaternion(NumLimit< Quaternion::Value >::Max
// ------------------------------------------------------------------------------------------------
SQChar Quaternion::Delim = ',';
// ------------------------------------------------------------------------------------------------
SQInteger Quaternion::Typename(HSQUIRRELVM vm)
{
static SQChar name[] = _SC("Quaternion");
sq_pushstring(vm, name, sizeof(name));
return 1;
}
// ------------------------------------------------------------------------------------------------
Quaternion::Quaternion()
: x(0.0), y(0.0), z(0.0), w(0.0)
@ -44,29 +52,6 @@ Quaternion::Quaternion(Value xv, Value yv, Value zv, Value wv)
/* ... */
}
// ------------------------------------------------------------------------------------------------
Quaternion::Quaternion(const Quaternion & o)
: x(o.x), y(o.y), z(o.z), w(o.w)
{
/* ... */
}
// ------------------------------------------------------------------------------------------------
Quaternion::~Quaternion()
{
/* ... */
}
// ------------------------------------------------------------------------------------------------
Quaternion & Quaternion::operator = (const Quaternion & o)
{
x = o.x;
y = o.y;
z = o.z;
w = o.w;
return *this;
}
// ------------------------------------------------------------------------------------------------
Quaternion & Quaternion::operator = (Value s)
{
@ -338,7 +323,7 @@ Int32 Quaternion::Cmp(const Quaternion & o) const
// ------------------------------------------------------------------------------------------------
CSStr Quaternion::ToString() const
{
return ToStringF("%f,%f,%f,%f", x, y, z, w);
return ToStrF("%f,%f,%f,%f", x, y, z, w);
}
// ------------------------------------------------------------------------------------------------
@ -408,31 +393,23 @@ void Quaternion::Generate()
void Quaternion::Generate(Value min, Value max)
{
if (EpsLt(max, min))
{
SqThrow("max value is lower than min value");
}
else
{
x = GetRandomFloat32(min, max);
y = GetRandomFloat32(min, max);
z = GetRandomFloat32(min, max);
y = GetRandomFloat32(min, max);
}
SqThrowF("max value is lower than min value");
x = GetRandomFloat32(min, max);
y = GetRandomFloat32(min, max);
z = GetRandomFloat32(min, max);
y = GetRandomFloat32(min, max);
}
void Quaternion::Generate(Value xmin, Value xmax, Value ymin, Value ymax, Value zmin, Value zmax, Value wmin, Value wmax)
{
if (EpsLt(xmax, xmin) || EpsLt(ymax, ymin) || EpsLt(zmax, zmin) || EpsLt(wmax, wmin))
{
SqThrow("max value is lower than min value");
}
else
{
x = GetRandomFloat32(xmin, xmax);
y = GetRandomFloat32(ymin, ymax);
z = GetRandomFloat32(zmin, zmax);
y = GetRandomFloat32(ymin, ymax);
}
SqThrowF("max value is lower than min value");
x = GetRandomFloat32(xmin, xmax);
y = GetRandomFloat32(ymin, ymax);
z = GetRandomFloat32(zmin, zmax);
y = GetRandomFloat32(ymin, ymax);
}
// ------------------------------------------------------------------------------------------------
@ -463,6 +440,7 @@ void Register_Quaternion(HSQUIRRELVM vm)
.Prop(_SC("abs"), &Quaternion::Abs)
/* Core Metamethods */
.Func(_SC("_tostring"), &Quaternion::ToString)
.SquirrelFunc(_SC("_typename"), &Quaternion::Typename)
.Func(_SC("_cmp"), &Quaternion::Cmp)
/* Metamethods */
.Func<Quaternion (Quaternion::*)(const Quaternion &) const>(_SC("_add"), &Quaternion::operator +)

View File

@ -8,34 +8,34 @@
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
*
* Quaternion class for representing rotations.
*/
struct Quaternion
{
/* --------------------------------------------------------------------------------------------
* ...
* The type of value used by components of type.
*/
typedef float Value;
/* --------------------------------------------------------------------------------------------
* ...
* Helper instances for common values mostly used as return types or comparison.
*/
static const Quaternion NIL;
static const Quaternion MIN;
static const Quaternion MAX;
/* --------------------------------------------------------------------------------------------
* ...
* The delimiter character to be used when extracting values from strings.
*/
static SQChar Delim;
/* --------------------------------------------------------------------------------------------
* ...
* The x, y, z and w components of this type.
*/
Value x, y, z, w;
/* --------------------------------------------------------------------------------------------
*
* Default constructor.
*/
Quaternion();
@ -55,257 +55,272 @@ struct Quaternion
Quaternion(Value xv, Value yv, Value zv, Value wv);
/* --------------------------------------------------------------------------------------------
*
* Copy constructor.
*/
Quaternion(const Quaternion & o);
Quaternion(const Quaternion & o) = default;
/* --------------------------------------------------------------------------------------------
*
* Move constructor.
*/
~Quaternion();
Quaternion(Quaternion && o) = default;
/* --------------------------------------------------------------------------------------------
*
* Destructor.
*/
Quaternion & operator = (const Quaternion & o);
~Quaternion() = default;
/* --------------------------------------------------------------------------------------------
* ...
* Copy assignment operator.
*/
Quaternion & operator = (const Quaternion & o) = default;
/* --------------------------------------------------------------------------------------------
* Move assignment operator.
*/
Quaternion & operator = (Quaternion && o) = default;
/* --------------------------------------------------------------------------------------------
* Scalar value assignment operator.
*/
Quaternion & operator = (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Euler assignment operator.
*/
Quaternion & operator = (const Vector3 & q);
/* --------------------------------------------------------------------------------------------
* ...
* Four-dimensional vector assignment operator threated as a three-dimensional vector.
*/
Quaternion & operator = (const Vector4 & q);
/* --------------------------------------------------------------------------------------------
* ...
* Addition assignment operator.
*/
Quaternion & operator += (const Quaternion & q);
/* --------------------------------------------------------------------------------------------
* ...
* Subtraction assignment operator.
*/
Quaternion & operator -= (const Quaternion & q);
/* --------------------------------------------------------------------------------------------
* ...
* Multiplication assignment operator.
*/
Quaternion & operator *= (const Quaternion & q);
/* --------------------------------------------------------------------------------------------
* ...
* Division assignment operator.
*/
Quaternion & operator /= (const Quaternion & q);
/* --------------------------------------------------------------------------------------------
* ...
* Modulo assignment operator.
*/
Quaternion & operator %= (const Quaternion & q);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value addition assignment operator.
*/
Quaternion & operator += (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value subtraction assignment operator.
*/
Quaternion & operator -= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value multiplication assignment operator.
*/
Quaternion & operator *= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value division assignment operator.
*/
Quaternion & operator /= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value modulo assignment operator.
*/
Quaternion & operator %= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Pre-increment operator.
*/
Quaternion & operator ++ ();
/* --------------------------------------------------------------------------------------------
* ...
* Pre-decrement operator.
*/
Quaternion & operator -- ();
/* --------------------------------------------------------------------------------------------
* ...
* Post-increment operator.
*/
Quaternion operator ++ (int);
/* --------------------------------------------------------------------------------------------
* ...
* Post-decrement operator.
*/
Quaternion operator -- (int);
/* --------------------------------------------------------------------------------------------
* ...
* Addition operator.
*/
Quaternion operator + (const Quaternion & q) const;
/* --------------------------------------------------------------------------------------------
* ...
* Subtraction operator.
*/
Quaternion operator - (const Quaternion & q) const;
/* --------------------------------------------------------------------------------------------
* ...
* Multiplication operator.
*/
Quaternion operator * (const Quaternion & q) const;
/* --------------------------------------------------------------------------------------------
* ...
* Division operator.
*/
Quaternion operator / (const Quaternion & q) const;
/* --------------------------------------------------------------------------------------------
* ...
* Modulo operator.
*/
Quaternion operator % (const Quaternion & q) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value addition operator.
*/
Quaternion operator + (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value subtraction operator.
*/
Quaternion operator - (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value multiplication operator.
*/
Quaternion operator * (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value division operator.
*/
Quaternion operator / (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value modulo operator.
*/
Quaternion operator % (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Unary plus operator.
*/
Quaternion operator + () const;
/* --------------------------------------------------------------------------------------------
* ...
* Unary minus operator.
*/
Quaternion operator - () const;
/* --------------------------------------------------------------------------------------------
* ...
* Equality comparison operator.
*/
bool operator == (const Quaternion & q) const;
/* --------------------------------------------------------------------------------------------
* ...
* Inequality comparison operator.
*/
bool operator != (const Quaternion & q) const;
/* --------------------------------------------------------------------------------------------
* ...
* Less than comparison operator.
*/
bool operator < (const Quaternion & q) const;
/* --------------------------------------------------------------------------------------------
* ...
* Greater than comparison operator.
*/
bool operator > (const Quaternion & q) const;
/* --------------------------------------------------------------------------------------------
* ...
* Less than or equal comparison operator.
*/
bool operator <= (const Quaternion & q) const;
/* --------------------------------------------------------------------------------------------
* ...
* Greater than or equal comparison operator.
*/
bool operator >= (const Quaternion & q) const;
/* --------------------------------------------------------------------------------------------
* ...
* Used by the script engine to compare two instances of this type.
*/
Int32 Cmp(const Quaternion & q) const;
/* --------------------------------------------------------------------------------------------
* ...
* Used by the script engine to convert an instance of this type to a string.
*/
CSStr ToString() const;
/* --------------------------------------------------------------------------------------------
* ...
* Used by the script engine to retrieve the name from instances of this type.
*/
static SQInteger Typename(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Set all components to the specified scalar value.
*/
void Set(Value ns);
/* --------------------------------------------------------------------------------------------
* ...
* Set all components to the specified values.
*/
void Set(Value nx, Value ny, Value nz);
/* --------------------------------------------------------------------------------------------
* ...
* Set all components to the specified values.
*/
void Set(Value nx, Value ny, Value nz, Value nw);
/* --------------------------------------------------------------------------------------------
* ...
* Copy the values from another instance of this type.
*/
void Set(const Quaternion & q);
/* --------------------------------------------------------------------------------------------
* ...
* Copy the values from a three-dimensional vector as euler rotation.
*/
void Set(const Vector3 & v);
/* --------------------------------------------------------------------------------------------
* ...
* Copy the values from a four-dimensional vector.
*/
void Set(const Vector4 & v);
/* --------------------------------------------------------------------------------------------
* ...
* Set the values extracted from the specified string using the specified delimiter.
*/
void Set(CSStr values, SQChar delim);
/* --------------------------------------------------------------------------------------------
* ...
* Generate random values for all components of this instance.
*/
void Generate();
/* --------------------------------------------------------------------------------------------
* ...
* Generate random values for all components of this instance within the specified bounds.
*/
void Generate(Value min, Value max);
/* --------------------------------------------------------------------------------------------
* ...
* Generate random values for all components of this instance within the specified bounds.
*/
void Generate(Value xmin, Value xmax, Value ymin, Value ymax, Value zmin, Value zmax, Value wmin, Value wmax);
/* --------------------------------------------------------------------------------------------
* ...
* Clear the component values to default.
*/
void Clear()
{
@ -313,7 +328,7 @@ struct Quaternion
}
/* --------------------------------------------------------------------------------------------
* ...
* Retrieve a new instance of this type with absolute component values.
*/
Quaternion Abs() const;
};

View File

@ -35,6 +35,11 @@ PluginFuncs* _Func = NULL;
PluginCallbacks* _Clbk = NULL;
PluginInfo* _Info = NULL;
/* ------------------------------------------------------------------------------------------------
* Common buffer to reduce memory allocations. To be immediately copied uppon return!
*/
static SQChar g_Buffer[4096];
// ------------------------------------------------------------------------------------------------
const char NumLimit< char >::Min = CHAR_MIN;
const signed char NumLimit< signed char >::Min = SCHAR_MIN;
@ -99,30 +104,52 @@ bool SToB(CSStr str)
}
// ------------------------------------------------------------------------------------------------
CSStr ToStrF(CCStr fmt, ...)
void SqThrowF(CCStr fmt, ...)
{
static char buf[128];
// Initialize the argument list
va_list args;
va_start (args, fmt);
int ret = vsnprintf(buf, sizeof(buf), fmt, args);
if (ret < 0)
{
SqThrow("Failed to run the specified string format");
buf[0] = 0;
}
// Write the requested contents
if (snprintf(g_Buffer, sizeof(g_Buffer), fmt, args) < 0)
strcpy(g_Buffer, "Unknown error has occurred");
// Release the argument list
va_end(args);
return buf;
// Throw the exception with the resulted message
throw Sqrat::Exception(g_Buffer);
}
// ------------------------------------------------------------------------------------------------
CSStr ToStrF(CCStr fmt, ...)
{
// Prepare the arguments list
va_list args;
va_start (args, fmt);
// Attempt to run the specified format
int ret = vsnprintf(g_Buffer, sizeof(g_Buffer), fmt, args);
// See if the format function failed
if (ret < 0)
SqThrowF("Failed to run the specified string format");
// Finalized the arguments list
va_end(args);
// Return the resulted string
return g_Buffer;
}
// ------------------------------------------------------------------------------------------------
CSStr ToStringF(CCStr fmt, ...)
{
// Acquire a moderately sized buffer
Buffer b(128);
// Prepare the arguments list
va_list args;
va_start (args, fmt);
// Attempt to run the specified format
if (b.WriteF(0, fmt, args) == 0)
b.At< SQChar >(0) = 0;
// Make sure the string is null terminated
b.At(0) = 0;
// Finalized the arguments list
va_end(args);
// Return the resulted string
return b.Get< SQChar >();
}
@ -280,22 +307,17 @@ const Color3 & GetRandomColor()
// ------------------------------------------------------------------------------------------------
Color3 GetColor(CSStr name)
{
Uint32 len = 0;
// See if we actually have something to search for
if(!name || (len = (Uint32)strlen(name)) <= 0)
{
SqThrow("Cannot extract values from an empty string");
return Color3::NIL;
}
if(!name || *name == 0)
SqThrowF("Cannot extract values from an empty string");
// Clone the string into an editable version
CCStr str = StrJustAlphaNum(name);
str = StrToLowercase(str);
// See if we still have a valid name after the cleanup
if((len = (Uint32)strlen(name)) <= 0)
{
SqThrow("Cannot extract values from an invalid string: %s", name);
return Color3::NIL;
}
if(!str || *str == 0)
SqThrowF("Cannot extract values from an invalid string: %s", name);
// Calculate the name length
const Uint32 len = strlen(str);
// Get the most significant characters used to identify a weapon
SQChar a = str[0], b = 0, c = 0, d = str[len-1];
// Look for deeper specifiers
@ -885,19 +907,17 @@ Color3 GetColor(CSStr name)
}
// ------------------------------------------------------------------------------------------------
AABB GetAABB(CSStr str, SQChar delim)
const AABB & GetAABB(CSStr str, SQChar delim)
{
static SQChar fs[] = _SC(" %f , %f , %f , %f , %f , %f ");
static AABB box;
if (!str || *str == 0)
SqThrowF("Cannot extract values from an empty string");
box.Clear();
if (strlen(str) <= 0)
{
SqThrow("Cannot extract values from an empty string");
return box;
}
else if (delim != AABB::Delim)
if (delim != AABB::Delim)
{
fs[4] = delim;
fs[9] = delim;
@ -920,19 +940,17 @@ AABB GetAABB(CSStr str, SQChar delim)
}
// ------------------------------------------------------------------------------------------------
Circle GetCircle(CSStr str, SQChar delim)
const Circle & GetCircle(CSStr str, SQChar delim)
{
static SQChar fs[] = _SC(" %f , %f , %f ");
static Circle circle;
//circle.Clear();
if (!str || *str == 0)
SqThrowF("Cannot extract values from an empty string");
if (strlen(str) <= 0)
{
SqThrow("Cannot extract values from an empty string");
return circle;
}
else if (delim != Circle::Delim)
circle.Clear();
if (delim != Circle::Delim)
{
fs[4] = delim;
fs[9] = delim;
@ -949,16 +967,15 @@ Circle GetCircle(CSStr str, SQChar delim)
}
// ------------------------------------------------------------------------------------------------
Color3 GetColor3(CSStr str, SQChar delim)
const Color3 & GetColor3(CSStr str, SQChar delim)
{
static SQChar fs[] = _SC(" %u , %u , %u ");
static Color3 col;
Uint32 r = 0, g = 0, b = 0;
if (strlen(str) <= 0)
{
SqThrow("Cannot extract values from an empty string");
return Color3();
}
if (!str || *str == 0)
SqThrowF("Cannot extract values from an empty string");
else if (delim != Color3::Delim)
{
fs[4] = delim;
@ -972,19 +989,23 @@ Color3 GetColor3(CSStr str, SQChar delim)
sscanf(str, &fs[0], &r, &g, &b);
return Color3(Color3::Value(r), Color3::Value(g), Color3::Value(b));
col.r = static_cast< Color4::Value >(r);
col.g = static_cast< Color4::Value >(g);
col.b = static_cast< Color4::Value >(b);
return col;
}
Color4 GetColor4(CSStr str, SQChar delim)
// ------------------------------------------------------------------------------------------------
const Color4 & GetColor4(CSStr str, SQChar delim)
{
static SQChar fs[] = _SC(" %u , %u , %u , %u ");
static Color4 col;
Uint32 r = 0, g = 0, b = 0, a = 0;
if (strlen(str) <= 0)
{
SqThrow("Cannot extract values from an empty string");
return Color4();
}
if (!str || *str == 0)
SqThrowF("Cannot extract values from an empty string");
else if (delim != Color4::Delim)
{
fs[4] = delim;
@ -1000,23 +1021,26 @@ Color4 GetColor4(CSStr str, SQChar delim)
sscanf(str, &fs[0], &r, &g, &b, &a);
return Color4(Color4::Value(r), Color4::Value(g), Color4::Value(b), Color4::Value(a));
col.r = static_cast< Color4::Value >(r);
col.g = static_cast< Color4::Value >(g);
col.b = static_cast< Color4::Value >(b);
col.a = static_cast< Color4::Value >(a);
return col;
}
// ------------------------------------------------------------------------------------------------
Quaternion GetQuaternion(CSStr str, SQChar delim)
const Quaternion & GetQuaternion(CSStr str, SQChar delim)
{
static SQChar fs[] = _SC(" %f , %f , %f , %f ");
static Quaternion quat;
//quat.Clear();
if (!str || *str == 0)
SqThrowF("Cannot extract values from an empty string");
if (strlen(str) <= 0)
{
SqThrow("Cannot extract values from an empty string");
return quat;
}
else if (delim != Quaternion::Delim)
quat.Clear();
if (delim != Quaternion::Delim)
{
fs[4] = delim;
fs[9] = delim;
@ -1034,19 +1058,18 @@ Quaternion GetQuaternion(CSStr str, SQChar delim)
return quat;
}
Sphere GetSphere(CSStr str, SQChar delim)
// ------------------------------------------------------------------------------------------------
const Sphere & GetSphere(CSStr str, SQChar delim)
{
static SQChar fs[] = _SC(" %f , %f , %f , %f ");
static Sphere sphere;
//sphere.Clear();
if (!str || *str == 0)
SqThrowF("Cannot extract values from an empty string");
if (strlen(str) <= 0)
{
SqThrow("Cannot extract values from an empty string");
return sphere;
}
else if (delim != Sphere::Delim)
sphere.Clear();
if (delim != Sphere::Delim)
{
fs[4] = delim;
fs[9] = delim;
@ -1065,52 +1088,40 @@ Sphere GetSphere(CSStr str, SQChar delim)
}
// ------------------------------------------------------------------------------------------------
Vector2 GetVector2(CSStr str, SQChar delim)
const Vector2 & GetVector2(CSStr str, SQChar delim)
{
static SQChar fs[] = _SC(" %f , %f ");
static Vector2 vec;
//vec.Clear();
if (!str || *str == 0)
SqThrowF("Cannot extract values from an empty string");
if (strlen(str) <= 0)
{
SqThrow("Cannot extract values from an empty string");
return vec;
}
else if (delim != Vector2::Delim)
{
vec.Clear();
if (delim != Vector2::Delim)
fs[4] = delim;
}
else
{
fs[4] = Vector2::Delim;
}
sscanf(str, &fs[0], &vec.x, &vec.y);
return vec;
}
Vector2i GetVector2i(CSStr str, SQChar delim)
const Vector2i & GetVector2i(CSStr str, SQChar delim)
{
static SQChar fs[] = _SC(" %d , %d ");
static Vector2i vec;
//vec.Clear();
if (!str || *str == 0)
SqThrowF("Cannot extract values from an empty string");
if (strlen(str) <= 0)
{
SqThrow("Cannot extract values from an empty string");
return vec;
}
else if (delim != Vector2i::Delim)
{
vec.Clear();
if (delim != Vector2i::Delim)
fs[4] = delim;
}
else
{
fs[4] = Vector2i::Delim;
}
sscanf(str, &fs[0], &vec.x, &vec.y);
@ -1118,19 +1129,17 @@ Vector2i GetVector2i(CSStr str, SQChar delim)
}
// ------------------------------------------------------------------------------------------------
Vector3 GetVector3(CSStr str, SQChar delim)
const Vector3 & GetVector3(CSStr str, SQChar delim)
{
static SQChar fs[] = _SC(" %f , %f , %f ");
static Vector3 vec;
if (!str || *str == 0)
SqThrowF("Cannot extract values from an empty string");
vec.Clear();
if (strlen(str) <= 0)
{
SqThrow("Cannot extract values from an empty string");
return vec;
}
else if (delim != Vector3::Delim)
if (delim != Vector3::Delim)
{
fs[4] = delim;
fs[9] = delim;
@ -1146,19 +1155,17 @@ Vector3 GetVector3(CSStr str, SQChar delim)
return vec;
}
Vector4 GetVector4(CSStr str, SQChar delim)
const Vector4 & GetVector4(CSStr str, SQChar delim)
{
static SQChar fs[] = _SC(" %f , %f , %f , %f ");
static Vector4 vec;
if (!str || *str == 0)
SqThrowF("Cannot extract values from an empty string");
vec.Clear();
if (strlen(str) <= 0)
{
SqThrow("Cannot extract values from an empty string");
return vec;
}
else if (delim != Vector4::Delim)
if (delim != Vector4::Delim)
{
fs[4] = delim;
fs[9] = delim;

View File

@ -5,8 +5,8 @@
#include "SqBase.hpp"
// ------------------------------------------------------------------------------------------------
#include <math.h>
#include <assert.h>
#include <cmath>
#include <cassert>
// ------------------------------------------------------------------------------------------------
#include <vcmp.h>
@ -19,7 +19,7 @@ namespace SqMod {
extern const SQChar * g_EmptyStr;
/* ------------------------------------------------------------------------------------------------
* Proxies to comunicate with the server.
* Proxies to communicate with the server.
*/
extern PluginFuncs* _Func;
extern PluginCallbacks* _Clbk;
@ -28,7 +28,9 @@ extern PluginInfo* _Info;
// ------------------------------------------------------------------------------------------------
template < typename T > struct NumLimit;
// ------------------------------------------------------------------------------------------------
/* ------------------------------------------------------------------------------------------------
* Basic minimum and maximum values for primitive numeric types.
*/
template <> struct NumLimit< char > { static const char Min, Max; };
template <> struct NumLimit< signed char > { static const signed char Min, Max; };
template <> struct NumLimit< unsigned char > { static const unsigned char Min, Max; };
@ -44,7 +46,58 @@ template <> struct NumLimit< float > { static const float Min, Max; };
template <> struct NumLimit< double > { static const double Min, Max; };
template <> struct NumLimit< long double > { static const long double Min, Max; };
// ------------------------------------------------------------------------------------------------
/* ------------------------------------------------------------------------------------------------
* Implements RAII to restore the VM stack to it's initial size on function exit.
*/
struct StackGuard
{
/* --------------------------------------------------------------------------------------------
* Base constructor.
*/
StackGuard(HSQUIRRELVM vm)
: m_Top(sq_gettop(vm)), m_VM(vm)
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Copy constructor. (disabled)
*/
StackGuard(const StackGuard &) = delete;
/* --------------------------------------------------------------------------------------------
* Move constructor. (disabled)
*/
StackGuard(StackGuard &&) = delete;
/* --------------------------------------------------------------------------------------------
* Destructor.
*/
~StackGuard()
{
sq_pop(m_VM, sq_gettop(m_VM) - m_Top);
}
/* --------------------------------------------------------------------------------------------
* Copy assignment operator. (disabled)
*/
StackGuard & operator = (const StackGuard &) = delete;
/* --------------------------------------------------------------------------------------------
* Move assignment operator. (disabled)
*/
StackGuard & operator = (StackGuard &&) = delete;
private:
// --------------------------------------------------------------------------------------------
Int32 m_Top; /* The top of the stack when this instance was created. */
HSQUIRRELVM m_VM; /* The VM where the stack should be restored. */
};
/* ------------------------------------------------------------------------------------------------
* Perform an equality comparison between two values taking into account floating point issues.
*/
template< typename T > inline bool EpsEq(const T a, const T b)
{
return abs(a - b) <= 0;
@ -60,7 +113,9 @@ template <> inline bool EpsEq(const Float64 a, const Float64 b)
return fabs(a - b) <= 0.000000001d;
}
// ------------------------------------------------------------------------------------------------
/* ------------------------------------------------------------------------------------------------
* Perform a less than comparison between two values taking into account floating point issues.
*/
template< typename T > inline bool EpsLt(const T a, const T b)
{
return !EpsEq(a, b) && (a < b);
@ -76,7 +131,9 @@ template <> inline bool EpsLt(const Float64 a, const Float64 b)
return !EpsEq(a, b) && (a - b) < 0.000000001d;
}
// ------------------------------------------------------------------------------------------------
/* ------------------------------------------------------------------------------------------------
* Perform a greater than comparison between two values taking into account floating point issues.
*/
template< typename T > inline bool EpsGt(const T a, const T b)
{
return !EpsEq(a, b) && (a > b);
@ -92,7 +149,10 @@ template <> inline bool EpsGt(const Float64 a, const Float64 b)
return !EpsEq(a, b) && (a - b) > 0.000000001d;
}
// ------------------------------------------------------------------------------------------------
/* ------------------------------------------------------------------------------------------------
* Perform a less than or equal comparison between two values taking into account
* floating point issues.
*/
template< typename T > inline bool EpsLtEq(const T a, const T b)
{
return !EpsEq(a, b) || (a < b);
@ -108,7 +168,10 @@ template <> inline bool EpsLtEq(const Float64 a, const Float64 b)
return !EpsEq(a, b) || (a - b) < 0.000000001d;
}
// ------------------------------------------------------------------------------------------------
/* ------------------------------------------------------------------------------------------------
* Perform a greater than or equal comparison between two values taking into account
* floating point issues.
*/
template< typename T > inline bool EpsGtEq(const T a, const T b)
{
return !EpsEq(a, b) || (a > b);
@ -124,7 +187,9 @@ template <> inline bool EpsGtEq(const Float64 a, const Float64 b)
return !EpsEq(a, b) || (a - b) > 0.000000001d;
}
// ------------------------------------------------------------------------------------------------
/* ------------------------------------------------------------------------------------------------
* Force a value to be within a certain range.
*/
template< typename T > inline T Clamp(T val, T min, T max)
{
return val < min ? min : (val > max ? max : val);
@ -144,6 +209,142 @@ inline Uint32 NextPow2(Uint32 num)
return ++num;
}
/* ------------------------------------------------------------------------------------------------
* Output a message only if the _DEBUG was defined.
*/
void OutputDebug(const char * msg, ...);
/* ------------------------------------------------------------------------------------------------
* Output a formatted user message to the console.
*/
void OutputMessage(const char * msg, ...);
/* ------------------------------------------------------------------------------------------------
* Output a formatted error message to the console.
*/
void OutputError(const char * msg, ...);
/* ------------------------------------------------------------------------------------------------
* Retrieve a reference to a null script object.
*/
Object & NullObject();
/* ------------------------------------------------------------------------------------------------
* Retrieve a reference to a null/empty script array.
*/
Array & NullArray();
/* ------------------------------------------------------------------------------------------------
* Retrieve a reference to a null script function.
*/
Function & NullFunction();
/* ------------------------------------------------------------------------------------------------
* Create a script object from the specified value on the default VM.
*/
template < typename T > Object MakeObject(const T & v)
{
PushVar< T >(DefaultVM::Get(), v);
Var< Object > var(DefaultVM::Get(), -1);
sq_pop(DefaultVM::Get(), 1);
return var.value;
}
/* ------------------------------------------------------------------------------------------------
* Create a script object from the specified value on the specified VM.
*/
template < typename T > Object MakeObject(HSQUIRRELVM vm, const T & v)
{
PushVar< T >(vm, v);
Var< Object > var(vm, -1);
sq_pop(vm, 1);
return var.value;
}
/* ------------------------------------------------------------------------------------------------
* Simple function to check whether the specified string can be considered as a boolean value
*/
bool SToB(CSStr str);
/* ------------------------------------------------------------------------------------------------
* Generate a formatted string and throw it as a sqrat exception.
*/
void SqThrowF(CCStr fmt, ...);
/* ------------------------------------------------------------------------------------------------
* Quickly generate a formatted string on a small static buffer without any memory allocations.
*/
CSStr ToStrF(CCStr fmt, ...);
/* ------------------------------------------------------------------------------------------------
* Generate a formatted string on a temporary buffer and return the string but not the buffer.
*/
CSStr ToStringF(CCStr fmt, ...);
/* ------------------------------------------------------------------------------------------------
* Obtain a randomly chosen color from a list of known colors.
*/
const Color3 & GetRandomColor();
/* ------------------------------------------------------------------------------------------------
* Attempt to identify the color in the specified name and return it.
*/
Color3 GetColor(CSStr name);
/* ------------------------------------------------------------------------------------------------
* Extract the values for components of the AABB type from a string.
*/
const AABB & GetAABB(CSStr str, SQChar delim);
/* ------------------------------------------------------------------------------------------------
* Extract the values for components of the Circle type from a string.
*/
const Circle & GetCircle(CSStr str, SQChar delim);
/* ------------------------------------------------------------------------------------------------
* Extract the values for components of the Color3 type from a string.
*/
const Color3 & GetColor3(CSStr str, SQChar delim);
/* ------------------------------------------------------------------------------------------------
* Extract the values for components of the Color4 type from a string.
*/
const Color4 & GetColor4(CSStr str, SQChar delim);
/* ------------------------------------------------------------------------------------------------
* Extract the values for components of the Quaternion type from a string.
*/
const Quaternion & GetQuaternion(CSStr str, SQChar delim);
/* ------------------------------------------------------------------------------------------------
* Extract the values for components of the Sphere type from a string.
*/
const Sphere & GetSphere(CSStr str, SQChar delim);
/* ------------------------------------------------------------------------------------------------
* Extract the values for components of the Vector2 type from a string.
*/
const Vector2 & GetVector2(CSStr str, SQChar delim);
/* ------------------------------------------------------------------------------------------------
* Extract the values for components of the Vector2i type from a string.
*/
const Vector2i & GetVector2i(CSStr str, SQChar delim);
/* ------------------------------------------------------------------------------------------------
* Extract the values for components of the Vector3 type from a string.
*/
const Vector3 & GetVector3(CSStr str, SQChar delim);
/* ------------------------------------------------------------------------------------------------
* Extract the values for components of the Vector4 type from a string.
*/
const Vector4 & GetVector4(CSStr str, SQChar delim);
/* ------------------------------------------------------------------------------------------------
* Forward declarations of the logging functions to avoid including the logger everywhere.
*/
// ------------------------------------------------------------------------------------------------
void LogDbg(CCStr fmt, ...);
void LogUsr(CCStr fmt, ...);
@ -180,84 +381,6 @@ bool cLogSWrn(bool cond, CCStr fmt, ...);
bool cLogSErr(bool cond, CCStr fmt, ...);
bool cLogSFtl(bool cond, CCStr fmt, ...);
// ------------------------------------------------------------------------------------------------
void SqThrow(CCStr fmt, ...);
/* ------------------------------------------------------------------------------------------------
* Output a message only if the _DEBUG was defined.
*/
void OutputDebug(const char * msg, ...);
/* ------------------------------------------------------------------------------------------------
* Output a formatted user message to the console.
*/
void OutputMessage(const char * msg, ...);
/* ------------------------------------------------------------------------------------------------
* Output a formatted error message to the console.
*/
void OutputError(const char * msg, ...);
// ------------------------------------------------------------------------------------------------
Object & NullObject();
// ------------------------------------------------------------------------------------------------
Array & NullArray();
// ------------------------------------------------------------------------------------------------
Function & NullFunction();
// ------------------------------------------------------------------------------------------------
template < typename T > Object MakeObject(const T & v)
{
PushVar< T >(DefaultVM::Get(), v);
Var< Object > var(DefaultVM::Get(), -1);
sq_pop(DefaultVM::Get(), 1);
return var.value;
}
// ------------------------------------------------------------------------------------------------
template < typename T > Object MakeObject(HSQUIRRELVM vm, const T & v)
{
PushVar< T >(vm, v);
Var< Object > var(vm, -1);
sq_pop(vm, 1);
return var.value;
}
/* ------------------------------------------------------------------------------------------------
* Simple function to check whether the specified string can be considered as a boolean value
*/
bool SToB(CSStr str);
/* ------------------------------------------------------------------------------------------------
*
*/
CSStr ToStrF(CCStr fmt, ...);
/* ------------------------------------------------------------------------------------------------
*
*/
CSStr ToStringF(CCStr fmt, ...);
// ------------------------------------------------------------------------------------------------
const Color3 & GetRandomColor();
/* ------------------------------------------------------------------------------------------------
* Value extractors.
*/
Color3 GetColor(CSStr name);
AABB GetAABB(CSStr str, SQChar delim);
Circle GetCircle(CSStr str, SQChar delim);
Color3 GetColor3(CSStr str, SQChar delim);
Color4 GetColor4(CSStr str, SQChar delim);
Quaternion GetQuaternion(CSStr str, SQChar delim);
Sphere GetSphere(CSStr str, SQChar delim);
Vector2 GetVector2(CSStr str, SQChar delim);
Vector2i GetVector2i(CSStr str, SQChar delim);
Vector3 GetVector3(CSStr str, SQChar delim);
Vector4 GetVector4(CSStr str, SQChar delim);
} // Namespace:: SqMod
#endif // _BASE_SHARED_HPP_

View File

@ -14,6 +14,14 @@ const Sphere Sphere::MAX = Sphere(NumLimit< Sphere::Value >::Max);
// ------------------------------------------------------------------------------------------------
SQChar Sphere::Delim = ',';
// ------------------------------------------------------------------------------------------------
SQInteger Sphere::Typename(HSQUIRRELVM vm)
{
static SQChar name[] = _SC("Sphere");
sq_pushstring(vm, name, sizeof(name));
return 1;
}
// ------------------------------------------------------------------------------------------------
Sphere::Sphere()
: pos(0.0), rad(0.0)
@ -42,27 +50,6 @@ Sphere::Sphere(Value xv, Value yv, Value zv, Value rv)
/* ... */
}
// ------------------------------------------------------------------------------------------------
Sphere::Sphere(const Sphere & o)
: pos(o.pos), rad(o.rad)
{
/* ... */
}
// ------------------------------------------------------------------------------------------------
Sphere::~Sphere()
{
/* ... */
}
// ------------------------------------------------------------------------------------------------
Sphere & Sphere::operator = (const Sphere & o)
{
pos = o.pos;
rad = o.rad;
return *this;
}
// ------------------------------------------------------------------------------------------------
Sphere & Sphere::operator = (Value r)
{
@ -341,7 +328,7 @@ Int32 Sphere::Cmp(const Sphere & o) const
// ------------------------------------------------------------------------------------------------
CSStr Sphere::ToString() const
{
return ToStringF("%f,%f,%f,%f", pos.x, pos.y, pos.z, rad);
return ToStrF("%f,%f,%f,%f", pos.x, pos.y, pos.z, rad);
}
// ------------------------------------------------------------------------------------------------
@ -395,35 +382,28 @@ void Sphere::Generate()
void Sphere::Generate(Value min, Value max, bool r)
{
if (EpsLt(max, min))
{
SqThrow("max value is lower than min value");
}
SqThrowF("max value is lower than min value");
else if (r)
{
rad = GetRandomFloat32(min, max);
}
else
{
pos.Generate(min, max);
}
}
void Sphere::Generate(Value xmin, Value xmax, Value ymin, Value ymax, Value zmin, Value zmax)
{
if (EpsLt(xmax, xmin) || EpsLt(ymax, ymin) || EpsLt(zmax, zmin))
SqThrowF("max value is lower than min value");
pos.Generate(xmin, xmax, ymin, ymax, zmin, zmax);
}
void Sphere::Generate(Value xmin, Value xmax, Value ymin, Value ymax, Value zmin, Value zmax, Value rmin, Value rmax)
{
if (EpsLt(rmax, rmin))
{
SqThrow("max value is lower than min value");
}
else
{
pos.Generate(xmin, xmax, ymin, ymax, zmin, zmax);
rad = GetRandomFloat32(rmin, rmax);
}
if (EpsLt(xmax, xmin) || EpsLt(ymax, ymin) || EpsLt(zmax, zmin) || EpsLt(rmax, rmin))
SqThrowF("max value is lower than min value");
pos.Generate(xmin, xmax, ymin, ymax, zmin, zmax);
rad = GetRandomFloat32(rmin, rmax);
}
// ------------------------------------------------------------------------------------------------
@ -452,6 +432,7 @@ void Register_Sphere(HSQUIRRELVM vm)
.Prop(_SC("abs"), &Sphere::Abs)
/* Core Metamethods */
.Func(_SC("_tostring"), &Sphere::ToString)
.SquirrelFunc(_SC("_typename"), &Sphere::Typename)
.Func(_SC("_cmp"), &Sphere::Cmp)
/* Metamethods */
.Func<Sphere (Sphere::*)(const Sphere &) const>(_SC("_add"), &Sphere::operator +)

View File

@ -9,355 +9,370 @@
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
*
* Class used to represent a three-dimensional sphere.
*/
struct Sphere
{
/* --------------------------------------------------------------------------------------------
* ...
* The type of value used by components of type.
*/
typedef float Value;
/* --------------------------------------------------------------------------------------------
* ...
* Helper instances for common values mostly used as return types or comparison.
*/
static const Sphere NIL;
static const Sphere MIN;
static const Sphere MAX;
/* --------------------------------------------------------------------------------------------
* ...
* The delimiter character to be used when extracting values from strings.
*/
static SQChar Delim;
/* --------------------------------------------------------------------------------------------
* ...
* The position and radius components of this type.
*/
Vector3 pos;
Value rad;
/* --------------------------------------------------------------------------------------------
*
* Default constructor.
*/
Sphere();
/* --------------------------------------------------------------------------------------------
* ...
* Construct a sphere at position 0,0,0 using the specified radius.
*/
Sphere(Value rv);
/* --------------------------------------------------------------------------------------------
* ...
* Construct a sphere at the specified position using the specified radius.
*/
Sphere(const Vector3 & pv, Value rv);
/* --------------------------------------------------------------------------------------------
* ...
* Construct a sphere at the specified position using the specified radius.
*/
Sphere(Value xv, Value yv, Value zv, Value rv);
/* --------------------------------------------------------------------------------------------
*
* Copy constructor.
*/
Sphere(const Sphere & o);
Sphere(const Sphere & o) = default;
/* --------------------------------------------------------------------------------------------
*
* Move constructor.
*/
~Sphere();
Sphere(Sphere && o) = default;
/* --------------------------------------------------------------------------------------------
*
* Destructor.
*/
Sphere & operator = (const Sphere & o);
~Sphere() = default;
/* --------------------------------------------------------------------------------------------
* ...
* Copy assignment operator.
*/
Sphere & operator = (const Sphere & o) = default;
/* --------------------------------------------------------------------------------------------
* Move assignment operator.
*/
Sphere & operator = (Sphere && o) = default;
/* --------------------------------------------------------------------------------------------
* Radius assignment operator.
*/
Sphere & operator = (Value r);
/* --------------------------------------------------------------------------------------------
* ...
* Position assignment operator.
*/
Sphere & operator = (const Vector3 & p);
/* --------------------------------------------------------------------------------------------
* ...
* Addition assignment operator.
*/
Sphere & operator += (const Sphere & s);
/* --------------------------------------------------------------------------------------------
* ...
* Subtraction assignment operator.
*/
Sphere & operator -= (const Sphere & s);
/* --------------------------------------------------------------------------------------------
* ...
* Multiplication assignment operator.
*/
Sphere & operator *= (const Sphere & s);
/* --------------------------------------------------------------------------------------------
* ...
* Division assignment operator.
*/
Sphere & operator /= (const Sphere & s);
/* --------------------------------------------------------------------------------------------
* ...
* Modulo assignment operator.
*/
Sphere & operator %= (const Sphere & s);
/* --------------------------------------------------------------------------------------------
* ...
* Radius addition assignment operator.
*/
Sphere & operator += (Value r);
/* --------------------------------------------------------------------------------------------
* ...
* Radius subtraction assignment operator.
*/
Sphere & operator -= (Value r);
/* --------------------------------------------------------------------------------------------
* ...
* Radius multiplication assignment operator.
*/
Sphere & operator *= (Value r);
/* --------------------------------------------------------------------------------------------
* ...
* Radius division assignment operator.
*/
Sphere & operator /= (Value r);
/* --------------------------------------------------------------------------------------------
* ...
* Radius modulo assignment operator.
*/
Sphere & operator %= (Value r);
/* --------------------------------------------------------------------------------------------
* ...
* Position addition assignment operator.
*/
Sphere & operator += (const Vector3 & p);
/* --------------------------------------------------------------------------------------------
* ...
* Position subtraction assignment operator.
*/
Sphere & operator -= (const Vector3 & p);
/* --------------------------------------------------------------------------------------------
* ...
* Position multiplication assignment operator.
*/
Sphere & operator *= (const Vector3 & p);
/* --------------------------------------------------------------------------------------------
* ...
* Position division assignment operator.
*/
Sphere & operator /= (const Vector3 & p);
/* --------------------------------------------------------------------------------------------
* ...
* Position modulo assignment operator.
*/
Sphere & operator %= (const Vector3 & p);
/* --------------------------------------------------------------------------------------------
* ...
* Pre-increment operator.
*/
Sphere & operator ++ ();
/* --------------------------------------------------------------------------------------------
* ...
* Pre-decrement operator.
*/
Sphere & operator -- ();
/* --------------------------------------------------------------------------------------------
* ...
* Post-increment operator.
*/
Sphere operator ++ (int);
/* --------------------------------------------------------------------------------------------
* ...
* Post-decrement operator.
*/
Sphere operator -- (int);
/* --------------------------------------------------------------------------------------------
* ...
* Addition operator.
*/
Sphere operator + (const Sphere & s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Subtraction operator.
*/
Sphere operator - (const Sphere & s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Multiplication operator.
*/
Sphere operator * (const Sphere & s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Division operator.
*/
Sphere operator / (const Sphere & s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Modulo operator.
*/
Sphere operator % (const Sphere & s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Radius addition operator.
*/
Sphere operator + (Value r) const;
/* --------------------------------------------------------------------------------------------
* ...
* Radius subtraction operator.
*/
Sphere operator - (Value r) const;
/* --------------------------------------------------------------------------------------------
* ...
* Radius multiplication operator.
*/
Sphere operator * (Value r) const;
/* --------------------------------------------------------------------------------------------
* ...
* Radius division operator.
*/
Sphere operator / (Value r) const;
/* --------------------------------------------------------------------------------------------
* ...
* Radius modulo operator.
*/
Sphere operator % (Value r) const;
/* --------------------------------------------------------------------------------------------
* ...
* Position addition operator.
*/
Sphere operator + (const Vector3 & p) const;
/* --------------------------------------------------------------------------------------------
* ...
* Position subtraction operator.
*/
Sphere operator - (const Vector3 & p) const;
/* --------------------------------------------------------------------------------------------
* ...
* Position multiplication operator.
*/
Sphere operator * (const Vector3 & p) const;
/* --------------------------------------------------------------------------------------------
* ...
* Position division operator.
*/
Sphere operator / (const Vector3 & p) const;
/* --------------------------------------------------------------------------------------------
* ...
* Position modulo operator.
*/
Sphere operator % (const Vector3 & p) const;
/* --------------------------------------------------------------------------------------------
* ...
* Unary plus operator.
*/
Sphere operator + () const;
/* --------------------------------------------------------------------------------------------
* ...
* Unary minus operator.
*/
Sphere operator - () const;
/* --------------------------------------------------------------------------------------------
* ...
* Equality comparison operator.
*/
bool operator == (const Sphere & s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Inequality comparison operator.
*/
bool operator != (const Sphere & s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Less than comparison operator.
*/
bool operator < (const Sphere & s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Greater than comparison operator.
*/
bool operator > (const Sphere & s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Less than or equal comparison operator.
*/
bool operator <= (const Sphere & s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Greater than or equal comparison operator.
*/
bool operator >= (const Sphere & s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Used by the script engine to compare two instances of this type.
*/
Int32 Cmp(const Sphere & s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Used by the script engine to convert an instance of this type to a string.
*/
CSStr ToString() const;
/* --------------------------------------------------------------------------------------------
* ...
* Used by the script engine to retrieve the name from instances of this type.
*/
static SQInteger Typename(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Set the specified radius.
*/
void Set(Value nr);
/* --------------------------------------------------------------------------------------------
* ...
* Copy the sphere from another instance of this type.
*/
void Set(const Sphere & ns);
/* --------------------------------------------------------------------------------------------
* ...
* Set the position from the specified position.
*/
void Set(const Vector3 & np);
/* --------------------------------------------------------------------------------------------
* ...
* Set the specified position and radius.
*/
void Set(const Vector3 & np, Value nr);
/* --------------------------------------------------------------------------------------------
* ...
* Set the specified position.
*/
void Set(Value nx, Value ny, Value nz);
/* --------------------------------------------------------------------------------------------
* ...
* Set the specified position and radius.
*/
void Set(Value nx, Value ny, Value nz, Value nr);
/* --------------------------------------------------------------------------------------------
* ...
* Set the values extracted from the specified string using the specified delimiter.
*/
void Set(CSStr values, SQChar delim);
/* --------------------------------------------------------------------------------------------
* ...
* Generate a randomly sized and positioned sphere.
*/
void Generate();
/* --------------------------------------------------------------------------------------------
* ...
* Generate a randomly sized or positioned sphere within the specified bounds.
*/
void Generate(Value min, Value max, bool r);
/* --------------------------------------------------------------------------------------------
* ...
* Generate a randomly positioned sphere within the specified bounds.
*/
void Generate(Value xmin, Value xmax, Value ymin, Value ymax, Value zmin, Value zmax);
/* --------------------------------------------------------------------------------------------
* ...
* Generate a randomly sized and positioned sphere within the specified bounds.
*/
void Generate(Value xmin, Value xmax, Value ymin, Value ymax, Value zmin, Value zmax, Value rmin, Value rmax);
/* --------------------------------------------------------------------------------------------
* ...
* Clear the component values to default.
*/
void Clear()
{
@ -365,7 +380,7 @@ struct Sphere
}
/* --------------------------------------------------------------------------------------------
* ...
* Retrieve a new instance of this type with absolute component values.
*/
Sphere Abs() const;
};

View File

@ -15,6 +15,14 @@ const Vector2 Vector2::MAX = Vector2(NumLimit< Vector2::Value >::Max);
// ------------------------------------------------------------------------------------------------
SQChar Vector2::Delim = ',';
// ------------------------------------------------------------------------------------------------
SQInteger Vector2::Typename(HSQUIRRELVM vm)
{
static SQChar name[] = _SC("Vector2");
sq_pushstring(vm, name, sizeof(name));
return 1;
}
// ------------------------------------------------------------------------------------------------
Vector2::Vector2()
: x(0.0), y(0.0)
@ -36,27 +44,6 @@ Vector2::Vector2(Value xv, Value yv)
/* ... */
}
// ------------------------------------------------------------------------------------------------
Vector2::Vector2(const Vector2 & o)
: x(o.x), y(o.y)
{
/* ... */
}
// ------------------------------------------------------------------------------------------------
Vector2::~Vector2()
{
/* ... */
}
// ------------------------------------------------------------------------------------------------
Vector2 & Vector2::operator = (const Vector2 & o)
{
x = o.x;
y = o.y;
return *this;
}
// ------------------------------------------------------------------------------------------------
Vector2 & Vector2::operator = (Value s)
{
@ -290,7 +277,7 @@ Int32 Vector2::Cmp(const Vector2 & o) const
// ------------------------------------------------------------------------------------------------
CSStr Vector2::ToString() const
{
return ToStringF("%f,%f", x, y);
return ToStrF("%f,%f", x, y);
}
// ------------------------------------------------------------------------------------------------
@ -335,27 +322,19 @@ void Vector2::Generate()
void Vector2::Generate(Value min, Value max)
{
if (EpsLt(max, min))
{
SqThrow("max value is lower than min value");
}
else
{
x = GetRandomFloat32(min, max);
y = GetRandomFloat32(min, max);
}
SqThrowF("max value is lower than min value");
x = GetRandomFloat32(min, max);
y = GetRandomFloat32(min, max);
}
void Vector2::Generate(Value xmin, Value xmax, Value ymin, Value ymax)
{
if (EpsLt(xmax, xmin) || EpsLt(ymax, ymin))
{
SqThrow("max value is lower than min value");
}
else
{
x = GetRandomFloat32(ymin, ymax);
y = GetRandomFloat32(xmin, xmax);
}
SqThrowF("max value is lower than min value");
x = GetRandomFloat32(ymin, ymax);
y = GetRandomFloat32(xmin, xmax);
}
// ------------------------------------------------------------------------------------------------
@ -383,6 +362,7 @@ void Register_Vector2(HSQUIRRELVM vm)
.Prop(_SC("abs"), &Vector2::Abs)
/* Core Metamethods */
.Func(_SC("_tostring"), &Vector2::ToString)
.SquirrelFunc(_SC("_typename"), &Vector2::Typename)
.Func(_SC("_cmp"), &Vector2::Cmp)
/* Metamethods */
.Func<Vector2 (Vector2::*)(const Vector2 &) const>(_SC("_add"), &Vector2::operator +)

View File

@ -8,289 +8,304 @@
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
*
* Class used to represent a two-dimensional vector.
*/
struct Vector2
{
/* --------------------------------------------------------------------------------------------
* ...
* The type of value used by components of type.
*/
typedef float Value;
/* --------------------------------------------------------------------------------------------
* ...
* Helper instances for common values mostly used as return types or comparison.
*/
static const Vector2 NIL;
static const Vector2 MIN;
static const Vector2 MAX;
/* --------------------------------------------------------------------------------------------
* ...
* The delimiter character to be used when extracting values from strings.
*/
static SQChar Delim;
/* --------------------------------------------------------------------------------------------
* ...
* The x and y components of this type.
*/
Value x, y;
/* --------------------------------------------------------------------------------------------
*
* Default constructor.
*/
Vector2();
/* --------------------------------------------------------------------------------------------
* ...
* Construct a vector with the same scalar value for all components.
*/
Vector2(Value sv);
/* --------------------------------------------------------------------------------------------
* ...
* Construct a vector with the specified component values.
*/
Vector2(Value xv, Value yv);
/* --------------------------------------------------------------------------------------------
*
* Copy constructor.
*/
Vector2(const Vector2 & o);
Vector2(const Vector2 & o) = default;
/* --------------------------------------------------------------------------------------------
*
* Move constructor.
*/
~Vector2();
Vector2(Vector2 && o) = default;
/* --------------------------------------------------------------------------------------------
*
* Destructor.
*/
Vector2 & operator = (const Vector2 & o);
~Vector2() = default;
/* --------------------------------------------------------------------------------------------
* ...
* Copy assignment operator.
*/
Vector2 & operator = (const Vector2 & o) = default;
/* --------------------------------------------------------------------------------------------
* Move assignment operator.
*/
Vector2 & operator = (Vector2 && o) = default;
/* --------------------------------------------------------------------------------------------
* Scalar value assignment operator.
*/
Vector2 & operator = (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* String assignment operator.
*/
Vector2 & operator = (CSStr values);
/* --------------------------------------------------------------------------------------------
* ...
* Integral two-dimensional vector assignment.
*/
Vector2 & operator = (const Vector2i & v);
/* --------------------------------------------------------------------------------------------
* ...
* Addition assignment operator.
*/
Vector2 & operator += (const Vector2 & v);
/* --------------------------------------------------------------------------------------------
* ...
* Subtraction assignment operator.
*/
Vector2 & operator -= (const Vector2 & v);
/* --------------------------------------------------------------------------------------------
* ...
* Multiplication assignment operator.
*/
Vector2 & operator *= (const Vector2 & v);
/* --------------------------------------------------------------------------------------------
* ...
* Division assignment operator.
*/
Vector2 & operator /= (const Vector2 & v);
/* --------------------------------------------------------------------------------------------
* ...
* Modulo assignment operator.
*/
Vector2 & operator %= (const Vector2 & v);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value addition assignment operator.
*/
Vector2 & operator += (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value subtraction assignment operator.
*/
Vector2 & operator -= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value multiplication assignment operator.
*/
Vector2 & operator *= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value division assignment operator.
*/
Vector2 & operator /= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value modulo assignment operator.
*/
Vector2 & operator %= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Pre-increment operator.
*/
Vector2 & operator ++ ();
/* --------------------------------------------------------------------------------------------
* ...
* Pre-decrement operator.
*/
Vector2 & operator -- ();
/* --------------------------------------------------------------------------------------------
* ...
* Post-increment operator.
*/
Vector2 operator ++ (int);
/* --------------------------------------------------------------------------------------------
* ...
* Post-decrement operator.
*/
Vector2 operator -- (int);
/* --------------------------------------------------------------------------------------------
* ...
* Addition operator.
*/
Vector2 operator + (const Vector2 & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Subtraction operator.
*/
Vector2 operator - (const Vector2 & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Multiplication operator.
*/
Vector2 operator * (const Vector2 & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Division operator.
*/
Vector2 operator / (const Vector2 & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Modulo operator.
*/
Vector2 operator % (const Vector2 & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value addition operator.
*/
Vector2 operator + (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value subtraction operator.
*/
Vector2 operator - (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value multiplication operator.
*/
Vector2 operator * (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value division operator.
*/
Vector2 operator / (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value modulo operator.
*/
Vector2 operator % (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Unary plus operator.
*/
Vector2 operator + () const;
/* --------------------------------------------------------------------------------------------
* ...
* Unary minus operator.
*/
Vector2 operator - () const;
/* --------------------------------------------------------------------------------------------
* ...
* Equality comparison operator.
*/
bool operator == (const Vector2 & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Inequality comparison operator.
*/
bool operator != (const Vector2 & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Less than comparison operator.
*/
bool operator < (const Vector2 & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Greater than comparison operator.
*/
bool operator > (const Vector2 & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Less than or equal comparison operator.
*/
bool operator <= (const Vector2 & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Greater than or equal comparison operator.
*/
bool operator >= (const Vector2 & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Used by the script engine to compare two instances of this type.
*/
Int32 Cmp(const Vector2 & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Used by the script engine to convert an instance of this type to a string.
*/
CSStr ToString() const;
/* --------------------------------------------------------------------------------------------
* ...
* Used by the script engine to retrieve the name from instances of this type.
*/
static SQInteger Typename(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Set all components to the specified scalar value.
*/
void Set(Value ns);
/* --------------------------------------------------------------------------------------------
* ...
* Set all components to the specified values.
*/
void Set(Value nx, Value ny);
/* --------------------------------------------------------------------------------------------
* ...
* Copy the values from another instance of this type.
*/
void Set(const Vector2 & v);
/* --------------------------------------------------------------------------------------------
* ...
* Copy the values from an integral two-dimensional vector.
*/
void Set(const Vector2i & v);
/* --------------------------------------------------------------------------------------------
* ...
* Set the values extracted from the specified string using the specified delimiter.
*/
void Set(CSStr values, SQChar delim);
/* --------------------------------------------------------------------------------------------
* ...
* Generate random values for all components of this instance.
*/
void Generate();
/* --------------------------------------------------------------------------------------------
* ...
* Generate random values for all components of this instance within the specified bounds.
*/
void Generate(Value min, Value max);
/* --------------------------------------------------------------------------------------------
* ...
* Generate random values for all components of this instance within the specified bounds.
*/
void Generate(Value xmin, Value xmax, Value ymin, Value ymax);
/* --------------------------------------------------------------------------------------------
* ...
* Clear the component values to default.
*/
void Clear()
{
@ -298,7 +313,7 @@ struct Vector2
}
/* --------------------------------------------------------------------------------------------
* ...
* Retrieve a new instance of this type with absolute component values.
*/
Vector2 Abs() const;
};

View File

@ -15,6 +15,14 @@ const Vector2i Vector2i::MAX = Vector2i(NumLimit< Vector2i::Value >::Max);
// ------------------------------------------------------------------------------------------------
SQChar Vector2i::Delim = ',';
// ------------------------------------------------------------------------------------------------
SQInteger Vector2i::Typename(HSQUIRRELVM vm)
{
static SQChar name[] = _SC("Vector2i");
sq_pushstring(vm, name, sizeof(name));
return 1;
}
// ------------------------------------------------------------------------------------------------
Vector2i::Vector2i()
: x(0), y(0)
@ -36,27 +44,6 @@ Vector2i::Vector2i(Value xv, Value yv)
/* ... */
}
// ------------------------------------------------------------------------------------------------
Vector2i::Vector2i(const Vector2i & o)
: x(o.x), y(o.y)
{
/* ... */
}
// ------------------------------------------------------------------------------------------------
Vector2i::~Vector2i()
{
/* ... */
}
// ------------------------------------------------------------------------------------------------
Vector2i & Vector2i::operator = (const Vector2i & o)
{
x = o.x;
y = o.y;
return *this;
}
// ------------------------------------------------------------------------------------------------
Vector2i & Vector2i::operator = (Value s)
{
@ -416,7 +403,7 @@ Int32 Vector2i::Cmp(const Vector2i & o) const
// ------------------------------------------------------------------------------------------------
CSStr Vector2i::ToString() const
{
return ToStringF("%d,%d", x, y);
return ToStrF("%d,%d", x, y);
}
// ------------------------------------------------------------------------------------------------
@ -461,27 +448,19 @@ void Vector2i::Generate()
void Vector2i::Generate(Value min, Value max)
{
if (max < min)
{
SqThrow("max value is lower than min value");
}
else
{
x = GetRandomInt32(min, max);
y = GetRandomInt32(min, max);
}
SqThrowF("max value is lower than min value");
x = GetRandomInt32(min, max);
y = GetRandomInt32(min, max);
}
void Vector2i::Generate(Value xmin, Value xmax, Value ymin, Value ymax)
{
if (xmax < xmin || ymax < ymin)
{
SqThrow("max value is lower than min value");
}
else
{
x = GetRandomInt32(ymin, ymax);
y = GetRandomInt32(xmin, xmax);
}
SqThrowF("max value is lower than min value");
x = GetRandomInt32(ymin, ymax);
y = GetRandomInt32(xmin, xmax);
}
// ------------------------------------------------------------------------------------------------
@ -509,6 +488,7 @@ void Register_Vector2i(HSQUIRRELVM vm)
.Prop(_SC("abs"), &Vector2i::Abs)
/* Core Metamethods */
.Func(_SC("_tostring"), &Vector2i::ToString)
.SquirrelFunc(_SC("_typename"), &Vector2i::Typename)
.Func(_SC("_cmp"), &Vector2i::Cmp)
/* Metamethods */
.Func<Vector2i (Vector2i::*)(const Vector2i &) const>(_SC("_add"), &Vector2i::operator +)

View File

@ -8,394 +8,409 @@
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
*
* Class used to represent a two-dimensional vector using integral values.
*/
struct Vector2i
{
/* --------------------------------------------------------------------------------------------
* ...
* The type of value used by components of type.
*/
typedef int Value;
/* --------------------------------------------------------------------------------------------
* ...
* Helper instances for common values mostly used as return types or comparison.
*/
static const Vector2i NIL;
static const Vector2i MIN;
static const Vector2i MAX;
/* --------------------------------------------------------------------------------------------
* ...
* The delimiter character to be used when extracting values from strings.
*/
static SQChar Delim;
/* --------------------------------------------------------------------------------------------
* ...
* The x and y components of this type.
*/
Value x, y;
/* --------------------------------------------------------------------------------------------
*
* Default constructor.
*/
Vector2i();
/* --------------------------------------------------------------------------------------------
* ...
* Construct a vector with the same scalar value for all components.
*/
Vector2i(Value sv);
/* --------------------------------------------------------------------------------------------
* ...
* Construct a vector with the specified component values.
*/
Vector2i(Value xv, Value yv);
/* --------------------------------------------------------------------------------------------
*
* Copy constructor.
*/
Vector2i(const Vector2i & o);
Vector2i(const Vector2i & o) = default;
/* --------------------------------------------------------------------------------------------
*
* Copy constructor.
*/
~Vector2i();
Vector2i(Vector2i && o) = default;
/* --------------------------------------------------------------------------------------------
*
* Destructor.
*/
Vector2i & operator = (const Vector2i & o);
~Vector2i() = default;
/* --------------------------------------------------------------------------------------------
* ...
* Copy assignment operator.
*/
Vector2i & operator = (const Vector2i & o) = default;
/* --------------------------------------------------------------------------------------------
* Move assignment operator.
*/
Vector2i & operator = (Vector2i && o) = default;
/* --------------------------------------------------------------------------------------------
* Scalar value assignment operator.
*/
Vector2i & operator = (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* String assignment operator.
*/
Vector2i & operator = (CSStr values);
/* --------------------------------------------------------------------------------------------
* ...
* Real two-dimensional vector assignment.
*/
Vector2i & operator = (const Vector2 & v);
/* --------------------------------------------------------------------------------------------
* ...
* Addition assignment operator.
*/
Vector2i & operator += (const Vector2i & v);
/* --------------------------------------------------------------------------------------------
* ...
* Subtraction assignment operator.
*/
Vector2i & operator -= (const Vector2i & v);
/* --------------------------------------------------------------------------------------------
* ...
* Multiplication assignment operator.
*/
Vector2i & operator *= (const Vector2i & v);
/* --------------------------------------------------------------------------------------------
* ...
* Division assignment operator.
*/
Vector2i & operator /= (const Vector2i & v);
/* --------------------------------------------------------------------------------------------
* ...
* Modulo assignment operator.
*/
Vector2i & operator %= (const Vector2i & v);
/* --------------------------------------------------------------------------------------------
* ...
* Bitwise AND assignment operator.
*/
Vector2i & operator &= (const Vector2i & v);
/* --------------------------------------------------------------------------------------------
* ...
* Bitwise OR assignment operator.
*/
Vector2i & operator |= (const Vector2i & v);
/* --------------------------------------------------------------------------------------------
* ...
* Bitwise XOR assignment operator.
*/
Vector2i & operator ^= (const Vector2i & v);
/* --------------------------------------------------------------------------------------------
* ...
* Bitwise left shift assignment operator.
*/
Vector2i & operator <<= (const Vector2i & v);
/* --------------------------------------------------------------------------------------------
* ...
* Bitwise right shift assignment operator.
*/
Vector2i & operator >>= (const Vector2i & v);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value addition assignment operator.
*/
Vector2i & operator += (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value subtraction assignment operator.
*/
Vector2i & operator -= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value multiplication assignment operator.
*/
Vector2i & operator *= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value division assignment operator.
*/
Vector2i & operator /= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value modulo assignment operator.
*/
Vector2i & operator %= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value bitwise AND assignment operator.
*/
Vector2i & operator &= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value bitwise OR assignment operator.
*/
Vector2i & operator |= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value bitwise XOR assignment operator.
*/
Vector2i & operator ^= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value bitwise left shift assignment operator.
*/
Vector2i & operator <<= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value bitwise right shift assignment operator.
*/
Vector2i & operator >>= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Pre-increment operator.
*/
Vector2i & operator ++ ();
/* --------------------------------------------------------------------------------------------
* ...
* Pre-decrement operator.
*/
Vector2i & operator -- ();
/* --------------------------------------------------------------------------------------------
* ...
* Post-increment operator.
*/
Vector2i operator ++ (int);
/* --------------------------------------------------------------------------------------------
* ...
* Post-decrement operator.
*/
Vector2i operator -- (int);
/* --------------------------------------------------------------------------------------------
* ...
* Addition operator.
*/
Vector2i operator + (const Vector2i & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Subtraction operator.
*/
Vector2i operator - (const Vector2i & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Multiplication operator.
*/
Vector2i operator * (const Vector2i & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Division operator.
*/
Vector2i operator / (const Vector2i & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Modulo operator.
*/
Vector2i operator % (const Vector2i & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Bitwise AND operator.
*/
Vector2i operator & (const Vector2i & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Bitwise OR operator.
*/
Vector2i operator | (const Vector2i & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Bitwise XOR operator.
*/
Vector2i operator ^ (const Vector2i & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Bitwise shift left operator.
*/
Vector2i operator << (const Vector2i & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Bitwise shift right operator.
*/
Vector2i operator >> (const Vector2i & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value addition operator.
*/
Vector2i operator + (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value subtraction operator.
*/
Vector2i operator - (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value multiplication operator.
*/
Vector2i operator * (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value division operator.
*/
Vector2i operator / (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value modulo operator.
*/
Vector2i operator % (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value bitwise AND operator.
*/
Vector2i operator & (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value bitwise OR operator.
*/
Vector2i operator | (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value bitwise XOR operator.
*/
Vector2i operator ^ (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value bitwise shift left operator.
*/
Vector2i operator << (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value bitwise shift right operator.
*/
Vector2i operator >> (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Unary plus operator.
*/
Vector2i operator + () const;
/* --------------------------------------------------------------------------------------------
* ...
* Unary minus operator.
*/
Vector2i operator - () const;
/* --------------------------------------------------------------------------------------------
* ...
* Bitwise NOT operator.
*/
Vector2i operator ~ () const;
/* --------------------------------------------------------------------------------------------
* ...
* Equality comparison operator.
*/
bool operator == (const Vector2i & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Inequality comparison operator.
*/
bool operator != (const Vector2i & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Less than comparison operator.
*/
bool operator < (const Vector2i & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Greater than comparison operator.
*/
bool operator > (const Vector2i & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Less than or equal comparison operator.
*/
bool operator <= (const Vector2i & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Greater than or equal comparison operator.
*/
bool operator >= (const Vector2i & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Used by the script engine to compare two instances of this type.
*/
Int32 Cmp(const Vector2i & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Used by the script engine to convert an instance of this type to a string.
*/
CSStr ToString() const;
/* --------------------------------------------------------------------------------------------
* ...
* Used by the script engine to retrieve the name from instances of this type.
*/
static SQInteger Typename(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Set all components to the specified scalar value.
*/
void Set(Value ns);
/* --------------------------------------------------------------------------------------------
* ...
* Set all components to the specified values.
*/
void Set(Value nx, Value ny);
/* --------------------------------------------------------------------------------------------
* ...
* Copy the values from another instance of this type.
*/
void Set(const Vector2i & v);
/* --------------------------------------------------------------------------------------------
* ...
* Copy the values from a real two-dimensional vector.
*/
void Set(const Vector2 & v);
/* --------------------------------------------------------------------------------------------
* ...
* Set the values extracted from the specified string using the specified delimiter.
*/
void Set(CSStr values, SQChar delim);
/* --------------------------------------------------------------------------------------------
* ...
* Generate random values for all components of this instance.
*/
void Generate();
/* --------------------------------------------------------------------------------------------
* ...
* Generate random values for all components of this instance within the specified bounds.
*/
void Generate(Value min, Value max);
/* --------------------------------------------------------------------------------------------
* ...
* Generate random values for all components of this instance within the specified bounds.
*/
void Generate(Value xmin, Value xmax, Value ymin, Value ymax);
/* --------------------------------------------------------------------------------------------
* ...
* Clear the component values to default.
*/
void Clear()
{
@ -403,7 +418,7 @@ struct Vector2i
}
/* --------------------------------------------------------------------------------------------
* ...
* Retrieve a new instance of this type with absolute component values.
*/
Vector2i Abs() const;
};

View File

@ -16,6 +16,14 @@ const Vector3 Vector3::MAX = Vector3(NumLimit< Vector3::Value >::Max);
// ------------------------------------------------------------------------------------------------
SQChar Vector3::Delim = ',';
// ------------------------------------------------------------------------------------------------
SQInteger Vector3::Typename(HSQUIRRELVM vm)
{
static SQChar name[] = _SC("Vector3");
sq_pushstring(vm, name, sizeof(name));
return 1;
}
// ------------------------------------------------------------------------------------------------
Vector3::Vector3()
: x(0.0), y(0.0), z(0.0)
@ -37,28 +45,6 @@ Vector3::Vector3(Value xv, Value yv, Value zv)
/* ... */
}
// ------------------------------------------------------------------------------------------------
Vector3::Vector3(const Vector3 & o)
: x(o.x), y(o.y), z(o.z)
{
/* ... */
}
// ------------------------------------------------------------------------------------------------
Vector3::~Vector3()
{
/* ... */
}
// ------------------------------------------------------------------------------------------------
Vector3 & Vector3::operator = (const Vector3 & o)
{
x = o.x;
y = o.y;
z = o.z;
return *this;
}
// ------------------------------------------------------------------------------------------------
Vector3 & Vector3::operator = (Value s)
{
@ -310,7 +296,7 @@ Int32 Vector3::Cmp(const Vector3 & o) const
// ------------------------------------------------------------------------------------------------
CSStr Vector3::ToString() const
{
return ToStringF("%f,%f,%f", x, y, z);
return ToStrF("%f,%f,%f", x, y, z);
}
// ------------------------------------------------------------------------------------------------
@ -367,29 +353,21 @@ void Vector3::Generate()
void Vector3::Generate(Value min, Value max)
{
if (EpsLt(max, min))
{
SqThrow("max value is lower than min value");
}
else
{
x = GetRandomFloat32(min, max);
y = GetRandomFloat32(min, max);
z = GetRandomFloat32(min, max);
}
SqThrowF("max value is lower than min value");
x = GetRandomFloat32(min, max);
y = GetRandomFloat32(min, max);
z = GetRandomFloat32(min, max);
}
void Vector3::Generate(Value xmin, Value xmax, Value ymin, Value ymax, Value zmin, Value zmax)
{
if (EpsLt(xmax, xmin) || EpsLt(ymax, ymin) || EpsLt(zmax, zmin))
{
SqThrow("max value is lower than min value");
}
else
{
x = GetRandomFloat32(xmin, xmax);
y = GetRandomFloat32(ymin, ymax);
z = GetRandomFloat32(zmin, zmax);
}
SqThrowF("max value is lower than min value");
x = GetRandomFloat32(xmin, xmax);
y = GetRandomFloat32(ymin, ymax);
z = GetRandomFloat32(zmin, zmax);
}
// ------------------------------------------------------------------------------------------------
@ -418,6 +396,7 @@ void Register_Vector3(HSQUIRRELVM vm)
.Prop(_SC("abs"), &Vector3::Abs)
/* Core Metamethods */
.Func(_SC("_tostring"), &Vector3::ToString)
.SquirrelFunc(_SC("_typename"), &Vector3::Typename)
.Func(_SC("_cmp"), &Vector3::Cmp)
/* Metamethods */
.Func<Vector3 (Vector3::*)(const Vector3 &) const>(_SC("_add"), &Vector3::operator +)

View File

@ -8,294 +8,309 @@
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
*
* Class used to represent a three-dimensional vector.
*/
struct Vector3
{
/* --------------------------------------------------------------------------------------------
* ...
* The type of value used by components of type.
*/
typedef float Value;
/* --------------------------------------------------------------------------------------------
* ...
* Helper instances for common values mostly used as return types or comparison.
*/
static const Vector3 NIL;
static const Vector3 MIN;
static const Vector3 MAX;
/* --------------------------------------------------------------------------------------------
* ...
* The delimiter character to be used when extracting values from strings.
*/
static SQChar Delim;
/* --------------------------------------------------------------------------------------------
* ...
* The x, y and z components of this type.
*/
Value x, y, z;
/* --------------------------------------------------------------------------------------------
*
* Default constructor.
*/
Vector3();
/* --------------------------------------------------------------------------------------------
* ...
* Construct a vector with the same scalar value for all components.
*/
Vector3(Value sv);
/* --------------------------------------------------------------------------------------------
* ...
* Construct a vector with the specified component values.
*/
Vector3(Value xv, Value yv, Value zv);
/* --------------------------------------------------------------------------------------------
*
* Copy constructor.
*/
Vector3(const Vector3 & o);
Vector3(const Vector3 & o) = default;
/* --------------------------------------------------------------------------------------------
*
* Copy constructor.
*/
~Vector3();
Vector3(Vector3 && o) = default;
/* --------------------------------------------------------------------------------------------
*
* Destructor.
*/
Vector3 & operator = (const Vector3 & o);
~Vector3() = default;
/* --------------------------------------------------------------------------------------------
* ...
* Copy assignment operator.
*/
Vector3 & operator = (const Vector3 & o) = default;
/* --------------------------------------------------------------------------------------------
* Move assignment operator.
*/
Vector3 & operator = (Vector3 && o) = default;
/* --------------------------------------------------------------------------------------------
* Scalar value assignment operator.
*/
Vector3 & operator = (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Four-dimensional vector assignment.
*/
Vector3 & operator = (const Vector4 & v);
/* --------------------------------------------------------------------------------------------
* ...
* Quaternion rotation assignment.
*/
Vector3 & operator = (const Quaternion & q);
/* --------------------------------------------------------------------------------------------
* ...
* Addition assignment operator.
*/
Vector3 & operator += (const Vector3 & v);
/* --------------------------------------------------------------------------------------------
* ...
* Subtraction assignment operator.
*/
Vector3 & operator -= (const Vector3 & v);
/* --------------------------------------------------------------------------------------------
* ...
* Multiplication assignment operator.
*/
Vector3 & operator *= (const Vector3 & v);
/* --------------------------------------------------------------------------------------------
* ...
* Division assignment operator.
*/
Vector3 & operator /= (const Vector3 & v);
/* --------------------------------------------------------------------------------------------
* ...
* Modulo assignment operator.
*/
Vector3 & operator %= (const Vector3 & v);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value addition assignment operator.
*/
Vector3 & operator += (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value subtraction assignment operator.
*/
Vector3 & operator -= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value multiplication assignment operator.
*/
Vector3 & operator *= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value division assignment operator.
*/
Vector3 & operator /= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value modulo assignment operator.
*/
Vector3 & operator %= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Pre-increment operator.
*/
Vector3 & operator ++ ();
/* --------------------------------------------------------------------------------------------
* ...
* Pre-decrement operator.
*/
Vector3 & operator -- ();
/* --------------------------------------------------------------------------------------------
* ...
* Post-increment operator.
*/
Vector3 operator ++ (int);
/* --------------------------------------------------------------------------------------------
* ...
* Post-decrement operator.
*/
Vector3 operator -- (int);
/* --------------------------------------------------------------------------------------------
* ...
* Addition operator.
*/
Vector3 operator + (const Vector3 & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Subtraction operator.
*/
Vector3 operator - (const Vector3 & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Multiplication operator.
*/
Vector3 operator * (const Vector3 & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Division operator.
*/
Vector3 operator / (const Vector3 & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Modulo operator.
*/
Vector3 operator % (const Vector3 & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value addition operator.
*/
Vector3 operator + (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value subtraction operator.
*/
Vector3 operator - (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value multiplication operator.
*/
Vector3 operator * (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value division operator.
*/
Vector3 operator / (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value modulo operator.
*/
Vector3 operator % (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Unary plus operator.
*/
Vector3 operator + () const;
/* --------------------------------------------------------------------------------------------
* ...
* Unary minus operator.
*/
Vector3 operator - () const;
/* --------------------------------------------------------------------------------------------
* ...
* Equality comparison operator.
*/
bool operator == (const Vector3 & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Inequality comparison operator.
*/
bool operator != (const Vector3 & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Less than comparison operator.
*/
bool operator < (const Vector3 & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Greater than comparison operator.
*/
bool operator > (const Vector3 & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Less than or equal comparison operator.
*/
bool operator <= (const Vector3 & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Greater than or equal comparison operator.
*/
bool operator >= (const Vector3 & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Used by the script engine to compare two instances of this type.
*/
Int32 Cmp(const Vector3 & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Used by the script engine to convert an instance of this type to a string.
*/
CSStr ToString() const;
/* --------------------------------------------------------------------------------------------
* ...
* Used by the script engine to retrieve the name from instances of this type.
*/
static SQInteger Typename(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Set all components to the specified scalar value.
*/
void Set(Value ns);
/* --------------------------------------------------------------------------------------------
* ...
* Set all components to the specified values.
*/
void Set(Value nx, Value ny, Value nz);
/* --------------------------------------------------------------------------------------------
* ...
* Copy the values from another instance of this type.
*/
void Set(const Vector3 & v);
/* --------------------------------------------------------------------------------------------
* ...
* Copy the values from a four-dimensional vector.
*/
void Set(const Vector4 & v);
/* --------------------------------------------------------------------------------------------
* ...
* Copy the values from a quaternion rotation.
*/
void Set(const Quaternion & q);
/* --------------------------------------------------------------------------------------------
* ...
* Set the values extracted from the specified string using the specified delimiter.
*/
void Set(CSStr values, SQChar delim);
/* --------------------------------------------------------------------------------------------
* ...
* Generate random values for all components of this instance.
*/
void Generate();
/* --------------------------------------------------------------------------------------------
* ...
* Generate random values for all components of this instance within the specified bounds.
*/
void Generate(Value min, Value max);
/* --------------------------------------------------------------------------------------------
* ...
* Generate random values for all components of this instance within the specified bounds.
*/
void Generate(Value xmin, Value xmax, Value ymin, Value ymax, Value zmin, Value zmax);
/* --------------------------------------------------------------------------------------------
* ...
* Clear the component values to default.
*/
void Clear()
{
@ -303,7 +318,7 @@ struct Vector3
}
/* --------------------------------------------------------------------------------------------
* ...
* Retrieve a new instance of this type with absolute component values.
*/
Vector3 Abs() const;
};

View File

@ -16,6 +16,14 @@ const Vector4 Vector4::MAX = Vector4(NumLimit< Vector4::Value >::Max);
// ------------------------------------------------------------------------------------------------
SQChar Vector4::Delim = ',';
// ------------------------------------------------------------------------------------------------
SQInteger Vector4::Typename(HSQUIRRELVM vm)
{
static SQChar name[] = _SC("Vector4");
sq_pushstring(vm, name, sizeof(name));
return 1;
}
// ------------------------------------------------------------------------------------------------
Vector4::Vector4()
: x(0.0), y(0.0), z(0.0), w(0.0)
@ -44,29 +52,6 @@ Vector4::Vector4(Value xv, Value yv, Value zv, Value wv)
/* ... */
}
// ------------------------------------------------------------------------------------------------
Vector4::Vector4(const Vector4 & o)
: x(o.x), y(o.y), z(o.z), w(o.w)
{
/* ... */
}
// ------------------------------------------------------------------------------------------------
Vector4::~Vector4()
{
/* ... */
}
// ------------------------------------------------------------------------------------------------
Vector4 & Vector4::operator = (const Vector4 & o)
{
x = o.x;
y = o.y;
z = o.z;
w = o.w;
return *this;
}
// ------------------------------------------------------------------------------------------------
Vector4 & Vector4::operator = (Value s)
{
@ -335,7 +320,7 @@ Int32 Vector4::Cmp(const Vector4 & o) const
// ------------------------------------------------------------------------------------------------
CSStr Vector4::ToString() const
{
return ToStringF("%f,%f,%f,%f", x, y, z, w);
return ToStrF("%f,%f,%f,%f", x, y, z, w);
}
// ------------------------------------------------------------------------------------------------
@ -405,31 +390,23 @@ void Vector4::Generate()
void Vector4::Generate(Value min, Value max)
{
if (max < min)
{
SqThrow("max value is lower than min value");
}
else
{
x = GetRandomFloat32(min, max);
y = GetRandomFloat32(min, max);
z = GetRandomFloat32(min, max);
y = GetRandomFloat32(min, max);
}
SqThrowF("max value is lower than min value");
x = GetRandomFloat32(min, max);
y = GetRandomFloat32(min, max);
z = GetRandomFloat32(min, max);
y = GetRandomFloat32(min, max);
}
void Vector4::Generate(Value xmin, Value xmax, Value ymin, Value ymax, Value zmin, Value zmax, Value wmin, Value wmax)
{
if (EpsLt(xmax, xmin) || EpsLt(ymax, ymin) || EpsLt(zmax, zmin) || EpsLt(wmax, wmin))
{
SqThrow("max value is lower than min value");
}
else
{
x = GetRandomFloat32(xmin, xmax);
y = GetRandomFloat32(ymin, ymax);
z = GetRandomFloat32(zmin, zmax);
y = GetRandomFloat32(ymin, ymax);
}
SqThrowF("max value is lower than min value");
x = GetRandomFloat32(xmin, xmax);
y = GetRandomFloat32(ymin, ymax);
z = GetRandomFloat32(zmin, zmax);
y = GetRandomFloat32(ymin, ymax);
}
// ------------------------------------------------------------------------------------------------
@ -460,6 +437,7 @@ void Register_Vector4(HSQUIRRELVM vm)
.Prop(_SC("abs"), &Vector4::Abs)
/* Core Metamethods */
.Func(_SC("_tostring"), &Vector4::ToString)
.SquirrelFunc(_SC("_typename"), &Vector4::Typename)
.Func(_SC("_cmp"), &Vector4::Cmp)
/* Metamethods */
.Func<Vector4 (Vector4::*)(const Vector4 &) const>(_SC("_add"), &Vector4::operator +)

View File

@ -8,304 +8,319 @@
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
*
* Class used to represent a four-dimensional vector.
*/
struct Vector4
{
/* --------------------------------------------------------------------------------------------
* ...
* The type of value used by components of type.
*/
typedef float Value;
/* --------------------------------------------------------------------------------------------
* ...
* Helper instances for common values mostly used as return types or comparison.
*/
static const Vector4 NIL;
static const Vector4 MIN;
static const Vector4 MAX;
/* --------------------------------------------------------------------------------------------
* ...
* The delimiter character to be used when extracting values from strings.
*/
static SQChar Delim;
/* --------------------------------------------------------------------------------------------
* ...
* The x, y, z and w components of this type.
*/
Value x, y, z, w;
/* --------------------------------------------------------------------------------------------
*
* Default constructor.
*/
Vector4();
/* --------------------------------------------------------------------------------------------
* ...
* Construct a vector with the same scalar value for all components.
*/
Vector4(Value sv);
/* --------------------------------------------------------------------------------------------
* ...
* Construct a vector with the specified component values.
*/
Vector4(Value xv, Value yv, Value zv);
/* --------------------------------------------------------------------------------------------
* ...
* Construct a vector with the specified component values.
*/
Vector4(Value xv, Value yv, Value zv, Value wv);
/* --------------------------------------------------------------------------------------------
*
* Copy constructor.
*/
Vector4(const Vector4 & o);
Vector4(const Vector4 & o) = default;
/* --------------------------------------------------------------------------------------------
*
* Move constructor.
*/
~Vector4();
Vector4(Vector4 && o) = default;
/* --------------------------------------------------------------------------------------------
*
* Destructor.
*/
Vector4 & operator = (const Vector4 & o);
~Vector4() = default;
/* --------------------------------------------------------------------------------------------
* ...
* Copy assignment operator.
*/
Vector4 & operator = (const Vector4 & o) = default;
/* --------------------------------------------------------------------------------------------
* Move assignment operator.
*/
Vector4 & operator = (Vector4 && o) = default;
/* --------------------------------------------------------------------------------------------
* Scalar value assignment operator.
*/
Vector4 & operator = (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Three-dimensional vector assignment operator.
*/
Vector4 & operator = (const Vector3 & v);
/* --------------------------------------------------------------------------------------------
* ...
* Quaternion rotation assignment operator.
*/
Vector4 & operator = (const Quaternion & q);
/* --------------------------------------------------------------------------------------------
* ...
* Addition assignment operator.
*/
Vector4 & operator += (const Vector4 & v);
/* --------------------------------------------------------------------------------------------
* ...
* Subtraction assignment operator.
*/
Vector4 & operator -= (const Vector4 & v);
/* --------------------------------------------------------------------------------------------
* ...
* Multiplication assignment operator.
*/
Vector4 & operator *= (const Vector4 & v);
/* --------------------------------------------------------------------------------------------
* ...
* Division assignment operator.
*/
Vector4 & operator /= (const Vector4 & v);
/* --------------------------------------------------------------------------------------------
* ...
* Modulo assignment operator.
*/
Vector4 & operator %= (const Vector4 & v);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value addition assignment operator.
*/
Vector4 & operator += (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value subtraction assignment operator.
*/
Vector4 & operator -= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value multiplication assignment operator.
*/
Vector4 & operator *= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value division assignment operator.
*/
Vector4 & operator /= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value modulo assignment operator.
*/
Vector4 & operator %= (Value s);
/* --------------------------------------------------------------------------------------------
* ...
* Pre-increment operator.
*/
Vector4 & operator ++ ();
/* --------------------------------------------------------------------------------------------
* ...
* Pre-decrement operator.
*/
Vector4 & operator -- ();
/* --------------------------------------------------------------------------------------------
* ...
* Post-increment operator.
*/
Vector4 operator ++ (int);
/* --------------------------------------------------------------------------------------------
* ...
* Post-decrement operator.
*/
Vector4 operator -- (int);
/* --------------------------------------------------------------------------------------------
* ...
* Addition operator.
*/
Vector4 operator + (const Vector4 & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Subtraction operator.
*/
Vector4 operator - (const Vector4 & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Multiplication operator.
*/
Vector4 operator * (const Vector4 & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Division operator.
*/
Vector4 operator / (const Vector4 & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Modulo operator.
*/
Vector4 operator % (const Vector4 & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value addition operator.
*/
Vector4 operator + (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value subtraction operator.
*/
Vector4 operator - (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value multiplication operator.
*/
Vector4 operator * (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value division operator.
*/
Vector4 operator / (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Scalar value modulo operator.
*/
Vector4 operator % (Value s) const;
/* --------------------------------------------------------------------------------------------
* ...
* Unary plus operator.
*/
Vector4 operator + () const;
/* --------------------------------------------------------------------------------------------
* ...
* Unary minus operator.
*/
Vector4 operator - () const;
/* --------------------------------------------------------------------------------------------
* ...
* Equality comparison operator.
*/
bool operator == (const Vector4 & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Inequality comparison operator.
*/
bool operator != (const Vector4 & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Less than comparison operator.
*/
bool operator < (const Vector4 & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Greater than comparison operator.
*/
bool operator > (const Vector4 & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Less than or equal comparison operator.
*/
bool operator <= (const Vector4 & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Greater than or equal comparison operator.
*/
bool operator >= (const Vector4 & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Used by the script engine to compare two instances of this type.
*/
Int32 Cmp(const Vector4 & v) const;
/* --------------------------------------------------------------------------------------------
* ...
* Used by the script engine to convert an instance of this type to a string.
*/
CSStr ToString() const;
/* --------------------------------------------------------------------------------------------
* ...
* Used by the script engine to retrieve the name from instances of this type.
*/
static SQInteger Typename(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Set all components to the specified scalar value.
*/
void Set(Value ns);
/* --------------------------------------------------------------------------------------------
* ...
* Set all components to the specified values.
*/
void Set(Value nx, Value ny, Value nz);
/* --------------------------------------------------------------------------------------------
* ...
* Set all components to the specified values.
*/
void Set(Value nx, Value ny, Value nz, Value nw);
/* --------------------------------------------------------------------------------------------
* ...
* Copy the values from another instance of this type.
*/
void Set(const Vector4 & v);
/* --------------------------------------------------------------------------------------------
* ...
* Copy the values from a three-dimensional vector.
*/
void Set(const Vector3 & v);
/* --------------------------------------------------------------------------------------------
* ...
* Copy the values from a quaternion rotation.
*/
void Set(const Quaternion & q);
/* --------------------------------------------------------------------------------------------
* ...
* Set the values extracted from the specified string using the specified delimiter.
*/
void Set(CSStr values, SQChar delim);
/* --------------------------------------------------------------------------------------------
* ...
* Generate random values for all components of this instance.
*/
void Generate();
/* --------------------------------------------------------------------------------------------
* ...
* Generate random values for all components of this instance within the specified bounds.
*/
void Generate(Value min, Value max);
/* --------------------------------------------------------------------------------------------
* ...
* Generate random values for all components of this instance within the specified bounds.
*/
void Generate(Value xmin, Value xmax, Value ymin, Value ymax, Value zmin, Value zmax, Value wmin, Value wmax);
/* --------------------------------------------------------------------------------------------
* ...
* Clear the component values to default.
*/
void Clear()
{
@ -313,7 +328,7 @@ struct Vector4
}
/* --------------------------------------------------------------------------------------------
* ...
* Retrieve a new instance of this type with absolute component values.
*/
Vector4 Abs() const;
};

File diff suppressed because it is too large Load Diff

View File

@ -165,10 +165,19 @@ protected:
*/
template < typename T > void SqError(Int32 type, CSStr msg, T data)
{
if (!m_OnError.IsNull())
// Is there a callback that deals with errors?
if (m_OnError.IsNull())
return;
// Attempt to forward the error to that callback
try
{
m_OnError.Execute< Int32, CSStr, T >(type, msg, data);
}
catch (const Sqrat::Exception & e)
{
// We can only log this incident and in the future maybe also include the location
LogErr("Command error callback failed [%s]", e.Message().c_str());
}
}
/* --------------------------------------------------------------------------------------------
@ -350,7 +359,7 @@ protected:
/* --------------------------------------------------------------------------------------------
*
*/
bool ProcSpec(CSStr spec);
void ProcSpec(CSStr spec);
private:

View File

@ -48,13 +48,6 @@ extern void TerminateCommand();
// ------------------------------------------------------------------------------------------------
Core * _Core = NULL;
// ------------------------------------------------------------------------------------------------
static void CalculateStringIDs(SQChar arr[][8], Uint32 num)
{
for (Uint32 n = 0; n < num; n++)
snprintf(arr[n], 8, "%d", n);
}
// ------------------------------------------------------------------------------------------------
Core::Core()
: m_State(0)
@ -100,19 +93,6 @@ bool Core::Init()
m_Textdraws.resize(SQMOD_TEXTDRAW_POOL);
m_Vehicles.resize(SQMOD_VEHICLE_POOL);
LogDbg("Pre-calculating entity string identifiers");
// Pre-calculate all possible entity IDs for fast string conversion
CalculateStringIDs(CBlip::s_StrID, SQMOD_BLIP_POOL);
CalculateStringIDs(CCheckpoint::s_StrID, SQMOD_CHECKPOINT_POOL);
CalculateStringIDs(CForcefield::s_StrID, SQMOD_FORCEFIELD_POOL);
CalculateStringIDs(CKeybind::s_StrID, SQMOD_KEYBIND_POOL);
CalculateStringIDs(CObject::s_StrID, SQMOD_OBJECT_POOL);
CalculateStringIDs(CPickup::s_StrID, SQMOD_PICKUP_POOL);
CalculateStringIDs(CPlayer::s_StrID, SQMOD_PLAYER_POOL);
CalculateStringIDs(CSprite::s_StrID, SQMOD_SPRITE_POOL);
CalculateStringIDs(CTextdraw::s_StrID, SQMOD_TEXTDRAW_POOL);
CalculateStringIDs(CVehicle::s_StrID, SQMOD_VEHICLE_POOL);
LogDbg("Initializing entity options to defaults");
// Initialize player messaging options to default values
for (Players::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
@ -154,148 +134,130 @@ bool Core::Init()
// Attempt to read the database port number
try
{
Ulong num = strtoul(conf.GetValue("Config", "StackSize", "0"), NULL, 10);
// Make sure that the retrieved number is in range
Ulong num = conf.GetLongValue("Config", "StackSize", SQMOD_STACK_SIZE);
// Make sure that the retrieved number is within range
if (!num)
{
throw std::out_of_range("stack size too small");
}
else if (num >= NumLimit< Uint16 >::Max)
{
else if (num >= std::numeric_limits< Uint16 >::max())
throw std::out_of_range("stack size too big");
}
// Save the port number
stack_size = (Uint16)num;
stack_size = static_cast< Uint16 >(num);
}
catch (const std::exception & e)
{
LogWrn("Unable to obtain the stack size [%s]", e.what());
LogWrn("Unable to obtain a valid stack size [%s]", e.what());
}
LogDbg("Creating virtual machine with a stack size (%d)", stack_size);
LogDbg("Creating a virtual machine with a stack size of (%d)", stack_size);
// Attempt to create the VM
m_VM = sq_open(stack_size);
// See if the virtual machine could be created
if (cLogFtl(!m_VM, "Unable to create the virtual machine"))
{
m_VM = NULL;
// Explicitly prevent further use of this pointer
m_VM = nullptr;
// Unable to load the plugin properly
return false;
}
// Set this as the default VM and enable error handling
// Set this as the default VM
DefaultVM::Set(m_VM);
// Enable error handling
ErrorHandling::Enable(true);
LogDbg("Registering the standard libraries");
// Register the standard library on the root table
// Push the root table on the stack
sq_pushroottable(m_VM);
// Register the standard library on the pushed table
sqstd_register_iolib(m_VM);
sqstd_register_bloblib(m_VM);
sqstd_register_mathlib(m_VM);
sqstd_register_systemlib(m_VM);
sqstd_register_stringlib(m_VM);
// Pop the root table from the stack
sq_pop(m_VM, 1);
LogDbg("Setting the base output function");
// Tell the VM to use these functions to output user on error messages
sq_setprintfunc(m_VM, PrintFunc, ErrorFunc);
LogDbg("Setting the base error handlers");
// Tell the VM to trigger this function on compile time errors
sq_setcompilererrorhandler(m_VM, CompilerErrorHandler);
// Push the runtime error handler on the stack and create a closure
sq_newclosure(m_VM, RuntimeErrorHandler, 0);
// Tell the VM to trigger this function on runtime errors
sq_seterrorhandler(m_VM);
LogDbg("Registering the plug-in API");
// Attempt to register the plugin API
if (cLogFtl(!RegisterAPI(m_VM), "Unable to register the plug-in API"))
return false;
return false; // Can't execute scripts without a valid API!
// Attempt to retrieve the list of strings specified in the config
CSimpleIniA::TNamesDepend scripts;
conf.GetAllValues("Scripts", "Source", scripts);
// See if any script was specified
if (scripts.size() <= 0)
if (scripts.size() <= 0 && !conf.GetBoolValue("Config", "EmptyInit", false))
{
LogWrn("No scripts specified in the configuration file");
// No point in loading the plug-in
return false;
}
// Sort the list in it's original order
scripts.sort(CSimpleIniA::Entry::LoadOrder());
// Process each specified script path
for (CSimpleIniA::TNamesDepend::iterator itr = scripts.begin(); itr != scripts.end(); ++itr)
else
{
// Get the file path as a string
String path(itr->pItem);
// See if the specified script path is valid
if (path.empty())
{
// Simply ignore it
continue;
}
// See if it wasn't already loaded
else if (m_Scripts.find(path) != m_Scripts.end())
{
LogWrn("Script was specified before: %s", path.c_str());
// No point in loading it again
continue;
}
// Create a new script container and insert it into the script pool
std::pair< Scripts::iterator, bool > res = m_Scripts.insert(Scripts::value_type(path, Script(m_VM)));
// We don't compile the scripts yet. We just store their path and prepare the objects.
if (!res.second)
{
LogErr("Unable to queue script: %s", path.c_str());
// Drop all previous scripts
m_Scripts.clear();
// Failed to compile the specified script
return false;
}
// Sort the list in it's original order
scripts.sort(CSimpleIniA::Entry::LoadOrder());
// Process each specified script paths
for (const auto & script : scripts)
// Attempt to queue the specified script path for loading
LoadScript(script.pItem);
}
// See if any script could be compiled
// See if any script could be queued for loading
if (m_Scripts.empty() && !conf.GetBoolValue("Config", "EmptyInit", false))
{
LogErr("No scripts compiled. No reason to load the plug-in");
LogErr("No scripts loaded. No reason to load the plug-in");
// No point in loading the plug-in
return false;
}
LogDbg("Reading the options from the general section");
// Read options only after compilation was successful
// Read options only after loading was successful
CSimpleIniA::TNamesDepend options;
// Are there any options to load?
// Are there any options to read?
if (conf.GetAllKeys("Options", options) || options.size() > 0)
{
// Process all the specified keys under the [Options] section
for (CSimpleIniA::TNamesDepend::iterator itr = options.begin(); itr != options.end(); ++itr)
for (const auto & option : options)
{
CSimpleIniA::TNamesDepend optlist;
// Get all keys with the same name
if (!conf.GetAllValues("Options", itr->pItem, optlist))
{
CSimpleIniA::TNamesDepend values;
// Get the values of all keys with the same name
if (!conf.GetAllValues("Options", option.pItem, values))
continue;
}
// Sort the keys in their original order
optlist.sort(CSimpleIniA::Entry::LoadOrder());
// Process each option and overwrite existing values
for (CSimpleIniA::TNamesDepend::iterator opt = optlist.begin(); opt != optlist.end(); ++opt)
{
m_Options[itr->pItem] = opt->pItem;
}
values.sort(CSimpleIniA::Entry::LoadOrder());
// Save each option option and overwrite existing value
for (const auto & value : values)
m_Options[option.pItem] = value.pItem;
}
}
else
{
LogInf("No options specified in the configuration file");
}
LogDbg("Applying the specified logging filters");
// Apply the specified logging filters only after initialization was completed
if (!SToB(conf.GetValue("Log", "Debug", "true"))) _Log->DisableLevel(LL_DBG);
if (!SToB(conf.GetValue("Log", "User", "true"))) _Log->DisableLevel(LL_USR);
if (!SToB(conf.GetValue("Log", "Success", "true"))) _Log->DisableLevel(LL_SCS);
if (!SToB(conf.GetValue("Log", "Info", "true"))) _Log->DisableLevel(LL_INF);
if (!SToB(conf.GetValue("Log", "Warning", "true"))) _Log->DisableLevel(LL_WRN);
if (!SToB(conf.GetValue("Log", "Error", "true"))) _Log->DisableLevel(LL_ERR);
if (!SToB(conf.GetValue("Log", "Fatal", "true"))) _Log->DisableLevel(LL_FTL);
if (!conf.GetBoolValue("Log", "Debug", true))
_Log->DisableLevel(LL_DBG);
if (!conf.GetBoolValue("Log", "User", true))
_Log->DisableLevel(LL_USR);
if (!conf.GetBoolValue("Log", "Success", true))
_Log->DisableLevel(LL_SCS);
if (!conf.GetBoolValue("Log", "Info", true))
_Log->DisableLevel(LL_INF);
if (!conf.GetBoolValue("Log", "Warning", true))
_Log->DisableLevel(LL_WRN);
if (!conf.GetBoolValue("Log", "Error", true))
_Log->DisableLevel(LL_ERR);
if (!conf.GetBoolValue("Log", "Fatal", true))
_Log->DisableLevel(LL_FTL);
// Initialization successful
return true;
@ -306,7 +268,8 @@ bool Core::Load()
{
// Are there any scripts to execute?
if (cLogErr(m_Scripts.empty(), "No scripts to execute. Plug-in has no purpose"))
return false;
return false; // No reason to load the plug-in
LogDbg("Signaling outside plugins to register their API");
// Signal outside plugins to do their monkey business
_Func->SendCustomCommand(0xDEADBABE, "");
@ -316,18 +279,29 @@ bool Core::Load()
for (Scripts::iterator itr = m_Scripts.begin(); itr != m_Scripts.end(); ++itr)
{
// Attempt to load and compile the script file
itr->second.CompileFile(itr->first);
// See if any compile time error occurred during compilation
if (Error::Occurred(m_VM))
return false; /* Failed to load properly */
// Attempt to execute the script
itr->second.Run();
// See if the executed script had any errors
if (Error::Occurred(m_VM))
// Failed to execute scripts
return false; /* Failed to load properly */
else
LogScs("Successfully executed script: %s", itr->first.c_str());
try
{
itr->second.CompileFile(itr->first);
}
catch (const Sqrat::Exception & e)
{
LogFtl("Unable to compile: %s", itr->first.c_str());
// Failed to load properly
return false;
}
// Attempt to execute the compiled script code
try
{
itr->second.Run();
}
catch (const Sqrat::Exception & e)
{
LogFtl("Unable to execute: %s", itr->first.c_str());
// Failed to load properly
return false;
}
// At this point the script should be completely loaded
LogScs("Successfully executed script: %s", itr->first.c_str());
}
// Successfully loaded
return true;
@ -382,6 +356,25 @@ void Core::SetOption(const String & name, const String & value)
m_Options[name] = value;
}
// ------------------------------------------------------------------------------------------------
bool Core::LoadScript(CSStr filepath)
{
// Is the specified path empty?
if (!filepath || *filepath == 0)
return false; // Simply ignore it
// Get the file path as a string
String path(filepath);
// See if it wasn't already loaded
if (m_Scripts.find(path) != m_Scripts.end())
LogWrn("Script was specified before: %s", path.c_str());
// We don't compile the scripts yet. We just store their path and prepare the objects.
else
// Create a new script container and insert it into the script pool
m_Scripts.emplace(std::move(path), Script(m_VM));
// At this point the script exists in the pool
return true;
}
// ------------------------------------------------------------------------------------------------
void Core::PrintFunc(HSQUIRRELVM vm, CSStr msg, ...)
{
@ -1720,8 +1713,8 @@ void Core::ResetInst(BlipInst & inst)
inst.mWorld = -1;
inst.mScale = -1;
inst.mSprID = -1;
//inst.mPosition.Clear();
//inst.mColor.Clear();
inst.mPosition.Clear();
inst.mColor.Clear();
}
void Core::ResetInst(CheckpointInst & inst)
@ -1740,9 +1733,9 @@ void Core::ResetInst(KeybindInst & inst)
{
inst.mID = -1;
inst.mFlags = ENF_DEFAULT;
inst.mPrimary = -1;
inst.mSecondary = -1;
inst.mAlternative = -1;
inst.mFirst = -1;
inst.mSecond = -1;
inst.mThird = -1;
inst.mRelease = -1;
}

View File

@ -155,9 +155,9 @@ protected:
Object mObj;
// ----------------------------------------------------------------------------------------
Int32 mPrimary;
Int32 mSecondary;
Int32 mAlternative;
Int32 mFirst;
Int32 mSecond;
Int32 mThird;
Int32 mRelease;
// ----------------------------------------------------------------------------------------
@ -392,6 +392,8 @@ protected:
Function mOnDisembark;
};
public:
// --------------------------------------------------------------------------------------------
typedef std::vector< BlipInst > Blips;
typedef std::vector< CheckpointInst > Checkpoints;
@ -483,8 +485,15 @@ public:
/* --------------------------------------------------------------------------------------------
* State mutators.
*/
void SetState(Int32 val) { m_State = val; }
Int32 GetState() const { return m_State; }
void SetState(Int32 val)
{
m_State = val;
}
Int32 GetState() const
{
return m_State;
}
/* --------------------------------------------------------------------------------------------
* Option mutators.
@ -495,7 +504,15 @@ public:
/* --------------------------------------------------------------------------------------------
* Retrieve the virtual machine.
*/
HSQUIRRELVM GetVM() const { return m_VM; }
HSQUIRRELVM GetVM() const
{
return m_VM;
}
/* --------------------------------------------------------------------------------------------
* Adds a script to the load queue.
*/
bool LoadScript(CSStr filepath);
protected:
@ -578,6 +595,20 @@ public:
TextdrawInst & GetTextdraw(Int32 id) { return m_Textdraws.at(id); }
VehicleInst & GetVehicle(Int32 id) { return m_Vehicles.at(id); }
/* --------------------------------------------------------------------------------------------
* Pool retrievers.
*/
const Blips & GetBlips() const { return m_Blips; }
const Checkpoints & GetCheckpoints() const { return m_Checkpoints; }
const Forcefields & GetForcefields() const { return m_Forcefields; }
const Keybinds & GetKeybinds() const { return m_Keybinds; }
const Objects & GetObjects() const { return m_Objects; }
const Pickups & GetPickups() const { return m_Pickups; }
const Players & GetPlayers() const { return m_Players; }
const Sprites & GetSprites() const { return m_Sprites; }
const Textdraws & GetTextdraws() const { return m_Textdraws; }
const Vehicles & GetVehicles() const { return m_Vehicles; }
protected:
/* --------------------------------------------------------------------------------------------

View File

@ -6,15 +6,20 @@
namespace SqMod {
// ------------------------------------------------------------------------------------------------
SQChar CBlip::s_StrID[SQMOD_BLIP_POOL][8];
const Int32 CBlip::Max = SQMOD_BLIP_POOL;
// ------------------------------------------------------------------------------------------------
const Int32 CBlip::Max = SQMOD_BLIP_POOL;
SQInteger CBlip::Typename(HSQUIRRELVM vm)
{
static SQChar name[] = _SC("SqBlip");
sq_pushstring(vm, name, sizeof(name));
return 1;
}
// ------------------------------------------------------------------------------------------------
CBlip::CBlip(Int32 id)
: m_ID(VALID_ENTITYGETEX(id, SQMOD_BLIP_POOL))
, m_Tag(VALID_ENTITY(m_ID) ? s_StrID[m_ID] : _SC("-1"))
, m_Tag(ToStrF("%d", id))
{
/* ... */
}
@ -36,153 +41,183 @@ Int32 CBlip::Cmp(const CBlip & o) const
return -1;
}
CSStr CBlip::ToString() const
// ------------------------------------------------------------------------------------------------
const String & CBlip::ToString() const
{
return VALID_ENTITYEX(m_ID, SQMOD_BLIP_POOL) ? s_StrID[m_ID] : _SC("-1");
return m_Tag;
}
// ------------------------------------------------------------------------------------------------
CSStr CBlip::GetTag() const
const String & CBlip::GetTag() const
{
return m_Tag.c_str();
return m_Tag;
}
// ------------------------------------------------------------------------------------------------
void CBlip::SetTag(CSStr tag)
{
m_Tag.assign(tag);
}
// ------------------------------------------------------------------------------------------------
Object & CBlip::GetData()
{
if (Validate())
return m_Data;
return NullObject();
// Validate the managed identifier
Validate();
// Return the requested information
return m_Data;
}
// ------------------------------------------------------------------------------------------------
void CBlip::SetData(Object & data)
{
if (Validate())
m_Data = data;
// Validate the managed identifier
Validate();
// Apply the specified value
m_Data = data;
}
// ------------------------------------------------------------------------------------------------
bool CBlip::Destroy(Int32 header, Object & payload)
{
// Validate the managed identifier
Validate();
// Perform the requested operation
return _Core->DelBlip(m_ID, header, payload);
}
// ------------------------------------------------------------------------------------------------
bool CBlip::BindEvent(Int32 evid, Object & env, Function & func) const
void CBlip::BindEvent(Int32 evid, Object & env, Function & func) const
{
if (!Validate())
return false;
// Validate the managed identifier
Validate();
// Obtain the function instance called for this event
Function & event = _Core->GetBlipEvent(m_ID, evid);
// Is the specified callback function null?
if (func.IsNull())
event.Release();
event.Release(); // Then release the current callback
// Assign the specified environment and function
else
event = Function(env.GetVM(), env, func.GetFunc());
return true;
}
// ------------------------------------------------------------------------------------------------
Int32 CBlip::GetWorld() const
{
if (Validate())
return _Core->GetBlip(m_ID).mWorld;
return -1;
// Validate the managed identifier
Validate();
// Return the requested information
return _Core->GetBlip(m_ID).mWorld;
}
// ------------------------------------------------------------------------------------------------
Int32 CBlip::GetScale() const
{
if (Validate())
return _Core->GetBlip(m_ID).mScale;
return -1;
// Validate the managed identifier
Validate();
// Return the requested information
return _Core->GetBlip(m_ID).mScale;
}
// ------------------------------------------------------------------------------------------------
const Vector3 & CBlip::GetPosition() const
{
if (Validate())
return _Core->GetBlip(m_ID).mPosition;
return Vector3::NIL;
// Validate the managed identifier
Validate();
// Return the requested information
return _Core->GetBlip(m_ID).mPosition;
}
// ------------------------------------------------------------------------------------------------
const Color4 & CBlip::GetColor() const
{
if (Validate())
return _Core->GetBlip(m_ID).mColor;
return Color4::NIL;
// Validate the managed identifier
Validate();
// Return the requested information
return _Core->GetBlip(m_ID).mColor;
}
// ------------------------------------------------------------------------------------------------
Int32 CBlip::GetSprID() const
{
if (Validate())
return _Core->GetBlip(m_ID).mSprID;
return -1;
// Validate the managed identifier
Validate();
// Return the requested information
return _Core->GetBlip(m_ID).mSprID;
}
// ------------------------------------------------------------------------------------------------
Float32 CBlip::GetPosX() const
{
if (Validate())
return _Core->GetBlip(m_ID).mPosition.x;
return 0;
// Validate the managed identifier
Validate();
// Return the requested information
return _Core->GetBlip(m_ID).mPosition.x;
}
// ------------------------------------------------------------------------------------------------
Float32 CBlip::GetPosY() const
{
if (Validate())
return _Core->GetBlip(m_ID).mPosition.y;
return 0;
// Validate the managed identifier
Validate();
// Return the requested information
return _Core->GetBlip(m_ID).mPosition.y;
}
// ------------------------------------------------------------------------------------------------
Float32 CBlip::GetPosZ() const
{
if (Validate())
return _Core->GetBlip(m_ID).mPosition.z;
return 0;
// Validate the managed identifier
Validate();
// Return the requested information
return _Core->GetBlip(m_ID).mPosition.z;
}
// ------------------------------------------------------------------------------------------------
Int32 CBlip::GetColorR() const
{
if (Validate())
return _Core->GetBlip(m_ID).mColor.r;
return 0;
}
Int32 CBlip::GetColorG() const
{
if (Validate())
return _Core->GetBlip(m_ID).mColor.g;
return 0;
}
Int32 CBlip::GetColorB() const
{
if (Validate())
return _Core->GetBlip(m_ID).mColor.b;
return 0;
}
Int32 CBlip::GetColorA() const
{
if (Validate())
return _Core->GetBlip(m_ID).mColor.a;
return 0;
// Validate the managed identifier
Validate();
// Return the requested information
return _Core->GetBlip(m_ID).mColor.r;
}
// ------------------------------------------------------------------------------------------------
static Object & CreateBlipEx(Int32 world, Float32 x, Float32 y, Float32 z, Int32 scale,
Int32 CBlip::GetColorG() const
{
// Validate the managed identifier
Validate();
// Return the requested information
return _Core->GetBlip(m_ID).mColor.g;
}
// ------------------------------------------------------------------------------------------------
Int32 CBlip::GetColorB() const
{
// Validate the managed identifier
Validate();
// Return the requested information
return _Core->GetBlip(m_ID).mColor.b;
}
// ------------------------------------------------------------------------------------------------
Int32 CBlip::GetColorA() const
{
// Validate the managed identifier
Validate();
// Return the requested information
return _Core->GetBlip(m_ID).mColor.a;
}
// ------------------------------------------------------------------------------------------------
static Object & Blip_CreateEx(Int32 world, Float32 x, Float32 y, Float32 z, Int32 scale,
Uint8 r, Uint8 g, Uint8 b, Uint8 a, Int32 sprid)
{
return _Core->NewBlip(-1, world, x, y, z, scale, SQMOD_PACK_RGBA(r, g, b, a), sprid,
SQMOD_CREATE_DEFAULT, NullObject());
}
static Object & CreateBlipEx(Int32 world, Float32 x, Float32 y, Float32 z, Int32 scale,
static Object & Blip_CreateEx(Int32 world, Float32 x, Float32 y, Float32 z, Int32 scale,
Uint8 r, Uint8 g, Uint8 b, Uint8 a, Int32 sprid,
Int32 header, Object & payload)
{
@ -191,14 +226,14 @@ static Object & CreateBlipEx(Int32 world, Float32 x, Float32 y, Float32 z, Int32
}
// ------------------------------------------------------------------------------------------------
static Object & CreateBlipEx(Int32 index, Int32 world, Float32 x, Float32 y, Float32 z,
static Object & Blip_CreateEx(Int32 index, Int32 world, Float32 x, Float32 y, Float32 z,
Int32 scale, Uint8 r, Uint8 g, Uint8 b, Uint8 a, Int32 sprid)
{
return _Core->NewBlip(index, world, x, y, z, scale, SQMOD_PACK_RGBA(r, g, b, a), sprid,
SQMOD_CREATE_DEFAULT, NullObject());
}
static Object & CreateBlipEx(Int32 index, Int32 world, Float32 x, Float32 y, Float32 z, Int32 scale,
static Object & Blip_CreateEx(Int32 index, Int32 world, Float32 x, Float32 y, Float32 z, Int32 scale,
Uint8 r, Uint8 g, Uint8 b, Uint8 a, Int32 sprid,
Int32 header, Object & payload)
{
@ -207,14 +242,14 @@ static Object & CreateBlipEx(Int32 index, Int32 world, Float32 x, Float32 y, Flo
}
// ------------------------------------------------------------------------------------------------
static Object & CreateBlip(Int32 world, const Vector3 & pos, Int32 scale, const Color4 & color,
static Object & Blip_Create(Int32 world, const Vector3 & pos, Int32 scale, const Color4 & color,
Int32 sprid)
{
return _Core->NewBlip(-1, world, pos.x, pos.y, pos.z, scale, color.GetRGBA(), sprid,
SQMOD_CREATE_DEFAULT, NullObject());
}
static Object & CreateBlip(Int32 world, const Vector3 & pos, Int32 scale, const Color4 & color,
static Object & Blip_Create(Int32 world, const Vector3 & pos, Int32 scale, const Color4 & color,
Int32 sprid, Int32 header, Object & payload)
{
return _Core->NewBlip(-1, world, pos.x, pos.y, pos.z, scale, color.GetRGBA(), sprid,
@ -222,41 +257,82 @@ static Object & CreateBlip(Int32 world, const Vector3 & pos, Int32 scale, const
}
// ------------------------------------------------------------------------------------------------
static Object & CreateBlip(Int32 index, Int32 world, const Vector3 & pos, Int32 scale,
static Object & Blip_Create(Int32 index, Int32 world, const Vector3 & pos, Int32 scale,
const Color4 & color, Int32 sprid)
{
return _Core->NewBlip(index, world, pos.x, pos.y, pos.z, scale, color.GetRGBA(), sprid,
SQMOD_CREATE_DEFAULT, NullObject());
}
static Object & CreateBlip(Int32 index, Int32 world, const Vector3 & pos, Int32 scale,
static Object & Blip_Create(Int32 index, Int32 world, const Vector3 & pos, Int32 scale,
const Color4 & color, Int32 sprid, Int32 header, Object & payload)
{
return _Core->NewBlip(index, world, pos.x, pos.y, pos.z, scale, color.GetRGBA(), sprid,
header, payload);
}
// ------------------------------------------------------------------------------------------------
static const Object & Blip_FindByID(Int32 id)
{
// Perform a range check on the specified identifier
if (INVALID_ENTITYEX(id, SQMOD_BLIP_POOL))
SqThrowF("The specified blip identifier is invalid: %d", id);
// Obtain the ends of the entity pool
Core::Blips::const_iterator itr = _Core->GetBlips().cbegin();
Core::Blips::const_iterator end = _Core->GetBlips().cend();
// Process each entity in the pool
for (; itr != end; ++itr)
{
// Does the identifier match the specified one?
if (itr->mID == id)
return itr->mObj; // Stop searching and return this entity
}
// Unable to locate a blip matching the specified identifier
return NullObject();
}
static const Object & Blip_FindByTag(CSStr tag)
{
// Perform a validity check on the specified tag
if (!tag || *tag == 0)
SqThrowF("The specified blip tag is invalid: null/empty");
// Obtain the ends of the entity pool
Core::Blips::const_iterator itr = _Core->GetBlips().cbegin();
Core::Blips::const_iterator end = _Core->GetBlips().cend();
// Process each entity in the pool
for (; itr != end; ++itr)
{
// Does this entity even exist and does the tag match the specified one?
if (itr->mInst != nullptr && itr->mInst->GetTag().compare(tag) == 0)
return itr->mObj; // Stop searching and return this entity
}
// Unable to locate a blip matching the specified tag
return NullObject();
}
// ================================================================================================
void Register_CBlip(HSQUIRRELVM vm)
{
RootTable(vm).Bind(_SC("SqBlip"),
Class< CBlip, NoConstructor< CBlip > >(vm, _SC("SqBlip"))
/* Metamethods */
// Metamethods
.Func(_SC("_cmp"), &CBlip::Cmp)
.SquirrelFunc(_SC("_typename"), &CBlip::Typename)
.Func(_SC("_tostring"), &CBlip::ToString)
/* Core Properties */
// Static values
.SetStaticValue(_SC("MaxID"), CBlip::Max)
// Core Properties
.Prop(_SC("ID"), &CBlip::GetID)
.Prop(_SC("Tag"), &CBlip::GetTag, &CBlip::SetTag)
.Prop(_SC("Data"), &CBlip::GetData, &CBlip::SetData)
.Prop(_SC("MaxID"), &CBlip::GetMaxID)
.Prop(_SC("Active"), &CBlip::IsActive)
/* Core Functions */
// Core Functions
.Func(_SC("Bind"), &CBlip::BindEvent)
/* Core Overloads */
// Core Overloads
.Overload< bool (CBlip::*)(void) >(_SC("Destroy"), &CBlip::Destroy)
.Overload< bool (CBlip::*)(Int32) >(_SC("Destroy"), &CBlip::Destroy)
.Overload< bool (CBlip::*)(Int32, Object &) >(_SC("Destroy"), &CBlip::Destroy)
/* Properties */
// Properties
.Prop(_SC("World"), &CBlip::GetWorld)
.Prop(_SC("Scale"), &CBlip::GetScale)
.Prop(_SC("Pos"), &CBlip::GetPosition)
@ -270,25 +346,24 @@ void Register_CBlip(HSQUIRRELVM vm)
.Prop(_SC("G"), &CBlip::GetColorG)
.Prop(_SC("B"), &CBlip::GetColorB)
.Prop(_SC("A"), &CBlip::GetColorA)
// Static Overloads
.StaticOverload< Object & (*)(Int32, Float32, Float32, Float32, Int32, Uint8, Uint8, Uint8, Uint8, Int32) >
(_SC("CreateEx"), &Blip_CreateEx)
.StaticOverload< Object & (*)(Int32, Float32, Float32, Float32, Int32, Uint8, Uint8, Uint8, Uint8, Int32, Int32, Object &) >
(_SC("CreateEx"), &Blip_CreateEx)
.StaticOverload< Object & (*)(Int32, Int32, Float32, Float32, Float32, Int32, Uint8, Uint8, Uint8, Uint8, Int32) >
(_SC("CreateEx"), &Blip_CreateEx)
.StaticOverload< Object & (*)(Int32, Int32, Float32, Float32, Float32, Int32, Uint8, Uint8, Uint8, Uint8, Int32, Int32, Object &) >
(_SC("CreateEx"), &Blip_CreateEx)
.StaticOverload< Object & (*)(Int32, const Vector3 &, Int32, const Color4 &, Int32) >
(_SC("Create"), &Blip_Create)
.StaticOverload< Object & (*)(Int32, const Vector3 &, Int32, const Color4 &, Int32, Int32, Object &) >
(_SC("Create"), &Blip_Create)
.StaticOverload< Object & (*)(Int32, Int32, const Vector3 &, Int32, const Color4 &, Int32) >
(_SC("Create"), &Blip_Create)
.StaticOverload< Object & (*)(Int32, Int32, const Vector3 &, Int32, const Color4 &, Int32, Int32, Object &) >
(_SC("Create"), &Blip_Create)
);
RootTable(vm)
.Overload< Object & (*)(Int32, Float32, Float32, Float32, Int32, Uint8, Uint8, Uint8, Uint8, Int32) >
(_SC("CreateBlipEx"), &CreateBlipEx)
.Overload< Object & (*)(Int32, Float32, Float32, Float32, Int32, Uint8, Uint8, Uint8, Uint8, Int32, Int32, Object &) >
(_SC("CreateBlipEx"), &CreateBlipEx)
.Overload< Object & (*)(Int32, Int32, Float32, Float32, Float32, Int32, Uint8, Uint8, Uint8, Uint8, Int32) >
(_SC("CreateBlipEx"), &CreateBlipEx)
.Overload< Object & (*)(Int32, Int32, Float32, Float32, Float32, Int32, Uint8, Uint8, Uint8, Uint8, Int32, Int32, Object &) >
(_SC("CreateBlipEx"), &CreateBlipEx)
.Overload< Object & (*)(Int32, const Vector3 &, Int32, const Color4 &, Int32) >
(_SC("CreateBlip"), &CreateBlip)
.Overload< Object & (*)(Int32, const Vector3 &, Int32, const Color4 &, Int32, Int32, Object &) >
(_SC("CreateBlip"), &CreateBlip)
.Overload< Object & (*)(Int32, Int32, const Vector3 &, Int32, const Color4 &, Int32) >
(_SC("CreateBlip"), &CreateBlip)
.Overload< Object & (*)(Int32, Int32, const Vector3 &, Int32, const Color4 &, Int32, Int32, Object &) >
(_SC("CreateBlip"), &CreateBlip);
}
} // Namespace:: SqMod
} // Namespace:: SqMod

View File

@ -8,7 +8,7 @@
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Manages Blip instances.
* Manages a single blip entity.
*/
class CBlip
{
@ -17,20 +17,19 @@ class CBlip
private:
/* --------------------------------------------------------------------------------------------
* Cached identifiers for fast integer to string conversion.
*/
static SQChar s_StrID[SQMOD_BLIP_POOL][8];
/* --------------------------------------------------------------------------------------------
* Identifier of the managed entity.
*/
Int32 m_ID;
/* --------------------------------------------------------------------------------------------
* User tag and data associated with this instance.
* User tag associated with this instance.
*/
String m_Tag;
/* --------------------------------------------------------------------------------------------
* User data associated with this instance.
*/
Object m_Data;
/* --------------------------------------------------------------------------------------------
@ -38,20 +37,22 @@ private:
*/
CBlip(Int32 id);
public:
/* --------------------------------------------------------------------------------------------
* Maximum possible number that could represent an identifier for this entity type.
*/
static const Int32 Max;
/* --------------------------------------------------------------------------------------------
* Copy constructor. (disabled)
*/
CBlip(const CBlip &);
CBlip(const CBlip &) = delete;
/* --------------------------------------------------------------------------------------------
* Copy assignment operator. (disabled)
* Move constructor. (disabled)
*/
CBlip & operator = (const CBlip &);
public:
// --------------------------------------------------------------------------------------------
static const Int32 Max;
CBlip(CBlip &&) = delete;
/* --------------------------------------------------------------------------------------------
* Destructor.
@ -59,14 +60,22 @@ public:
~CBlip();
/* --------------------------------------------------------------------------------------------
* See whether this instance manages a valid entity.
* Copy assignment operator. (disabled)
*/
bool Validate() const
CBlip & operator = (const CBlip &) = delete;
/* --------------------------------------------------------------------------------------------
* Move assignment operator. (disabled)
*/
CBlip & operator = (CBlip &&) = delete;
/* --------------------------------------------------------------------------------------------
* See whether this instance manages a valid entity otherwise throw an exception.
*/
void Validate() const
{
if (VALID_ENTITY(m_ID))
return true;
SqThrow("Invalid blip reference [%s]", m_Tag.c_str());
return false;
if (INVALID_ENTITY(m_ID))
SqThrowF("Invalid blip reference [%s]", m_Tag.c_str());
}
/* --------------------------------------------------------------------------------------------
@ -77,27 +86,33 @@ public:
/* --------------------------------------------------------------------------------------------
* Used by the script engine to convert an instance of this type to a string.
*/
CSStr ToString() const;
const String & ToString() const;
/* --------------------------------------------------------------------------------------------
* Used by the script engine to retrieve the name from instances of this type.
*/
static SQInteger Typename(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Retrieve the identifier of the entity managed by this instance.
*/
Int32 GetID() const { return m_ID; }
/* --------------------------------------------------------------------------------------------
* Retrieve the maximum possible identifier to an entity of this type.
*/
Int32 GetMaxID() const { return SQMOD_BLIP_POOL; }
Int32 GetID() const
{
return m_ID;
}
/* --------------------------------------------------------------------------------------------
* Check whether this instance manages a valid entity.
*/
bool IsActive() const { return VALID_ENTITY(m_ID); }
bool IsActive() const
{
return VALID_ENTITY(m_ID);
}
/* --------------------------------------------------------------------------------------------
* Retrieve the associated user tag.
*/
CSStr GetTag() const;
const String & GetTag() const;
/* --------------------------------------------------------------------------------------------
* Modify the associated user tag.
@ -115,29 +130,89 @@ public:
void SetData(Object & data);
/* --------------------------------------------------------------------------------------------
* Destroy the managed entity instance.
* Destroy the managed blip entity.
*/
bool Destroy()
{
return Destroy(0, NullObject());
}
/* --------------------------------------------------------------------------------------------
* Destroy the managed blip entity.
*/
bool Destroy(Int32 header)
{
return Destroy(header, NullObject());
}
/* --------------------------------------------------------------------------------------------
* Destroy the managed blip entity.
*/
bool Destroy(Int32 header, Object & payload);
bool Destroy() { return Destroy(0, NullObject()); }
bool Destroy(Int32 header) { return Destroy(header, NullObject()); }
// --------------------------------------------------------------------------------------------
bool BindEvent(Int32 evid, Object & env, Function & func) const;
/* --------------------------------------------------------------------------------------------
* Bind to an event supported by this entity type.
*/
void BindEvent(Int32 evid, Object & env, Function & func) const;
// --------------------------------------------------------------------------------------------
/* --------------------------------------------------------------------------------------------
* Retrieve the world in which the referenced blip entity exists.
*/
Int32 GetWorld() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the scale of the managed blip entity.
*/
Int32 GetScale() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the position of the managed blip entity.
*/
const Vector3 & GetPosition() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the color of the managed blip entity.
*/
const Color4 & GetColor() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the identifier of the sprite used by the managed blip entity.
*/
Int32 GetSprID() const;
// --------------------------------------------------------------------------------------------
/* --------------------------------------------------------------------------------------------
* Retrieve the position on the x axis of the managed blip entity.
*/
Float32 GetPosX() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the position on the y axis of the managed blip entity.
*/
Float32 GetPosY() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the position on the z axis of the managed blip entity.
*/
Float32 GetPosZ() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the red color of the managed blip entity.
*/
Int32 GetColorR() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the green color of the managed blip entity.
*/
Int32 GetColorG() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the blue color of the managed blip entity.
*/
Int32 GetColorB() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the alpha transparency of the managed blip entity.
*/
Int32 GetColorA() const;
};

View File

@ -19,15 +19,20 @@ Uint32 CCheckpoint::s_ColorB;
Uint32 CCheckpoint::s_ColorA;
// ------------------------------------------------------------------------------------------------
SQChar CCheckpoint::s_StrID[SQMOD_CHECKPOINT_POOL][8];
const Int32 CCheckpoint::Max = SQMOD_CHECKPOINT_POOL;
// ------------------------------------------------------------------------------------------------
const Int32 CCheckpoint::Max = SQMOD_CHECKPOINT_POOL;
SQInteger CCheckpoint::Typename(HSQUIRRELVM vm)
{
static SQChar name[] = _SC("SqCheckpoint");
sq_pushstring(vm, name, sizeof(name));
return 1;
}
// ------------------------------------------------------------------------------------------------
CCheckpoint::CCheckpoint(Int32 id)
: m_ID(VALID_ENTITYGETEX(id, SQMOD_CHECKPOINT_POOL))
, m_Tag(VALID_ENTITY(m_ID) ? s_StrID[m_ID] : _SC("-1"))
, m_Tag(ToStrF("%d", id))
{
/* ... */
}
@ -49,282 +54,373 @@ Int32 CCheckpoint::Cmp(const CCheckpoint & o) const
return -1;
}
CSStr CCheckpoint::ToString() const
// ------------------------------------------------------------------------------------------------
const String & CCheckpoint::ToString() const
{
return VALID_ENTITYEX(m_ID, SQMOD_CHECKPOINT_POOL) ? s_StrID[m_ID] : _SC("-1");
return m_Tag;
}
// ------------------------------------------------------------------------------------------------
CSStr CCheckpoint::GetTag() const
const String & CCheckpoint::GetTag() const
{
return m_Tag.c_str();
return m_Tag;
}
// ------------------------------------------------------------------------------------------------
void CCheckpoint::SetTag(CSStr tag)
{
m_Tag.assign(tag);
}
// ------------------------------------------------------------------------------------------------
Object & CCheckpoint::GetData()
{
if (Validate())
return m_Data;
return NullObject();
// Validate the managed identifier
Validate();
// Return the requested information
return m_Data;
}
// ------------------------------------------------------------------------------------------------
void CCheckpoint::SetData(Object & data)
{
if (Validate())
m_Data = data;
// Validate the managed identifier
Validate();
// Apply the specified value
m_Data = data;
}
// ------------------------------------------------------------------------------------------------
bool CCheckpoint::Destroy(Int32 header, Object & payload)
{
// Validate the managed identifier
Validate();
// Perform the requested operation
return _Core->DelCheckpoint(m_ID, header, payload);
}
// ------------------------------------------------------------------------------------------------
bool CCheckpoint::BindEvent(Int32 evid, Object & env, Function & func) const
void CCheckpoint::BindEvent(Int32 evid, Object & env, Function & func) const
{
if (!Validate())
return false;
// Validate the managed identifier
Validate();
// Obtain the function instance called for this event
Function & event = _Core->GetCheckpointEvent(m_ID, evid);
// Is the specified callback function null?
if (func.IsNull())
event.Release();
event.Release(); // Then release the current callback
// Assign the specified environment and function
else
event = Function(env.GetVM(), env, func.GetFunc());
return true;
}
// ------------------------------------------------------------------------------------------------
bool CCheckpoint::IsStreamedFor(CPlayer & player) const
{
// Is the specified player even valid?
if (!player.IsActive())
SqThrow("Invalid player argument: null");
else if (Validate())
return _Func->IsCheckpointStreamedForPlayer(m_ID, player.GetID());
return false;
SqThrowF("Invalid player argument: null");
// Validate the managed identifier
Validate();
// Return the requested information
return _Func->IsCheckpointStreamedForPlayer(m_ID, player.GetID());
}
// ------------------------------------------------------------------------------------------------
Int32 CCheckpoint::GetWorld() const
{
if (Validate())
return _Func->GetCheckpointWorld(m_ID);
return -1;
// Validate the managed identifier
Validate();
// Return the requested information
return _Func->GetCheckpointWorld(m_ID);
}
// ------------------------------------------------------------------------------------------------
void CCheckpoint::SetWorld(Int32 world) const
{
if (Validate())
_Func->SetCheckpointWorld(m_ID, world);
// Validate the managed identifier
Validate();
// Perform the requested operation
_Func->SetCheckpointWorld(m_ID, world);
}
// ------------------------------------------------------------------------------------------------
const Color4 & CCheckpoint::GetColor() const
{
// Validate the managed identifier
Validate();
// Clear previous color information, if any
s_Color4.Clear();
if (Validate())
{
_Func->GetCheckpointColor(m_ID, &s_ColorR, &s_ColorG, &s_ColorB, &s_ColorA);
s_Color4.Set(s_ColorR, s_ColorG, s_ColorB, s_ColorA);
}
// Query the server for the color values
_Func->GetCheckpointColor(m_ID, &s_ColorR, &s_ColorG, &s_ColorB, &s_ColorA);
// Convert and assign the retrieved values
s_Color4.Set(s_ColorR, s_ColorG, s_ColorB, s_ColorA);
// Return the requested information
return s_Color4;
}
// ------------------------------------------------------------------------------------------------
void CCheckpoint::SetColor(const Color4 & col) const
{
if (Validate())
_Func->SetCheckpointColor(m_ID, col.r, col.g, col.b, col.a);
// Validate the managed identifier
Validate();
// Perform the requested operation
_Func->SetCheckpointColor(m_ID, col.r, col.g, col.b, col.a);
}
// ------------------------------------------------------------------------------------------------
void CCheckpoint::SetColorEx(Uint8 r, Uint8 g, Uint8 b, Uint8 a) const
{
if (Validate())
_Func->SetCheckpointColor(m_ID, r, g, b, a);
// Validate the managed identifier
Validate();
// Perform the requested operation
_Func->SetCheckpointColor(m_ID, r, g, b, a);
}
// ------------------------------------------------------------------------------------------------
const Vector3 & CCheckpoint::GetPosition() const
{
// Validate the managed identifier
Validate();
// Clear previous position information, if any
s_Vector3.Clear();
if (Validate())
_Func->GetCheckpointPos(m_ID, &s_Vector3.x, &s_Vector3.y, &s_Vector3.z);
// Query the server for the position values
_Func->GetCheckpointPos(m_ID, &s_Vector3.x, &s_Vector3.y, &s_Vector3.z);
// Return the requested information
return s_Vector3;
}
// ------------------------------------------------------------------------------------------------
void CCheckpoint::SetPosition(const Vector3 & pos) const
{
if (Validate())
_Func->SetCheckpointPos(m_ID, pos.x, pos.y, pos.z);
// Validate the managed identifier
Validate();
// Perform the requested operation
_Func->SetCheckpointPos(m_ID, pos.x, pos.y, pos.z);
}
// ------------------------------------------------------------------------------------------------
void CCheckpoint::SetPositionEx(Float32 x, Float32 y, Float32 z) const
{
if (Validate())
_Func->SetCheckpointPos(m_ID, x, y, z);
// Validate the managed identifier
Validate();
// Perform the requested operation
_Func->SetCheckpointPos(m_ID, x, y, z);
}
// ------------------------------------------------------------------------------------------------
Float32 CCheckpoint::GetRadius() const
{
if (Validate())
_Func->GetCheckpointRadius(m_ID);
return 0;
// Validate the managed identifier
Validate();
// Return the requested information
return _Func->GetCheckpointRadius(m_ID);
}
// ------------------------------------------------------------------------------------------------
void CCheckpoint::SetRadius(Float32 radius) const
{
if (Validate())
_Func->SetCheckpointRadius(m_ID, radius);
// Validate the managed identifier
Validate();
// Perform the requested operation
_Func->SetCheckpointRadius(m_ID, radius);
}
// ------------------------------------------------------------------------------------------------
Object & CCheckpoint::GetOwner() const
{
if (Validate())
return _Core->GetPlayer(_Func->GetCheckpointOwner(m_ID)).mObj;
return NullObject();
// Validate the managed identifier
Validate();
// Return the requested information
return _Core->GetPlayer(_Func->GetCheckpointOwner(m_ID)).mObj;
}
// ------------------------------------------------------------------------------------------------
Int32 CCheckpoint::GetOwnerID() const
{
if (Validate())
return _Func->GetCheckpointOwner(m_ID);
return -1;
// Validate the managed identifier
Validate();
// Return the requested information
return _Func->GetCheckpointOwner(m_ID);
}
// ------------------------------------------------------------------------------------------------
Float32 CCheckpoint::GetPosX() const
{
// Validate the managed identifier
Validate();
// Clear previous position information, if any
s_Vector3.x = 0;
if (Validate())
_Func->GetCheckpointPos(m_ID, &s_Vector3.x, NULL, NULL);
// Query the server for the requested component value
_Func->GetCheckpointPos(m_ID, &s_Vector3.x, NULL, NULL);
// Return the requested information
return s_Vector3.x;
}
// ------------------------------------------------------------------------------------------------
Float32 CCheckpoint::GetPosY() const
{
// Validate the managed identifier
Validate();
// Clear previous position information, if any
s_Vector3.y = 0;
if (Validate())
_Func->GetCheckpointPos(m_ID, NULL, &s_Vector3.y, NULL);
// Query the server for the requested component value
_Func->GetCheckpointPos(m_ID, NULL, &s_Vector3.y, NULL);
// Return the requested information
return s_Vector3.y;
}
// ------------------------------------------------------------------------------------------------
Float32 CCheckpoint::GetPosZ() const
{
// Validate the managed identifier
Validate();
// Clear previous position information, if any
s_Vector3.z = 0;
if (Validate())
_Func->GetCheckpointPos(m_ID, NULL, NULL, &s_Vector3.z);
// Query the server for the requested component value
_Func->GetCheckpointPos(m_ID, NULL, NULL, &s_Vector3.z);
// Return the requested information
return s_Vector3.z;
}
// ------------------------------------------------------------------------------------------------
void CCheckpoint::SetPosX(Float32 x) const
{
if (Validate())
{
_Func->GetCheckpointPos(m_ID, NULL, &s_Vector3.y, &s_Vector3.z);
_Func->SetCheckpointPos(m_ID, x, s_Vector3.y, s_Vector3.z);
}
// Validate the managed identifier
Validate();
// Retrieve the current values for unchanged components
_Func->GetCheckpointPos(m_ID, NULL, &s_Vector3.y, &s_Vector3.z);
// Perform the requested operation
_Func->SetCheckpointPos(m_ID, x, s_Vector3.y, s_Vector3.z);
}
// ------------------------------------------------------------------------------------------------
void CCheckpoint::SetPosY(Float32 y) const
{
if (Validate())
{
_Func->GetCheckpointPos(m_ID, &s_Vector3.x, NULL, &s_Vector3.z);
_Func->SetCheckpointPos(m_ID, s_Vector3.x, y, s_Vector3.z);
}
// Validate the managed identifier
Validate();
// Retrieve the current values for unchanged components
_Func->GetCheckpointPos(m_ID, &s_Vector3.x, NULL, &s_Vector3.z);
// Perform the requested operation
_Func->SetCheckpointPos(m_ID, s_Vector3.x, y, s_Vector3.z);
}
// ------------------------------------------------------------------------------------------------
void CCheckpoint::SetPosZ(Float32 z) const
{
if (Validate())
{
_Func->GetCheckpointPos(m_ID, &s_Vector3.x, &s_Vector3.y, NULL);
_Func->SetCheckpointPos(m_ID, s_Vector3.z, s_Vector3.y, z);
}
// Validate the managed identifier
Validate();
// Retrieve the current values for unchanged components
_Func->GetCheckpointPos(m_ID, &s_Vector3.x, &s_Vector3.y, NULL);
// Perform the requested operation
_Func->SetCheckpointPos(m_ID, s_Vector3.z, s_Vector3.y, z);
}
// ------------------------------------------------------------------------------------------------
Uint32 CCheckpoint::GetColR() const
{
// Validate the managed identifier
Validate();
// Clear previous color information, if any
s_ColorR = 0;
if (Validate())
_Func->GetCheckpointColor(m_ID, &s_ColorR, NULL, NULL, NULL);
// Query the server for the requested component value
_Func->GetCheckpointColor(m_ID, &s_ColorR, NULL, NULL, NULL);
// Return the requested information
return s_ColorR;
}
// ------------------------------------------------------------------------------------------------
Uint32 CCheckpoint::GetColG() const
{
// Validate the managed identifier
Validate();
// Clear previous color information, if any
s_ColorG = 0;
if (Validate())
_Func->GetCheckpointColor(m_ID, NULL, &s_ColorG, NULL, NULL);
// Query the server for the requested component value
_Func->GetCheckpointColor(m_ID, NULL, &s_ColorG, NULL, NULL);
// Return the requested information
return s_ColorG;
}
// ------------------------------------------------------------------------------------------------
Uint32 CCheckpoint::GetColB() const
{
// Validate the managed identifier
Validate();
// Clear previous color information, if any
s_ColorB = 0;
if (Validate())
_Func->GetCheckpointColor(m_ID, NULL, NULL, &s_ColorB, NULL);
// Query the server for the requested component value
_Func->GetCheckpointColor(m_ID, NULL, NULL, &s_ColorB, NULL);
// Return the requested information
return s_ColorB;
}
// ------------------------------------------------------------------------------------------------
Uint32 CCheckpoint::GetColA() const
{
// Validate the managed identifier
Validate();
// Clear previous color information, if any
s_ColorA = 0;
if (Validate())
_Func->GetCheckpointColor(m_ID, NULL, NULL, NULL, &s_ColorA);
// Query the server for the requested component value
_Func->GetCheckpointColor(m_ID, NULL, NULL, NULL, &s_ColorA);
// Return the requested information
return s_ColorA;
}
// ------------------------------------------------------------------------------------------------
void CCheckpoint::SetColR(Uint32 r) const
{
if (Validate())
{
_Func->GetCheckpointColor(m_ID, NULL, &s_ColorG, &s_ColorB, &s_ColorA);
_Func->SetCheckpointColor(m_ID, r, s_ColorG, s_ColorB, s_ColorA);
}
}
void CCheckpoint::SetColG(Uint32 g) const
{
if (Validate())
{
_Func->GetCheckpointColor(m_ID, &s_ColorR, NULL, &s_ColorB, &s_ColorA);
_Func->SetCheckpointColor(m_ID, s_ColorR, g, s_ColorB, s_ColorA);
}
}
void CCheckpoint::SetColB(Uint32 b) const
{
if (Validate())
{
_Func->GetCheckpointColor(m_ID, &s_ColorB, &s_ColorG, NULL, &s_ColorA);
_Func->SetCheckpointColor(m_ID, s_ColorB, s_ColorG, b, s_ColorA);
}
}
void CCheckpoint::SetColA(Uint32 a) const
{
if (Validate())
{
_Func->GetCheckpointColor(m_ID, &s_ColorA, &s_ColorG, &s_ColorB, NULL);
_Func->SetCheckpointColor(m_ID, s_ColorA, s_ColorG, s_ColorB, a);
}
// Validate the managed identifier
Validate();
// Retrieve the current values for unchanged components
_Func->GetCheckpointColor(m_ID, NULL, &s_ColorG, &s_ColorB, &s_ColorA);
// Perform the requested operation
_Func->SetCheckpointColor(m_ID, r, s_ColorG, s_ColorB, s_ColorA);
}
// ------------------------------------------------------------------------------------------------
static Object & CreateCheckpointEx(CPlayer & player, Int32 world, Float32 x, Float32 y, Float32 z,
void CCheckpoint::SetColG(Uint32 g) const
{
// Validate the managed identifier
Validate();
// Retrieve the current values for unchanged components
_Func->GetCheckpointColor(m_ID, &s_ColorR, NULL, &s_ColorB, &s_ColorA);
// Perform the requested operation
_Func->SetCheckpointColor(m_ID, s_ColorR, g, s_ColorB, s_ColorA);
}
// ------------------------------------------------------------------------------------------------
void CCheckpoint::SetColB(Uint32 b) const
{
// Validate the managed identifier
Validate();
// Retrieve the current values for unchanged components
_Func->GetCheckpointColor(m_ID, &s_ColorB, &s_ColorG, NULL, &s_ColorA);
// Perform the requested operation
_Func->SetCheckpointColor(m_ID, s_ColorB, s_ColorG, b, s_ColorA);
}
// ------------------------------------------------------------------------------------------------
void CCheckpoint::SetColA(Uint32 a) const
{
// Validate the managed identifier
Validate();
// Retrieve the current values for unchanged components
_Func->GetCheckpointColor(m_ID, &s_ColorA, &s_ColorG, &s_ColorB, NULL);
// Perform the requested operation
_Func->SetCheckpointColor(m_ID, s_ColorA, s_ColorG, s_ColorB, a);
}
// ------------------------------------------------------------------------------------------------
static Object & Checkpoint_CreateEx(CPlayer & player, Int32 world, Float32 x, Float32 y, Float32 z,
Uint8 r, Uint8 g, Uint8 b, Uint8 a, Float32 radius)
{
return _Core->NewCheckpoint(player.GetID(), world, x, y, z, r, g, b, a, radius,
SQMOD_CREATE_DEFAULT, NullObject());
}
static Object & CreateCheckpointEx(CPlayer & player, Int32 world, Float32 x, Float32 y, Float32 z,
static Object & Checkpoint_CreateEx(CPlayer & player, Int32 world, Float32 x, Float32 y, Float32 z,
Uint8 r, Uint8 g, Uint8 b, Uint8 a, Float32 radius,
Int32 header, Object & payload)
{
@ -332,7 +428,7 @@ static Object & CreateCheckpointEx(CPlayer & player, Int32 world, Float32 x, Flo
}
// ------------------------------------------------------------------------------------------------
static Object & CreateCheckpoint(CPlayer & player, Int32 world, const Vector3 & pos,
static Object & Checkpoint_Create(CPlayer & player, Int32 world, const Vector3 & pos,
const Color4 & color, Float32 radius)
{
return _Core->NewCheckpoint(player.GetID(), world, pos.x, pos.y, pos.z,
@ -340,7 +436,7 @@ static Object & CreateCheckpoint(CPlayer & player, Int32 world, const Vector3 &
SQMOD_CREATE_DEFAULT, NullObject());
}
static Object & CreateCheckpoint(CPlayer & player, Int32 world, const Vector3 & pos,
static Object & Checkpoint_Create(CPlayer & player, Int32 world, const Vector3 & pos,
const Color4 & color, Float32 radius, Int32 header, Object & payload)
{
return _Core->NewCheckpoint(player.GetID(), world, pos.x, pos.y, pos.z,
@ -352,22 +448,24 @@ void Register_CCheckpoint(HSQUIRRELVM vm)
{
RootTable(vm).Bind(_SC("SqCheckpoint"),
Class< CCheckpoint, NoConstructor< CCheckpoint > >(vm, _SC("SqCheckpoint"))
/* Metamethods */
// Metamethods
.Func(_SC("_cmp"), &CCheckpoint::Cmp)
.SquirrelFunc(_SC("_typename"), &CCheckpoint::Typename)
.Func(_SC("_tostring"), &CCheckpoint::ToString)
/* Core Properties */
// Static values
.SetStaticValue(_SC("MaxID"), CCheckpoint::Max)
// Core Properties
.Prop(_SC("ID"), &CCheckpoint::GetID)
.Prop(_SC("Tag"), &CCheckpoint::GetTag, &CCheckpoint::SetTag)
.Prop(_SC("Data"), &CCheckpoint::GetData, &CCheckpoint::SetData)
.Prop(_SC("MaxID"), &CCheckpoint::GetMaxID)
.Prop(_SC("Active"), &CCheckpoint::IsActive)
/* Core Functions */
// Core Functions
.Func(_SC("Bind"), &CCheckpoint::BindEvent)
/* Core Overloads */
// Core Overloads
.Overload< bool (CCheckpoint::*)(void) >(_SC("Destroy"), &CCheckpoint::Destroy)
.Overload< bool (CCheckpoint::*)(Int32) >(_SC("Destroy"), &CCheckpoint::Destroy)
.Overload< bool (CCheckpoint::*)(Int32, Object &) >(_SC("Destroy"), &CCheckpoint::Destroy)
/* Properties */
// Properties
.Prop(_SC("World"), &CCheckpoint::GetWorld, &CCheckpoint::SetWorld)
.Prop(_SC("Color"), &CCheckpoint::GetColor, &CCheckpoint::SetColor)
.Prop(_SC("Pos"), &CCheckpoint::GetPosition, &CCheckpoint::SetPosition)
@ -382,22 +480,21 @@ void Register_CCheckpoint(HSQUIRRELVM vm)
.Prop(_SC("G"), &CCheckpoint::GetColG, &CCheckpoint::SetColG)
.Prop(_SC("B"), &CCheckpoint::GetColB, &CCheckpoint::SetColB)
.Prop(_SC("A"), &CCheckpoint::GetColA, &CCheckpoint::SetColA)
/* Functions */
// Functions
.Func(_SC("StreamedFor"), &CCheckpoint::IsStreamedFor)
.Func(_SC("SetColor"), &CCheckpoint::SetColorEx)
.Func(_SC("SetPos"), &CCheckpoint::SetPositionEx)
.Func(_SC("SetPosition"), &CCheckpoint::SetPositionEx)
// Static Overloads
.StaticOverload< Object & (*)(CPlayer &, Int32, Float32, Float32, Float32, Uint8, Uint8, Uint8, Uint8, Float32) >
(_SC("CreateEx"), &Checkpoint_CreateEx)
.StaticOverload< Object & (*)(CPlayer &, Int32, Float32, Float32, Float32, Uint8, Uint8, Uint8, Uint8, Float32, Int32, Object &) >
(_SC("CreateEx"), &Checkpoint_CreateEx)
.StaticOverload< Object & (*)(CPlayer &, Int32, const Vector3 &, const Color4 &, Float32) >
(_SC("Create"), &Checkpoint_Create)
.StaticOverload< Object & (*)(CPlayer &, Int32, const Vector3 &, const Color4 &, Float32, Int32, Object &) >
(_SC("Create"), &Checkpoint_Create)
);
RootTable(vm)
.Overload< Object & (*)(CPlayer &, Int32, Float32, Float32, Float32, Uint8, Uint8, Uint8, Uint8, Float32) >
(_SC("CreateCheckpointEx"), &CreateCheckpointEx)
.Overload< Object & (*)(CPlayer &, Int32, Float32, Float32, Float32, Uint8, Uint8, Uint8, Uint8, Float32, Int32, Object &) >
(_SC("CreateCheckpointEx"), &CreateCheckpointEx)
.Overload< Object & (*)(CPlayer &, Int32, const Vector3 &, const Color4 &, Float32) >
(_SC("CreateCheckpoint"), &CreateCheckpoint)
.Overload< Object & (*)(CPlayer &, Int32, const Vector3 &, const Color4 &, Float32, Int32, Object &) >
(_SC("CreateCheckpoint"), &CreateCheckpoint);
}
} // Namespace:: SqMod
} // Namespace:: SqMod

View File

@ -8,7 +8,7 @@
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Manages Checkpoint instances.
* Manages a single checkpoint entity.
*/
class CCheckpoint
{
@ -24,20 +24,19 @@ private:
// --------------------------------------------------------------------------------------------
static Uint32 s_ColorR, s_ColorG, s_ColorB, s_ColorA;
/* --------------------------------------------------------------------------------------------
* Cached identifiers for fast integer to string conversion.
*/
static SQChar s_StrID[SQMOD_CHECKPOINT_POOL][8];
/* --------------------------------------------------------------------------------------------
* Identifier of the managed entity.
*/
Int32 m_ID;
/* --------------------------------------------------------------------------------------------
* User tag and data associated with this instance.
* User tag associated with this instance.
*/
String m_Tag;
/* --------------------------------------------------------------------------------------------
* User data associated with this instance.
*/
Object m_Data;
/* --------------------------------------------------------------------------------------------
@ -45,20 +44,22 @@ private:
*/
CCheckpoint(Int32 id);
public:
/* --------------------------------------------------------------------------------------------
* Maximum possible number that could represent an identifier for this entity type.
*/
static const Int32 Max;
/* --------------------------------------------------------------------------------------------
* Copy constructor. (disabled)
*/
CCheckpoint(const CCheckpoint &);
CCheckpoint(const CCheckpoint &) = delete;
/* --------------------------------------------------------------------------------------------
* Copy assignment operator. (disabled)
* Move constructor. (disabled)
*/
CCheckpoint & operator = (const CCheckpoint &);
public:
// --------------------------------------------------------------------------------------------
static const Int32 Max;
CCheckpoint(CCheckpoint &&) = delete;
/* --------------------------------------------------------------------------------------------
* Destructor.
@ -66,14 +67,22 @@ public:
~CCheckpoint();
/* --------------------------------------------------------------------------------------------
* See whether this instance manages a valid entity.
* Copy assignment operator. (disabled)
*/
bool Validate() const
CCheckpoint & operator = (const CCheckpoint &) = delete;
/* --------------------------------------------------------------------------------------------
* Move assignment operator. (disabled)
*/
CCheckpoint & operator = (CCheckpoint &&) = delete;
/* --------------------------------------------------------------------------------------------
* See whether this instance manages a valid entity otherwise throw an exception.
*/
void Validate() const
{
if (VALID_ENTITY(m_ID))
return true;
SqThrow("Invalid checkpoint reference [%s]", m_Tag.c_str());
return false;
if (INVALID_ENTITY(m_ID))
SqThrowF("Invalid checkpoint reference [%s]", m_Tag.c_str());
}
/* --------------------------------------------------------------------------------------------
@ -84,27 +93,33 @@ public:
/* --------------------------------------------------------------------------------------------
* Used by the script engine to convert an instance of this type to a string.
*/
CSStr ToString() const;
const String & ToString() const;
/* --------------------------------------------------------------------------------------------
* Used by the script engine to retrieve the name from instances of this type.
*/
static SQInteger Typename(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Retrieve the identifier of the entity managed by this instance.
*/
Int32 GetID() const { return m_ID; }
/* --------------------------------------------------------------------------------------------
* Retrieve the maximum possible identifier to an entity of this type.
*/
Int32 GetMaxID() const { return SQMOD_CHECKPOINT_POOL; }
Int32 GetID() const
{
return m_ID;
}
/* --------------------------------------------------------------------------------------------
* Check whether this instance manages a valid entity.
*/
bool IsActive() const { return VALID_ENTITY(m_ID); }
bool IsActive() const
{
return VALID_ENTITY(m_ID);
}
/* --------------------------------------------------------------------------------------------
* Retrieve the associated user tag.
*/
CSStr GetTag() const;
const String & GetTag() const;
/* --------------------------------------------------------------------------------------------
* Modify the associated user tag.
@ -120,45 +135,166 @@ public:
* Modify the associated user data.
*/
void SetData(Object & data);
// --------------------------------------------------------------------------------------------
/* --------------------------------------------------------------------------------------------
* Destroy the managed checkpoint entity.
*/
bool Destroy()
{
return Destroy(0, NullObject());
}
/* --------------------------------------------------------------------------------------------
* Destroy the managed checkpoint entity.
*/
bool Destroy(Int32 header)
{
return Destroy(header, NullObject());
}
/* --------------------------------------------------------------------------------------------
* Destroy the managed checkpoint entity.
*/
bool Destroy(Int32 header, Object & payload);
bool Destroy() { return Destroy(0, NullObject()); }
bool Destroy(Int32 header) { return Destroy(header, NullObject()); }
// --------------------------------------------------------------------------------------------
bool BindEvent(Int32 evid, Object & env, Function & func) const;
/* --------------------------------------------------------------------------------------------
* Bind to an event supported by this entity type.
*/
void BindEvent(Int32 evid, Object & env, Function & func) const;
// --------------------------------------------------------------------------------------------
/* --------------------------------------------------------------------------------------------
* See if the managed checkpoint entity is streamed for the specified player.
*/
bool IsStreamedFor(CPlayer & player) const;
/* --------------------------------------------------------------------------------------------
* Retrieve the world in which the managed checkpoint entity exists.
*/
Int32 GetWorld() const;
/* --------------------------------------------------------------------------------------------
* Modify the world in which the managed checkpoint entity exists.
*/
void SetWorld(Int32 world) const;
/* --------------------------------------------------------------------------------------------
* Retrieve the color of the managed checkpoint entity.
*/
const Color4 & GetColor() const;
/* --------------------------------------------------------------------------------------------
* Modify the color of the managed checkpoint entity.
*/
void SetColor(const Color4 & col) const;
/* --------------------------------------------------------------------------------------------
* Modify the color of the managed checkpoint entity.
*/
void SetColorEx(Uint8 r, Uint8 g, Uint8 b, Uint8 a) const;
/* --------------------------------------------------------------------------------------------
* Retrieve the position of the managed checkpoint entity.
*/
const Vector3 & GetPosition() const;
/* --------------------------------------------------------------------------------------------
* Modify the position of the managed checkpoint entity.
*/
void SetPosition(const Vector3 & pos) const;
/* --------------------------------------------------------------------------------------------
* Modify the position of the managed checkpoint entity.
*/
void SetPositionEx(Float32 x, Float32 y, Float32 z) const;
/* --------------------------------------------------------------------------------------------
* Retrieve the radius of the managed checkpoint entity.
*/
Float32 GetRadius() const;
/* --------------------------------------------------------------------------------------------
* Modify the radius of the managed checkpoint entity.
*/
void SetRadius(Float32 radius) const;
/* --------------------------------------------------------------------------------------------
* Retrieve the owner of the managed checkpoint entity.
*/
Object & GetOwner() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the owner identifier of the managed checkpoint entity.
*/
Int32 GetOwnerID() const;
// --------------------------------------------------------------------------------------------
/* --------------------------------------------------------------------------------------------
* Retrieve the position on the x axis of the managed checkpoint entity.
*/
Float32 GetPosX() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the position on the y axis of the managed checkpoint entity.
*/
Float32 GetPosY() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the position on the z axis of the managed checkpoint entity.
*/
Float32 GetPosZ() const;
/* --------------------------------------------------------------------------------------------
* Modify the position on the x axis of the managed checkpoint entity.
*/
void SetPosX(Float32 x) const;
/* --------------------------------------------------------------------------------------------
* Modify the position on the y axis of the managed checkpoint entity.
*/
void SetPosY(Float32 y) const;
/* --------------------------------------------------------------------------------------------
* Modify the position on the z axis of the managed checkpoint entity.
*/
void SetPosZ(Float32 z) const;
// --------------------------------------------------------------------------------------------
/* --------------------------------------------------------------------------------------------
* Retrieve the red color of the managed checkpoint entity.
*/
Uint32 GetColR() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the green color of the managed checkpoint entity.
*/
Uint32 GetColG() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the blue color of the managed checkpoint entity.
*/
Uint32 GetColB() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the alpha transparency of the managed checkpoint entity.
*/
Uint32 GetColA() const;
/* --------------------------------------------------------------------------------------------
* Modify the red color of the managed checkpoint entity.
*/
void SetColR(Uint32 r) const;
/* --------------------------------------------------------------------------------------------
* Modify the green color of the managed checkpoint entity.
*/
void SetColG(Uint32 g) const;
/* --------------------------------------------------------------------------------------------
* Modify the blue color of the managed checkpoint entity.
*/
void SetColB(Uint32 b) const;
/* --------------------------------------------------------------------------------------------
* Modify the alpha transparency of the managed checkpoint entity.
*/
void SetColA(Uint32 a) const;
};

View File

@ -18,15 +18,20 @@ Uint32 CForcefield::s_ColorG;
Uint32 CForcefield::s_ColorB;
// ------------------------------------------------------------------------------------------------
SQChar CForcefield::s_StrID[SQMOD_FORCEFIELD_POOL][8];
const Int32 CForcefield::Max = SQMOD_FORCEFIELD_POOL;
// ------------------------------------------------------------------------------------------------
const Int32 CForcefield::Max = SQMOD_FORCEFIELD_POOL;
SQInteger CForcefield::Typename(HSQUIRRELVM vm)
{
static SQChar name[] = _SC("SqForcefield");
sq_pushstring(vm, name, sizeof(name));
return 1;
}
// ------------------------------------------------------------------------------------------------
CForcefield::CForcefield(Int32 id)
: m_ID(VALID_ENTITYGETEX(id, SQMOD_FORCEFIELD_POOL))
, m_Tag(VALID_ENTITY(m_ID) ? s_StrID[m_ID] : _SC("-1"))
, m_Tag(ToStrF("%d", id))
{
/* ... */
}
@ -48,265 +53,349 @@ Int32 CForcefield::Cmp(const CForcefield & o) const
return -1;
}
CSStr CForcefield::ToString() const
// ------------------------------------------------------------------------------------------------
const String & CForcefield::ToString() const
{
return VALID_ENTITYEX(m_ID, SQMOD_FORCEFIELD_POOL) ? s_StrID[m_ID] : _SC("-1");
return m_Tag;
}
// ------------------------------------------------------------------------------------------------
CSStr CForcefield::GetTag() const
const String & CForcefield::GetTag() const
{
return m_Tag.c_str();
return m_Tag;
}
// ------------------------------------------------------------------------------------------------
void CForcefield::SetTag(CSStr tag)
{
m_Tag.assign(tag);
}
// ------------------------------------------------------------------------------------------------
Object & CForcefield::GetData()
{
if (Validate())
return m_Data;
return NullObject();
// Validate the managed identifier
Validate();
// Return the requested information
return m_Data;
}
// ------------------------------------------------------------------------------------------------
void CForcefield::SetData(Object & data)
{
if (Validate())
m_Data = data;
// Validate the managed identifier
Validate();
// Apply the specified value
m_Data = data;
}
// ------------------------------------------------------------------------------------------------
bool CForcefield::Destroy(Int32 header, Object & payload)
{
// Validate the managed identifier
Validate();
// Perform the requested operation
return _Core->DelForcefield(m_ID, header, payload);
}
// ------------------------------------------------------------------------------------------------
bool CForcefield::BindEvent(Int32 evid, Object & env, Function & func) const
void CForcefield::BindEvent(Int32 evid, Object & env, Function & func) const
{
if (!Validate())
return false;
// Validate the managed identifier
Validate();
// Obtain the function instance called for this event
Function & event = _Core->GetForcefieldEvent(m_ID, evid);
// Is the specified callback function null?
if (func.IsNull())
event.Release();
event.Release(); // Then release the current callback
// Assign the specified environment and function
else
event = Function(env.GetVM(), env, func.GetFunc());
return true;
}
// ------------------------------------------------------------------------------------------------
bool CForcefield::IsStreamedFor(CPlayer & player) const
{
// Is the specified player even valid?
if (!player.IsActive())
SqThrow("Invalid player argument: null");
else if (Validate())
return _Func->IsSphereStreamedForPlayer(m_ID, player.GetID());
return false;
SqThrowF("Invalid player argument: null");
// Validate the managed identifier
Validate();
// Return the requested information
return _Func->IsSphereStreamedForPlayer(m_ID, player.GetID());
}
// ------------------------------------------------------------------------------------------------
Int32 CForcefield::GetWorld() const
{
if (Validate())
return _Func->GetSphereWorld(m_ID);
return -1;
// Validate the managed identifier
Validate();
// Return the requested information
return _Func->GetSphereWorld(m_ID);
}
// ------------------------------------------------------------------------------------------------
void CForcefield::SetWorld(Int32 world) const
{
if (Validate())
_Func->SetSphereWorld(m_ID, world);
// Validate the managed identifier
Validate();
// Perform the requested operation
_Func->SetSphereWorld(m_ID, world);
}
// ------------------------------------------------------------------------------------------------
const Color3 & CForcefield::GetColor() const
{
// Validate the managed identifier
Validate();
// Clear previous color information, if any
s_Color3.Clear();
if (Validate())
{
_Func->GetSphereColor(m_ID, &s_ColorR, &s_ColorG, &s_ColorB);
s_Color3.Set(s_ColorR, s_ColorG, s_ColorB);
}
// Query the server for the color values
_Func->GetSphereColor(m_ID, &s_ColorR, &s_ColorG, &s_ColorB);
// Convert and assign the retrieved values
s_Color3.Set(s_ColorR, s_ColorG, s_ColorB);
// Return the requested information
return s_Color3;
}
// ------------------------------------------------------------------------------------------------
void CForcefield::SetColor(const Color3 & col) const
{
if (Validate())
_Func->SetSphereColor(m_ID, col.r, col.g, col.b);
// Validate the managed identifier
Validate();
// Perform the requested operation
_Func->SetSphereColor(m_ID, col.r, col.g, col.b);
}
// ------------------------------------------------------------------------------------------------
void CForcefield::SetColorEx(Uint8 r, Uint8 g, Uint8 b) const
{
if (Validate())
_Func->SetSphereColor(m_ID, r, g, b);
// Validate the managed identifier
Validate();
// Perform the requested operation
_Func->SetSphereColor(m_ID, r, g, b);
}
// ------------------------------------------------------------------------------------------------
const Vector3 & CForcefield::GetPosition() const
{
// Validate the managed identifier
Validate();
// Clear previous position information, if any
s_Vector3.Clear();
if (Validate())
_Func->GetSpherePos(m_ID, &s_Vector3.x, &s_Vector3.y, &s_Vector3.z);
// Query the server for the position values
_Func->GetSpherePos(m_ID, &s_Vector3.x, &s_Vector3.y, &s_Vector3.z);
// Return the requested information
return s_Vector3;
}
// ------------------------------------------------------------------------------------------------
void CForcefield::SetPosition(const Vector3 & pos) const
{
if (Validate())
_Func->SetSpherePos(m_ID, pos.x, pos.y, pos.z);
// Validate the managed identifier
Validate();
// Perform the requested operation
_Func->SetSpherePos(m_ID, pos.x, pos.y, pos.z);
}
// ------------------------------------------------------------------------------------------------
void CForcefield::SetPositionEx(Float32 x, Float32 y, Float32 z) const
{
if (Validate())
_Func->SetSpherePos(m_ID, x, y, z);
// Validate the managed identifier
Validate();
// Perform the requested operation
_Func->SetSpherePos(m_ID, x, y, z);
}
// ------------------------------------------------------------------------------------------------
Float32 CForcefield::GetRadius() const
{
if (Validate())
_Func->GetSphereRadius(m_ID);
return 0;
// Validate the managed identifier
Validate();
// Return the requested information
return _Func->GetSphereRadius(m_ID);
}
// ------------------------------------------------------------------------------------------------
void CForcefield::SetRadius(Float32 radius) const
{
if (Validate())
_Func->SetSphereRadius(m_ID, radius);
// Validate the managed identifier
Validate();
// Perform the requested operation
_Func->SetSphereRadius(m_ID, radius);
}
// ------------------------------------------------------------------------------------------------
Object & CForcefield::GetOwner() const
{
if (Validate())
return _Core->GetPlayer(_Func->GetSphereOwner(m_ID)).mObj;
return NullObject();
// Validate the managed identifier
Validate();
// Return the requested information
return _Core->GetPlayer(_Func->GetSphereOwner(m_ID)).mObj;
}
// ------------------------------------------------------------------------------------------------
Int32 CForcefield::GetOwnerID() const
{
if (Validate())
_Func->GetSphereOwner(m_ID);
return -1;
// Validate the managed identifier
Validate();
// Return the requested information
return _Func->GetSphereOwner(m_ID);
}
// ------------------------------------------------------------------------------------------------
Float32 CForcefield::GetPosX() const
{
// Validate the managed identifier
Validate();
// Clear previous position information, if any
s_Vector3.x = 0;
if (Validate())
_Func->GetSpherePos(m_ID, &s_Vector3.x, NULL, NULL);
// Query the server for the requested component value
_Func->GetSpherePos(m_ID, &s_Vector3.x, NULL, NULL);
// Return the requested information
return s_Vector3.x;
}
// ------------------------------------------------------------------------------------------------
Float32 CForcefield::GetPosY() const
{
// Validate the managed identifier
Validate();
// Clear previous position information, if any
s_Vector3.y = 0;
if (Validate())
_Func->GetSpherePos(m_ID, NULL, &s_Vector3.y, NULL);
// Query the server for the requested component value
_Func->GetSpherePos(m_ID, NULL, &s_Vector3.y, NULL);
// Return the requested information
return s_Vector3.y;
}
// ------------------------------------------------------------------------------------------------
Float32 CForcefield::GetPosZ() const
{
// Validate the managed identifier
Validate();
// Clear previous position information, if any
s_Vector3.z = 0;
if (Validate())
_Func->GetSpherePos(m_ID, NULL, NULL, &s_Vector3.z);
// Query the server for the requested component value
_Func->GetSpherePos(m_ID, NULL, NULL, &s_Vector3.z);
// Return the requested information
return s_Vector3.z;
}
// ------------------------------------------------------------------------------------------------
void CForcefield::SetPosX(Float32 x) const
{
if (Validate())
{
_Func->GetSpherePos(m_ID, NULL, &s_Vector3.y, &s_Vector3.z);
_Func->SetSpherePos(m_ID, x, s_Vector3.y, s_Vector3.z);
}
// Validate the managed identifier
Validate();
// Retrieve the current values for unchanged components
_Func->GetSpherePos(m_ID, NULL, &s_Vector3.y, &s_Vector3.z);
// Perform the requested operation
_Func->SetSpherePos(m_ID, x, s_Vector3.y, s_Vector3.z);
}
// ------------------------------------------------------------------------------------------------
void CForcefield::SetPosY(Float32 y) const
{
if (Validate())
{
_Func->GetSpherePos(m_ID, &s_Vector3.x, NULL, &s_Vector3.z);
_Func->SetSpherePos(m_ID, s_Vector3.x, y, s_Vector3.z);
}
// Validate the managed identifier
Validate();
// Retrieve the current values for unchanged components
_Func->GetSpherePos(m_ID, &s_Vector3.x, NULL, &s_Vector3.z);
// Perform the requested operation
_Func->SetSpherePos(m_ID, s_Vector3.x, y, s_Vector3.z);
}
// ------------------------------------------------------------------------------------------------
void CForcefield::SetPosZ(Float32 z) const
{
if (Validate())
{
_Func->GetSpherePos(m_ID, &s_Vector3.x, &s_Vector3.y, NULL);
_Func->SetSpherePos(m_ID, s_Vector3.z, s_Vector3.y, z);
}
// Validate the managed identifier
Validate();
// Retrieve the current values for unchanged components
_Func->GetSpherePos(m_ID, &s_Vector3.x, &s_Vector3.y, NULL);
// Perform the requested operation
_Func->SetSpherePos(m_ID, s_Vector3.z, s_Vector3.y, z);
}
// ------------------------------------------------------------------------------------------------
Uint32 CForcefield::GetColR() const
{
// Validate the managed identifier
Validate();
// Clear previous color information, if any
s_ColorR = 0;
if (Validate())
_Func->GetSphereColor(m_ID, &s_ColorR, NULL, NULL);
// Query the server for the requested component value
_Func->GetSphereColor(m_ID, &s_ColorR, NULL, NULL);
// Return the requested information
return s_ColorR;
}
// ------------------------------------------------------------------------------------------------
Uint32 CForcefield::GetColG() const
{
// Validate the managed identifier
Validate();
// Query the server for the requested component value
s_ColorG = 0;
if (Validate())
_Func->GetSphereColor(m_ID, NULL, &s_ColorG, NULL);
// Query the server for the requested component value
_Func->GetSphereColor(m_ID, NULL, &s_ColorG, NULL);
// Return the requested information
return s_ColorG;
}
// ------------------------------------------------------------------------------------------------
Uint32 CForcefield::GetColB() const
{
// Validate the managed identifier
Validate();
// Query the server for the requested component value
s_ColorB = 0;
if (Validate())
_Func->GetSphereColor(m_ID, NULL, NULL, &s_ColorB);
// Query the server for the requested component value
_Func->GetSphereColor(m_ID, NULL, NULL, &s_ColorB);
// Return the requested information
return s_ColorB;
}
// ------------------------------------------------------------------------------------------------
void CForcefield::SetColR(Uint32 r) const
{
if (Validate())
{
_Func->GetSphereColor(m_ID, NULL, &s_ColorG, &s_ColorB);
_Func->SetSphereColor(m_ID, r, s_ColorG, s_ColorB);
}
}
void CForcefield::SetColG(Uint32 g) const
{
if (Validate())
{
_Func->GetSphereColor(m_ID, &s_ColorR, NULL, &s_ColorB);
_Func->SetSphereColor(m_ID, s_ColorR, g, s_ColorB);
}
}
void CForcefield::SetColB(Uint32 b) const
{
if (Validate())
{
_Func->GetSphereColor(m_ID, &s_ColorB, &s_ColorG, NULL);
_Func->SetSphereColor(m_ID, s_ColorB, s_ColorG, b);
}
// Validate the managed identifier
Validate();
// Retrieve the current values for unchanged components
_Func->GetSphereColor(m_ID, NULL, &s_ColorG, &s_ColorB);
// Perform the requested operation
_Func->SetSphereColor(m_ID, r, s_ColorG, s_ColorB);
}
// ------------------------------------------------------------------------------------------------
static Object & CreateForcefieldEx(CPlayer & player, Int32 world, Float32 x, Float32 y, Float32 z,
void CForcefield::SetColG(Uint32 g) const
{
// Validate the managed identifier
Validate();
// Retrieve the current values for unchanged components
_Func->GetSphereColor(m_ID, &s_ColorR, NULL, &s_ColorB);
// Perform the requested operation
_Func->SetSphereColor(m_ID, s_ColorR, g, s_ColorB);
}
// ------------------------------------------------------------------------------------------------
void CForcefield::SetColB(Uint32 b) const
{
// Validate the managed identifier
Validate();
// Retrieve the current values for unchanged components
_Func->GetSphereColor(m_ID, &s_ColorB, &s_ColorG, NULL);
// Perform the requested operation
_Func->SetSphereColor(m_ID, s_ColorB, s_ColorG, b);
}
// ------------------------------------------------------------------------------------------------
static Object & Forcefield_CreateEx(CPlayer & player, Int32 world, Float32 x, Float32 y, Float32 z,
Uint8 r, Uint8 g, Uint8 b, Float32 radius)
{
return _Core->NewForcefield(player.GetID(), world, x, y, z, r, g, b, radius,
SQMOD_CREATE_DEFAULT, NullObject());
}
static Object & CreateForcefieldEx(CPlayer & player, Int32 world, Float32 x, Float32 y, Float32 z,
static Object & Forcefield_CreateEx(CPlayer & player, Int32 world, Float32 x, Float32 y, Float32 z,
Uint8 r, Uint8 g, Uint8 b, Float32 radius,
Int32 header, Object & payload)
{
@ -314,14 +403,14 @@ static Object & CreateForcefieldEx(CPlayer & player, Int32 world, Float32 x, Flo
}
// ------------------------------------------------------------------------------------------------
static Object & CreateForcefield(CPlayer & player, Int32 world, const Vector3 & pos,
static Object & Forcefield_Create(CPlayer & player, Int32 world, const Vector3 & pos,
const Color3 & color, Float32 radius)
{
return _Core->NewForcefield(player.GetID(), world, pos.x, pos.y, pos.z, color.r, color.g, color.b, radius,
SQMOD_CREATE_DEFAULT, NullObject());
}
static Object & CreateForcefield(CPlayer & player, Int32 world, const Vector3 & pos,
static Object & Forcefield_Create(CPlayer & player, Int32 world, const Vector3 & pos,
const Color3 & color, Float32 radius, Int32 header, Object & payload)
{
return _Core->NewForcefield(player.GetID(), world, pos.x, pos.y, pos.z, color.r, color.g, color.b, radius,
@ -333,22 +422,24 @@ void Register_CForcefield(HSQUIRRELVM vm)
{
RootTable(vm).Bind(_SC("SqForcefield"),
Class< CForcefield, NoConstructor< CForcefield > >(vm, _SC("SqForcefield"))
/* Metamethods */
// Metamethods
.Func(_SC("_cmp"), &CForcefield::Cmp)
.SquirrelFunc(_SC("_typename"), &CForcefield::Typename)
.Func(_SC("_tostring"), &CForcefield::ToString)
/* Core Properties */
// Static values
.SetStaticValue(_SC("MaxID"), CForcefield::Max)
// Core Properties
.Prop(_SC("ID"), &CForcefield::GetID)
.Prop(_SC("Tag"), &CForcefield::GetTag, &CForcefield::SetTag)
.Prop(_SC("Data"), &CForcefield::GetData, &CForcefield::SetData)
.Prop(_SC("MaxID"), &CForcefield::GetMaxID)
.Prop(_SC("Active"), &CForcefield::IsActive)
/* Core Functions */
// Core Functions
.Func(_SC("Bind"), &CForcefield::BindEvent)
/* Core Overloads */
// Core Overloads
.Overload< bool (CForcefield::*)(void) >(_SC("Destroy"), &CForcefield::Destroy)
.Overload< bool (CForcefield::*)(Int32) >(_SC("Destroy"), &CForcefield::Destroy)
.Overload< bool (CForcefield::*)(Int32, Object &) >(_SC("Destroy"), &CForcefield::Destroy)
/* Properties */
// Properties
.Prop(_SC("World"), &CForcefield::GetWorld, &CForcefield::SetWorld)
.Prop(_SC("Color"), &CForcefield::GetColor, &CForcefield::SetColor)
.Prop(_SC("Pos"), &CForcefield::GetPosition, &CForcefield::SetPosition)
@ -362,22 +453,21 @@ void Register_CForcefield(HSQUIRRELVM vm)
.Prop(_SC("R"), &CForcefield::GetColR, &CForcefield::SetColR)
.Prop(_SC("G"), &CForcefield::GetColG, &CForcefield::SetColG)
.Prop(_SC("B"), &CForcefield::GetColB, &CForcefield::SetColB)
/* Functions */
// Functions
.Func(_SC("StreamedFor"), &CForcefield::IsStreamedFor)
.Func(_SC("SetColor"), &CForcefield::SetColorEx)
.Func(_SC("SetPos"), &CForcefield::SetPositionEx)
.Func(_SC("SetPosition"), &CForcefield::SetPositionEx)
// Static Overloads
.StaticOverload< Object & (*)(CPlayer &, Int32, Float32, Float32, Float32, Uint8, Uint8, Uint8, Float32) >
(_SC("CreateEx"), &Forcefield_CreateEx)
.StaticOverload< Object & (*)(CPlayer &, Int32, Float32, Float32, Float32, Uint8, Uint8, Uint8, Float32, Int32, Object &) >
(_SC("CreateEx"), &Forcefield_CreateEx)
.StaticOverload< Object & (*)(CPlayer &, Int32, const Vector3 &, const Color3 &, Float32) >
(_SC("Create"), &Forcefield_Create)
.StaticOverload< Object & (*)(CPlayer &, Int32, const Vector3 &, const Color3 &, Float32, Int32, Object &) >
(_SC("Create"), &Forcefield_Create)
);
RootTable(vm)
.Overload< Object & (*)(CPlayer &, Int32, Float32, Float32, Float32, Uint8, Uint8, Uint8, Float32) >
(_SC("CreateForcefieldEx"), &CreateForcefieldEx)
.Overload< Object & (*)(CPlayer &, Int32, Float32, Float32, Float32, Uint8, Uint8, Uint8, Float32, Int32, Object &) >
(_SC("CreateForcefieldEx"), &CreateForcefieldEx)
.Overload< Object & (*)(CPlayer &, Int32, const Vector3 &, const Color3 &, Float32) >
(_SC("CreateForcefield"), &CreateForcefield)
.Overload< Object & (*)(CPlayer &, Int32, const Vector3 &, const Color3 &, Float32, Int32, Object &) >
(_SC("CreateForcefield"), &CreateForcefield);
}
} // Namespace:: SqMod
} // Namespace:: SqMod

View File

@ -8,7 +8,7 @@
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Manages Forcefield instances.
* Manages a single forcefield entity.
*/
class CForcefield
{
@ -24,20 +24,19 @@ private:
// --------------------------------------------------------------------------------------------
static Uint32 s_ColorR, s_ColorG, s_ColorB;
/* --------------------------------------------------------------------------------------------
* Cached identifiers for fast integer to string conversion.
*/
static SQChar s_StrID[SQMOD_FORCEFIELD_POOL][8];
/* --------------------------------------------------------------------------------------------
* Identifier of the managed entity.
*/
Int32 m_ID;
/* --------------------------------------------------------------------------------------------
* User tag and data associated with this instance.
* User tag associated with this instance.
*/
String m_Tag;
/* --------------------------------------------------------------------------------------------
* User data associated with this instance.
*/
Object m_Data;
/* --------------------------------------------------------------------------------------------
@ -45,20 +44,22 @@ private:
*/
CForcefield(Int32 id);
public:
/* --------------------------------------------------------------------------------------------
* Maximum possible number that could represent an identifier for this entity type.
*/
static const Int32 Max;
/* --------------------------------------------------------------------------------------------
* Copy constructor. (disabled)
*/
CForcefield(const CForcefield &);
CForcefield(const CForcefield &) = delete;
/* --------------------------------------------------------------------------------------------
* Copy assignment operator. (disabled)
* Move constructor. (disabled)
*/
CForcefield & operator = (const CForcefield &);
public:
// --------------------------------------------------------------------------------------------
static const Int32 Max;
CForcefield(CForcefield &&) = delete;
/* --------------------------------------------------------------------------------------------
* Destructor.
@ -66,14 +67,22 @@ public:
~CForcefield();
/* --------------------------------------------------------------------------------------------
* See whether this instance manages a valid entity.
* Copy assignment operator. (disabled)
*/
bool Validate() const
CForcefield & operator = (const CForcefield &) = delete;
/* --------------------------------------------------------------------------------------------
* Move assignment operator. (disabled)
*/
CForcefield & operator = (CForcefield &&) = delete;
/* --------------------------------------------------------------------------------------------
* See whether this instance manages a valid entity otherwise throw an exception.
*/
void Validate() const
{
if (VALID_ENTITY(m_ID))
return true;
SqThrow("Invalid forcefield reference [%s]", m_Tag.c_str());
return false;
if (INVALID_ENTITY(m_ID))
SqThrowF("Invalid forcefield reference [%s]", m_Tag.c_str());
}
/* --------------------------------------------------------------------------------------------
@ -84,27 +93,33 @@ public:
/* --------------------------------------------------------------------------------------------
* Used by the script engine to convert an instance of this type to a string.
*/
CSStr ToString() const;
const String & ToString() const;
/* --------------------------------------------------------------------------------------------
* Used by the script engine to retrieve the name from instances of this type.
*/
static SQInteger Typename(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Retrieve the identifier of the entity managed by this instance.
*/
Int32 GetID() const { return m_ID; }
/* --------------------------------------------------------------------------------------------
* Retrieve the maximum possible identifier to an entity of this type.
*/
Int32 GetMaxID() const { return SQMOD_FORCEFIELD_POOL; }
Int32 GetID() const
{
return m_ID;
}
/* --------------------------------------------------------------------------------------------
* Check whether this instance manages a valid entity.
*/
bool IsActive() const { return VALID_ENTITY(m_ID); }
bool IsActive() const
{
return VALID_ENTITY(m_ID);
}
/* --------------------------------------------------------------------------------------------
* Retrieve the associated user tag.
*/
CSStr GetTag() const;
const String & GetTag() const;
/* --------------------------------------------------------------------------------------------
* Modify the associated user tag.
@ -121,43 +136,155 @@ public:
*/
void SetData(Object & data);
// --------------------------------------------------------------------------------------------
/* --------------------------------------------------------------------------------------------
* Destroy the managed forcefield entity.
*/
bool Destroy()
{
return Destroy(0, NullObject());
}
/* --------------------------------------------------------------------------------------------
* Destroy the managed forcefield entity.
*/
bool Destroy(Int32 header)
{
return Destroy(header, NullObject());
}
/* --------------------------------------------------------------------------------------------
* Destroy the managed forcefield entity.
*/
bool Destroy(Int32 header, Object & payload);
bool Destroy() { return Destroy(0, NullObject()); }
bool Destroy(Int32 header) { return Destroy(header, NullObject()); }
// --------------------------------------------------------------------------------------------
bool BindEvent(Int32 evid, Object & env, Function & func) const;
/* --------------------------------------------------------------------------------------------
* Bind to an event supported by this entity type.
*/
void BindEvent(Int32 evid, Object & env, Function & func) const;
// --------------------------------------------------------------------------------------------
/* --------------------------------------------------------------------------------------------
* See if the managed forcefield entity is streamed for the specified player.
*/
bool IsStreamedFor(CPlayer & player) const;
/* --------------------------------------------------------------------------------------------
* Retrieve the world in which the managed forcefield entity exists.
*/
Int32 GetWorld() const;
/* --------------------------------------------------------------------------------------------
* Modify the world in which the managed forcefield entity exists.
*/
void SetWorld(Int32 world) const;
/* --------------------------------------------------------------------------------------------
* Retrieve the color of the managed forcefield entity.
*/
const Color3 & GetColor() const;
/* --------------------------------------------------------------------------------------------
* Modify the color of the managed forcefield entity.
*/
void SetColor(const Color3 & col) const;
/* --------------------------------------------------------------------------------------------
* Modify the color of the managed forcefield entity.
*/
void SetColorEx(Uint8 r, Uint8 g, Uint8 b) const;
/* --------------------------------------------------------------------------------------------
* Retrieve the position of the managed forcefield entity.
*/
const Vector3 & GetPosition() const;
/* --------------------------------------------------------------------------------------------
* Modify the position of the managed forcefield entity.
*/
void SetPosition(const Vector3 & pos) const;
/* --------------------------------------------------------------------------------------------
* Modify the position of the managed forcefield entity.
*/
void SetPositionEx(Float32 x, Float32 y, Float32 z) const;
/* --------------------------------------------------------------------------------------------
* Retrieve the radius of the managed forcefield entity.
*/
Float32 GetRadius() const;
/* --------------------------------------------------------------------------------------------
* Modify the radius of the managed forcefield entity.
*/
void SetRadius(Float32 radius) const;
/* --------------------------------------------------------------------------------------------
* Retrieve the owner of the managed forcefield entity.
*/
Object & GetOwner() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the owner identifier of the managed forcefield entity.
*/
Int32 GetOwnerID() const;
// --------------------------------------------------------------------------------------------
/* --------------------------------------------------------------------------------------------
* Retrieve the position on the x axis of the managed forcefield entity.
*/
Float32 GetPosX() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the position on the y axis of the managed forcefield entity.
*/
Float32 GetPosY() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the position on the z axis of the managed forcefield entity.
*/
Float32 GetPosZ() const;
/* --------------------------------------------------------------------------------------------
* Modify the position on the x axis of the managed forcefield entity.
*/
void SetPosX(Float32 x) const;
/* --------------------------------------------------------------------------------------------
* Modify the position on the y axis of the managed forcefield entity.
*/
void SetPosY(Float32 y) const;
/* --------------------------------------------------------------------------------------------
* Modify the position on the z axis of the managed forcefield entity.
*/
void SetPosZ(Float32 z) const;
// --------------------------------------------------------------------------------------------
/* --------------------------------------------------------------------------------------------
* Retrieve the red color of the managed forcefield entity.
*/
Uint32 GetColR() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the green color of the managed forcefield entity.
*/
Uint32 GetColG() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the blue color of the managed forcefield entity.
*/
Uint32 GetColB() const;
/* --------------------------------------------------------------------------------------------
* Modify the red color of the managed forcefield entity.
*/
void SetColR(Uint32 r) const;
/* --------------------------------------------------------------------------------------------
* Modify the green color of the managed forcefield entity.
*/
void SetColG(Uint32 g) const;
/* --------------------------------------------------------------------------------------------
* Modify the blue color of the managed forcefield entity.
*/
void SetColB(Uint32 b) const;
};

View File

@ -6,15 +6,20 @@
namespace SqMod {
// ------------------------------------------------------------------------------------------------
SQChar CKeybind::s_StrID[SQMOD_KEYBIND_POOL][8];
const Int32 CKeybind::Max = SQMOD_KEYBIND_POOL;
// ------------------------------------------------------------------------------------------------
const Int32 CKeybind::Max = SQMOD_KEYBIND_POOL;
SQInteger CKeybind::Typename(HSQUIRRELVM vm)
{
static SQChar name[] = _SC("SqKeybind");
sq_pushstring(vm, name, sizeof(name));
return 1;
}
// ------------------------------------------------------------------------------------------------
CKeybind::CKeybind(Int32 id)
: m_ID(VALID_ENTITYGETEX(id, SQMOD_KEYBIND_POOL))
, m_Tag(VALID_ENTITY(m_ID) ? s_StrID[m_ID] : _SC("-1"))
, m_Tag(ToStrF("%d", id))
{
/* ... */
}
@ -36,108 +41,124 @@ Int32 CKeybind::Cmp(const CKeybind & o) const
return -1;
}
CSStr CKeybind::ToString() const
// ------------------------------------------------------------------------------------------------
const String & CKeybind::ToString() const
{
return VALID_ENTITYEX(m_ID, SQMOD_KEYBIND_POOL) ? s_StrID[m_ID] : _SC("-1");
return m_Tag;
}
// ------------------------------------------------------------------------------------------------
CSStr CKeybind::GetTag() const
const String & CKeybind::GetTag() const
{
return m_Tag.c_str();
return m_Tag;
}
// ------------------------------------------------------------------------------------------------
void CKeybind::SetTag(CSStr tag)
{
m_Tag.assign(tag);
}
// ------------------------------------------------------------------------------------------------
Object & CKeybind::GetData()
{
if (Validate())
return m_Data;
return NullObject();
// Validate the managed identifier
Validate();
// Return the requested information
return m_Data;
}
// ------------------------------------------------------------------------------------------------
void CKeybind::SetData(Object & data)
{
if (Validate())
m_Data = data;
// Validate the managed identifier
Validate();
// Apply the specified value
m_Data = data;
}
// ------------------------------------------------------------------------------------------------
bool CKeybind::Destroy(Int32 header, Object & payload)
{
// Validate the managed identifier
Validate();
// Perform the requested operation
return _Core->DelKeybind(m_ID, header, payload);
}
// ------------------------------------------------------------------------------------------------
bool CKeybind::BindEvent(Int32 evid, Object & env, Function & func) const
void CKeybind::BindEvent(Int32 evid, Object & env, Function & func) const
{
if (!Validate())
return false;
// Validate the managed identifier
Validate();
// Obtain the function instance called for this event
Function & event = _Core->GetKeybindEvent(m_ID, evid);
// Is the specified callback function null?
if (func.IsNull())
event.Release();
event.Release(); // Then release the current callback
// Assign the specified environment and function
else
event = Function(env.GetVM(), env, func.GetFunc());
return true;
}
// ------------------------------------------------------------------------------------------------
Int32 CKeybind::GetPrimary() const
Int32 CKeybind::GetFirst() const
{
if (Validate())
return _Core->GetKeybind(m_ID).mPrimary;
return -1;
// Validate the managed identifier
Validate();
// Return the requested information
return _Core->GetKeybind(m_ID).mFirst;
}
Int32 CKeybind::GetSecondary() const
// ------------------------------------------------------------------------------------------------
Int32 CKeybind::GetSecond() const
{
if (Validate())
return _Core->GetKeybind(m_ID).mSecondary;
return -1;
// Validate the managed identifier
Validate();
// Return the requested information
return _Core->GetKeybind(m_ID).mSecond;
}
Int32 CKeybind::GetAlternative() const
// ------------------------------------------------------------------------------------------------
Int32 CKeybind::GetThird() const
{
if (Validate())
return _Core->GetKeybind(m_ID).mAlternative;
return -1;
// Validate the managed identifier
Validate();
// Return the requested information
return _Core->GetKeybind(m_ID).mThird;
}
// ------------------------------------------------------------------------------------------------
bool CKeybind::IsRelease() const
{
if (Validate())
return _Core->GetKeybind(m_ID).mRelease;
return false;
// Validate the managed identifier
Validate();
// Return the requested information
return _Core->GetKeybind(m_ID).mRelease;
}
// ------------------------------------------------------------------------------------------------
static Object & CreateKeybindEx(Int32 slot, bool release, Int32 primary, Int32 secondary,
static Object & Keybind_CreateEx(Int32 slot, bool release, Int32 primary, Int32 secondary,
Int32 alternative)
{
return _Core->NewKeybind(slot, release, primary, secondary, alternative,
SQMOD_CREATE_DEFAULT, NullObject());
}
static Object & CreateKeybindEx(Int32 slot, bool release, Int32 primary, Int32 secondary,
static Object & Keybind_CreateEx(Int32 slot, bool release, Int32 primary, Int32 secondary,
Int32 alternative, Int32 header, Object & payload)
{
return _Core->NewKeybind(slot, release, primary, secondary, alternative, header, payload);
}
// ------------------------------------------------------------------------------------------------
static Object & CreateKeybind(bool release, Int32 primary, Int32 secondary, Int32 alternative)
static Object & Keybind_Create(bool release, Int32 primary, Int32 secondary, Int32 alternative)
{
return _Core->NewKeybind(-1, release, primary, secondary, alternative,
SQMOD_CREATE_DEFAULT, NullObject());
}
static Object & CreateKeybind(bool release, Int32 primary, Int32 secondary, Int32 alternative,
static Object & Keybind_Create(bool release, Int32 primary, Int32 secondary, Int32 alternative,
Int32 header, Object & payload)
{
return _Core->NewKeybind(-1, release, primary, secondary, alternative, header, payload);
@ -148,37 +169,38 @@ void Register_CKeybind(HSQUIRRELVM vm)
{
RootTable(vm).Bind(_SC("SqKeybind"),
Class< CKeybind, NoConstructor< CKeybind > >(vm, _SC("SqKeybind"))
/* Metamethods */
// Metamethods
.Func(_SC("_cmp"), &CKeybind::Cmp)
.SquirrelFunc(_SC("_typename"), &CKeybind::Typename)
.Func(_SC("_tostring"), &CKeybind::ToString)
/* Core Properties */
// Static values
.SetStaticValue(_SC("MaxID"), CKeybind::Max)
// Core Properties
.Prop(_SC("ID"), &CKeybind::GetID)
.Prop(_SC("Tag"), &CKeybind::GetTag, &CKeybind::SetTag)
.Prop(_SC("Data"), &CKeybind::GetData, &CKeybind::SetData)
.Prop(_SC("MaxID"), &CKeybind::GetMaxID)
.Prop(_SC("Active"), &CKeybind::IsActive)
/* Core Functions */
// Core Functions
.Func(_SC("Bind"), &CKeybind::BindEvent)
/* Core Overloads */
// Core Overloads
.Overload< bool (CKeybind::*)(void) >(_SC("Destroy"), &CKeybind::Destroy)
.Overload< bool (CKeybind::*)(Int32) >(_SC("Destroy"), &CKeybind::Destroy)
.Overload< bool (CKeybind::*)(Int32, Object &) >(_SC("Destroy"), &CKeybind::Destroy)
/* Properties */
.Prop(_SC("Primary"), &CKeybind::GetPrimary)
.Prop(_SC("Secondary"), &CKeybind::GetSecondary)
.Prop(_SC("Alternative"), &CKeybind::GetAlternative)
// Properties
.Prop(_SC("First"), &CKeybind::GetFirst)
.Prop(_SC("Second"), &CKeybind::GetSecond)
.Prop(_SC("Third"), &CKeybind::GetThird)
.Prop(_SC("Release"), &CKeybind::IsRelease)
// Static Overloads
.StaticOverload< Object & (*)(Int32, bool, Int32, Int32, Int32) >
(_SC("CreateEx"), &Keybind_CreateEx)
.StaticOverload< Object & (*)(Int32, bool, Int32, Int32, Int32, Int32, Object &) >
(_SC("CreateEx"), &Keybind_CreateEx)
.StaticOverload< Object & (*)(bool, Int32, Int32, Int32) >
(_SC("Create"), &Keybind_Create)
.StaticOverload< Object & (*)(bool, Int32, Int32, Int32, Int32, Object &) >
(_SC("Create"), &Keybind_Create)
);
RootTable(vm)
.Overload< Object & (*)(Int32, bool, Int32, Int32, Int32) >
(_SC("CreateKeybindEx"), &CreateKeybindEx)
.Overload< Object & (*)(Int32, bool, Int32, Int32, Int32, Int32, Object &) >
(_SC("CreateKeybindEx"), &CreateKeybindEx)
.Overload< Object & (*)(bool, Int32, Int32, Int32) >
(_SC("CreateKeybind"), &CreateKeybind)
.Overload< Object & (*)(bool, Int32, Int32, Int32, Int32, Object &) >
(_SC("CreateKeybind"), &CreateKeybind);
}
} // Namespace:: SqMod

View File

@ -8,7 +8,7 @@
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Manages Keybind instances.
* Manages a single keybind entity.
*/
class CKeybind
{
@ -17,20 +17,19 @@ class CKeybind
private:
/* --------------------------------------------------------------------------------------------
* Cached identifiers for fast integer to string conversion.
*/
static SQChar s_StrID[SQMOD_KEYBIND_POOL][8];
/* --------------------------------------------------------------------------------------------
* Identifier of the managed entity.
*/
Int32 m_ID;
/* --------------------------------------------------------------------------------------------
* User tag and data associated with this instance.
* User tag associated with this instance.
*/
String m_Tag;
/* --------------------------------------------------------------------------------------------
* User data associated with this instance.
*/
Object m_Data;
/* --------------------------------------------------------------------------------------------
@ -38,20 +37,22 @@ private:
*/
CKeybind(Int32 id);
public:
/* --------------------------------------------------------------------------------------------
* Maximum possible number that could represent an identifier for this entity type.
*/
static const Int32 Max;
/* --------------------------------------------------------------------------------------------
* Copy constructor. (disabled)
*/
CKeybind(const CKeybind &);
CKeybind(const CKeybind &) = delete;
/* --------------------------------------------------------------------------------------------
* Copy assignment operator. (disabled)
* Move constructor. (disabled)
*/
CKeybind & operator = (const CKeybind &);
public:
// --------------------------------------------------------------------------------------------
static const Int32 Max;
CKeybind(CKeybind &&) = delete;
/* --------------------------------------------------------------------------------------------
* Destructor.
@ -59,14 +60,22 @@ public:
~CKeybind();
/* --------------------------------------------------------------------------------------------
* See whether this instance manages a valid entity.
* Copy assignment operator. (disabled)
*/
bool Validate() const
CKeybind & operator = (const CKeybind &) = delete;
/* --------------------------------------------------------------------------------------------
* Move assignment operator. (disabled)
*/
CKeybind & operator = (CKeybind &&) = delete;
/* --------------------------------------------------------------------------------------------
* See whether this instance manages a valid entity instance otherwise throw an exception.
*/
void Validate() const
{
if (VALID_ENTITY(m_ID))
return true;
SqThrow("Invalid keybind reference [%s]", m_Tag.c_str());
return false;
if (INVALID_ENTITY(m_ID))
SqThrowF("Invalid keybind reference [%s]", m_Tag.c_str());
}
/* --------------------------------------------------------------------------------------------
@ -77,27 +86,33 @@ public:
/* --------------------------------------------------------------------------------------------
* Used by the script engine to convert an instance of this type to a string.
*/
CSStr ToString() const;
const String & ToString() const;
/* --------------------------------------------------------------------------------------------
* Used by the script engine to retrieve the name from instances of this type.
*/
static SQInteger Typename(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Retrieve the identifier of the entity managed by this instance.
*/
Int32 GetID() const { return m_ID; }
/* --------------------------------------------------------------------------------------------
* Retrieve the maximum possible identifier to an entity of this type.
*/
Int32 GetMaxID() const { return SQMOD_KEYBIND_POOL; }
Int32 GetID() const
{
return m_ID;
}
/* --------------------------------------------------------------------------------------------
* Check whether this instance manages a valid entity.
*/
bool IsActive() const { return VALID_ENTITY(m_ID); }
bool IsActive() const
{
return VALID_ENTITY(m_ID);
}
/* --------------------------------------------------------------------------------------------
* Retrieve the associated user tag.
*/
CSStr GetTag() const;
const String & GetTag() const;
/* --------------------------------------------------------------------------------------------
* Modify the associated user tag.
@ -114,18 +129,50 @@ public:
*/
void SetData(Object & data);
// --------------------------------------------------------------------------------------------
/* --------------------------------------------------------------------------------------------
* Destroy the managed destroy entity.
*/
bool Destroy()
{
return Destroy(0, NullObject());
}
/* --------------------------------------------------------------------------------------------
* Destroy the managed destroy entity.
*/
bool Destroy(Int32 header)
{
return Destroy(header, NullObject());
}
/* --------------------------------------------------------------------------------------------
* Destroy the managed destroy entity.
*/
bool Destroy(Int32 header, Object & payload);
bool Destroy() { return Destroy(0, NullObject()); }
bool Destroy(Int32 header) { return Destroy(header, NullObject()); }
// --------------------------------------------------------------------------------------------
bool BindEvent(Int32 evid, Object & env, Function & func) const;
/* --------------------------------------------------------------------------------------------
* Bind to an event supported by this entity type.
*/
void BindEvent(Int32 evid, Object & env, Function & func) const;
// --------------------------------------------------------------------------------------------
Int32 GetPrimary() const;
Int32 GetSecondary() const;
Int32 GetAlternative() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the first key code of the managed keybind entity.
*/
Int32 GetFirst() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the second key code of the managed keybind entity.
*/
Int32 GetSecond() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the third key code of the managed keybind entity.
*/
Int32 GetThird() const;
/* --------------------------------------------------------------------------------------------
* See whether the managed keybind entity reacts to key release events.
*/
bool IsRelease() const;
};

View File

@ -13,15 +13,20 @@ Vector3 CObject::s_Vector3;
Quaternion CObject::s_Quaternion;
// ------------------------------------------------------------------------------------------------
SQChar CObject::s_StrID[SQMOD_OBJECT_POOL][8];
const Int32 CObject::Max = SQMOD_OBJECT_POOL;
// ------------------------------------------------------------------------------------------------
const Int32 CObject::Max = SQMOD_OBJECT_POOL;
SQInteger CObject::Typename(HSQUIRRELVM vm)
{
static SQChar name[] = _SC("SqObject");
sq_pushstring(vm, name, sizeof(name));
return 1;
}
// ------------------------------------------------------------------------------------------------
CObject::CObject(Int32 id)
: m_ID(VALID_ENTITYGETEX(id, SQMOD_OBJECT_POOL))
, m_Tag(VALID_ENTITY(m_ID) ? s_StrID[m_ID] : _SC("-1"))
, m_Tag(ToStrF("%d", id))
{
/* ... */
}
@ -43,372 +48,517 @@ Int32 CObject::Cmp(const CObject & o) const
return -1;
}
CSStr CObject::ToString() const
// ------------------------------------------------------------------------------------------------
const String & CObject::ToString() const
{
return VALID_ENTITYEX(m_ID, SQMOD_OBJECT_POOL) ? s_StrID[m_ID] : _SC("-1");
return m_Tag;
}
// ------------------------------------------------------------------------------------------------
CSStr CObject::GetTag() const
const String & CObject::GetTag() const
{
return m_Tag.c_str();
return m_Tag;
}
// ------------------------------------------------------------------------------------------------
void CObject::SetTag(CSStr tag)
{
m_Tag.assign(tag);
}
// ------------------------------------------------------------------------------------------------
Object & CObject::GetData()
{
if (Validate())
return m_Data;
return NullObject();
// Validate the managed identifier
Validate();
// Return the requested information
return m_Data;
}
// ------------------------------------------------------------------------------------------------
void CObject::SetData(Object & data)
{
if (Validate())
m_Data = data;
// Validate the managed identifier
Validate();
// Apply the specified value
m_Data = data;
}
// ------------------------------------------------------------------------------------------------
bool CObject::Destroy(Int32 header, Object & payload)
{
// Validate the managed identifier
Validate();
// Perform the requested operation
return _Core->DelObject(m_ID, header, payload);
}
// ------------------------------------------------------------------------------------------------
bool CObject::BindEvent(Int32 evid, Object & env, Function & func) const
void CObject::BindEvent(Int32 evid, Object & env, Function & func) const
{
if (!Validate())
return false;
// Validate the managed identifier
Validate();
// Obtain the function instance called for this event
Function & event = _Core->GetObjectEvent(m_ID, evid);
// Is the specified callback function null?
if (func.IsNull())
event.Release();
event.Release(); // Then release the current callback
// Assign the specified environment and function
else
event = Function(env.GetVM(), env, func.GetFunc());
return true;
}
// ------------------------------------------------------------------------------------------------
bool CObject::IsStreamedFor(CPlayer & player) const
{
// Is the specified player even valid?
if (!player.IsActive())
SqThrow("Invalid player argument: null");
else if (Validate())
return _Func->IsObjectStreamedForPlayer(m_ID, player.GetID());
return false;
SqThrowF("Invalid player argument: null");
// Validate the managed identifier
Validate();
// Return the requested information
return _Func->IsObjectStreamedForPlayer(m_ID, player.GetID());
}
// ------------------------------------------------------------------------------------------------
Int32 CObject::GetModel() const
{
if (Validate())
return _Func->GetObjectModel(m_ID);
return -1;
// Validate the managed identifier
Validate();
// Return the requested information
return _Func->GetObjectModel(m_ID);
}
// ------------------------------------------------------------------------------------------------
Int32 CObject::GetWorld() const
{
if (Validate())
return _Func->GetObjectWorld(m_ID);
return -1;
// Validate the managed identifier
Validate();
// Return the requested information
return _Func->GetObjectWorld(m_ID);
}
// ------------------------------------------------------------------------------------------------
void CObject::SetWorld(Int32 world) const
{
if (Validate())
_Func->SetObjectWorld(m_ID, world);
// Validate the managed identifier
Validate();
// Perform the requested operation
_Func->SetObjectWorld(m_ID, world);
}
// ------------------------------------------------------------------------------------------------
Int32 CObject::GetAlpha() const
{
if (Validate())
return _Func->GetObjectAlpha(m_ID);
return -1;
// Validate the managed identifier
Validate();
// Return the requested information
return _Func->GetObjectAlpha(m_ID);
}
// ------------------------------------------------------------------------------------------------
void CObject::SetAlpha(Int32 alpha) const
{
if (Validate())
_Func->SetObjectAlpha(m_ID, alpha, 0);
// Validate the managed identifier
Validate();
// Perform the requested operation
_Func->SetObjectAlpha(m_ID, alpha, 0);
}
// ------------------------------------------------------------------------------------------------
void CObject::SetAlphaEx(Int32 alpha, Int32 time) const
{
if (Validate())
_Func->SetObjectAlpha(m_ID, alpha, time);
// Validate the managed identifier
Validate();
// Perform the requested operation
_Func->SetObjectAlpha(m_ID, alpha, time);
}
// ------------------------------------------------------------------------------------------------
void CObject::MoveTo(const Vector3 & pos, Int32 time) const
{
if (Validate())
_Func->MoveObjectTo(m_ID, pos.x, pos.y, pos.z, time);
// Validate the managed identifier
Validate();
// Perform the requested operation
_Func->MoveObjectTo(m_ID, pos.x, pos.y, pos.z, time);
}
// ------------------------------------------------------------------------------------------------
void CObject::MoveToEx(Float32 x, Float32 y, Float32 z, Int32 time) const
{
if (Validate())
_Func->MoveObjectTo(m_ID, x, y, z, time);
// Validate the managed identifier
Validate();
// Perform the requested operation
_Func->MoveObjectTo(m_ID, x, y, z, time);
}
// ------------------------------------------------------------------------------------------------
void CObject::MoveBy(const Vector3 & pos, Int32 time) const
{
if (Validate())
_Func->MoveObjectBy(m_ID, pos.x, pos.y, pos.z, time);
// Validate the managed identifier
Validate();
// Perform the requested operation
_Func->MoveObjectBy(m_ID, pos.x, pos.y, pos.z, time);
}
// ------------------------------------------------------------------------------------------------
void CObject::MoveByEx(Float32 x, Float32 y, Float32 z, Int32 time) const
{
if (Validate())
_Func->MoveObjectBy(m_ID, x, y, z, time);
// Validate the managed identifier
Validate();
// Perform the requested operation
_Func->MoveObjectBy(m_ID, x, y, z, time);
}
// ------------------------------------------------------------------------------------------------
const Vector3 & CObject::GetPosition()
{
// Validate the managed identifier
Validate();
// Clear previous position information
s_Vector3.Clear();
if (Validate())
_Func->GetObjectPos(m_ID, &s_Vector3.x, &s_Vector3.y, &s_Vector3.z);
// Query the server for the position values
_Func->GetObjectPos(m_ID, &s_Vector3.x, &s_Vector3.y, &s_Vector3.z);
// Return the requested information
return s_Vector3;
}
// ------------------------------------------------------------------------------------------------
void CObject::SetPosition(const Vector3 & pos) const
{
if (Validate())
_Func->SetObjectPos(m_ID, pos.x, pos.y, pos.z);
// Validate the managed identifier
Validate();
// Perform the requested operation
_Func->SetObjectPos(m_ID, pos.x, pos.y, pos.z);
}
// ------------------------------------------------------------------------------------------------
void CObject::SetPositionEx(Float32 x, Float32 y, Float32 z) const
{
if (Validate())
_Func->SetObjectPos(m_ID, x, y, z);
// Validate the managed identifier
Validate();
// Perform the requested operation
_Func->SetObjectPos(m_ID, x, y, z);
}
// ------------------------------------------------------------------------------------------------
void CObject::RotateTo(const Quaternion & rot, Int32 time) const
{
if (Validate())
_Func->RotObjectTo(m_ID, rot.x, rot.y, rot.z, rot.w, time);
// Validate the managed identifier
Validate();
// Perform the requested operation
_Func->RotObjectTo(m_ID, rot.x, rot.y, rot.z, rot.w, time);
}
// ------------------------------------------------------------------------------------------------
void CObject::RotateToEx(Float32 x, Float32 y, Float32 z, Float32 w, Int32 time) const
{
if (Validate())
_Func->RotObjectTo(m_ID, x, y, z, w, time);
// Validate the managed identifier
Validate();
// Perform the requested operation
_Func->RotObjectTo(m_ID, x, y, z, w, time);
}
// ------------------------------------------------------------------------------------------------
void CObject::RotateToEuler(const Vector3 & rot, Int32 time) const
{
if (Validate())
_Func->RotObjectToEuler(m_ID, rot.x, rot.y, rot.z, time);
// Validate the managed identifier
Validate();
// Perform the requested operation
_Func->RotObjectToEuler(m_ID, rot.x, rot.y, rot.z, time);
}
// ------------------------------------------------------------------------------------------------
void CObject::RotateToEulerEx(Float32 x, Float32 y, Float32 z, Int32 time) const
{
if (Validate())
_Func->RotObjectToEuler(m_ID, x, y, z, time);
// Validate the managed identifier
Validate();
// Perform the requested operation
_Func->RotObjectToEuler(m_ID, x, y, z, time);
}
// ------------------------------------------------------------------------------------------------
void CObject::RotateBy(const Quaternion & rot, Int32 time) const
{
if (Validate())
_Func->RotObjectBy(m_ID, rot.x, rot.y, rot.z, rot.w, time);
// Validate the managed identifier
Validate();
// Perform the requested operation
_Func->RotObjectBy(m_ID, rot.x, rot.y, rot.z, rot.w, time);
}
// ------------------------------------------------------------------------------------------------
void CObject::RotateByEx(Float32 x, Float32 y, Float32 z, Float32 w, Int32 time) const
{
if (Validate())
_Func->RotObjectBy(m_ID, x, y, z, w, time);
// Validate the managed identifier
Validate();
// Perform the requested operation
_Func->RotObjectBy(m_ID, x, y, z, w, time);
}
// ------------------------------------------------------------------------------------------------
void CObject::RotateByEuler(const Vector3 & rot, Int32 time) const
{
if (Validate())
_Func->RotObjectByEuler(m_ID, rot.x, rot.y, rot.z, time);
// Validate the managed identifier
Validate();
// Perform the requested operation
_Func->RotObjectByEuler(m_ID, rot.x, rot.y, rot.z, time);
}
// ------------------------------------------------------------------------------------------------
void CObject::RotateByEulerEx(Float32 x, Float32 y, Float32 z, Int32 time) const
{
if (Validate())
_Func->RotObjectByEuler(m_ID, x, y, z, time);
// Validate the managed identifier
Validate();
// Perform the requested operation
_Func->RotObjectByEuler(m_ID, x, y, z, time);
}
// ------------------------------------------------------------------------------------------------
const Quaternion & CObject::GetRotation()
{
// Validate the managed identifier
Validate();
// Clear previous rotation information
s_Quaternion.Clear();
if (Validate())
_Func->GetObjectRot(m_ID, &s_Quaternion.x, &s_Quaternion.y, &s_Quaternion.z, &s_Quaternion.w);
// Query the server for the rotation values
_Func->GetObjectRot(m_ID, &s_Quaternion.x, &s_Quaternion.y, &s_Quaternion.z, &s_Quaternion.w);
// Return the requested information
return s_Quaternion;
}
// ------------------------------------------------------------------------------------------------
const Vector3 & CObject::GetRotationEuler()
{
// Validate the managed identifier
Validate();
// Clear previous rotation information
s_Vector3.Clear();
if (Validate())
_Func->GetObjectRotEuler(m_ID, &s_Vector3.x, &s_Vector3.y, &s_Vector3.z);
// Query the server for the rotation values
_Func->GetObjectRotEuler(m_ID, &s_Vector3.x, &s_Vector3.y, &s_Vector3.z);
// Return the requested information
return s_Vector3;
}
// ------------------------------------------------------------------------------------------------
bool CObject::GetShotReport() const
{
if (Validate())
return _Func->IsObjectShotReport(m_ID);
return false;
// Validate the managed identifier
Validate();
// Return the requested information
return _Func->IsObjectShotReport(m_ID);
}
// ------------------------------------------------------------------------------------------------
void CObject::SetShotReport(bool toggle) const
{
if (Validate())
_Func->SetObjectShotReport(m_ID, toggle);
// Validate the managed identifier
Validate();
// Perform the requested operation
_Func->SetObjectShotReport(m_ID, toggle);
}
// ------------------------------------------------------------------------------------------------
bool CObject::GetBumpReport() const
{
if (Validate())
return _Func->IsObjectBumpReport(m_ID);
return false;
// Validate the managed identifier
Validate();
// Return the requested information
return _Func->IsObjectBumpReport(m_ID);
}
// ------------------------------------------------------------------------------------------------
void CObject::SetBumpReport(bool toggle) const
{
if (Validate())
_Func->SetObjectBumpReport(m_ID, toggle);
// Validate the managed identifier
Validate();
// Perform the requested operation
_Func->SetObjectBumpReport(m_ID, toggle);
}
// ------------------------------------------------------------------------------------------------
Float32 CObject::GetPosX() const
{
// Validate the managed identifier
Validate();
// Clear previous position information, if any
s_Vector3.x = 0;
if (Validate())
_Func->GetObjectPos(m_ID, &s_Vector3.x, NULL, NULL);
// Query the server for the requested component value
_Func->GetObjectPos(m_ID, &s_Vector3.x, NULL, NULL);
// Return the requested information
return s_Vector3.x;
}
// ------------------------------------------------------------------------------------------------
Float32 CObject::GetPosY() const
{
// Validate the managed identifier
Validate();
// Clear previous position information, if any
s_Vector3.y = 0;
if (Validate())
_Func->GetObjectPos(m_ID, NULL, &s_Vector3.y, NULL);
// Query the server for the requested component value
_Func->GetObjectPos(m_ID, NULL, &s_Vector3.y, NULL);
// Return the requested information
return s_Vector3.y;
}
// ------------------------------------------------------------------------------------------------
Float32 CObject::GetPosZ() const
{
// Validate the managed identifier
Validate();
// Clear previous position information, if any
s_Vector3.z = 0;
if (Validate())
_Func->GetObjectPos(m_ID, NULL, NULL, &s_Vector3.z);
// Query the server for the requested component value
_Func->GetObjectPos(m_ID, NULL, NULL, &s_Vector3.z);
// Return the requested information
return s_Vector3.z;
}
// ------------------------------------------------------------------------------------------------
void CObject::SetPosX(Float32 x) const
{
if (Validate())
{
_Func->GetObjectPos(m_ID, NULL, &s_Vector3.y, &s_Vector3.z);
_Func->SetObjectPos(m_ID, x, s_Vector3.y, s_Vector3.z);
}
// Validate the managed identifier
Validate();
// Retrieve the current values for unchanged components
_Func->GetObjectPos(m_ID, NULL, &s_Vector3.y, &s_Vector3.z);
// Perform the requested operation
_Func->SetObjectPos(m_ID, x, s_Vector3.y, s_Vector3.z);
}
// ------------------------------------------------------------------------------------------------
void CObject::SetPosY(Float32 y) const
{
if (Validate())
{
_Func->GetObjectPos(m_ID, &s_Vector3.x, NULL, &s_Vector3.z);
_Func->SetObjectPos(m_ID, s_Vector3.x, y, s_Vector3.z);
}
// Validate the managed identifier
Validate();
// Retrieve the current values for unchanged components
_Func->GetObjectPos(m_ID, &s_Vector3.x, NULL, &s_Vector3.z);
// Perform the requested operation
_Func->SetObjectPos(m_ID, s_Vector3.x, y, s_Vector3.z);
}
// ------------------------------------------------------------------------------------------------
void CObject::SetPosZ(Float32 z) const
{
if (Validate())
{
_Func->GetObjectPos(m_ID, &s_Vector3.x, &s_Vector3.y, NULL);
_Func->SetObjectPos(m_ID, s_Vector3.z, s_Vector3.y, z);
}
// Validate the managed identifier
Validate();
// Retrieve the current values for unchanged components
_Func->GetObjectPos(m_ID, &s_Vector3.x, &s_Vector3.y, NULL);
// Perform the requested operation
_Func->SetObjectPos(m_ID, s_Vector3.z, s_Vector3.y, z);
}
// ------------------------------------------------------------------------------------------------
Float32 CObject::GetRotX() const
{
// Validate the managed identifier
Validate();
// Clear previous rotation information, if any
s_Quaternion.x = 0;
if (Validate())
_Func->GetObjectRot(m_ID, &s_Quaternion.x, NULL, NULL, NULL);
// Query the server for the requested component value
_Func->GetObjectRot(m_ID, &s_Quaternion.x, NULL, NULL, NULL);
// Return the requested information
return s_Quaternion.x;
}
// ------------------------------------------------------------------------------------------------
Float32 CObject::GetRotY() const
{
// Validate the managed identifier
Validate();
// Clear previous rotation information, if any
s_Quaternion.y = 0;
if (Validate())
_Func->GetObjectRot(m_ID, NULL, &s_Quaternion.y, NULL, NULL);
// Query the server for the requested component value
_Func->GetObjectRot(m_ID, NULL, &s_Quaternion.y, NULL, NULL);
// Return the requested information
return s_Quaternion.y;
}
// ------------------------------------------------------------------------------------------------
Float32 CObject::GetRotZ() const
{
// Validate the managed identifier
Validate();
// Clear previous rotation information, if any
s_Quaternion.z = 0;
if (Validate())
_Func->GetObjectRot(m_ID, NULL, NULL, &s_Quaternion.z, NULL);
// Query the server for the requested component value
_Func->GetObjectRot(m_ID, NULL, NULL, &s_Quaternion.z, NULL);
// Return the requested information
return s_Quaternion.z;
}
// ------------------------------------------------------------------------------------------------
Float32 CObject::GetRotW() const
{
// Validate the managed identifier
Validate();
// Clear previous rotation information, if any
s_Quaternion.w = 0;
if (Validate())
_Func->GetObjectRot(m_ID, NULL, NULL, NULL, &s_Quaternion.w);
// Query the server for the requested component value
_Func->GetObjectRot(m_ID, NULL, NULL, NULL, &s_Quaternion.w);
// Return the requested information
return s_Quaternion.w;
}
// ------------------------------------------------------------------------------------------------
Float32 CObject::GetERotX() const
{
// Validate the managed identifier
Validate();
// Clear previous rotation information, if any
s_Vector3.x = 0;
if (Validate())
_Func->GetObjectRotEuler(m_ID, &s_Vector3.x, NULL, NULL);
// Query the server for the requested component value
_Func->GetObjectRotEuler(m_ID, &s_Vector3.x, NULL, NULL);
// Return the requested information
return s_Vector3.x;
}
// ------------------------------------------------------------------------------------------------
Float32 CObject::GetERotY() const
{
// Validate the managed identifier
Validate();
// Clear previous rotation information, if any
s_Vector3.y = 0;
if (Validate())
_Func->GetObjectRotEuler(m_ID, NULL, &s_Vector3.y, NULL);
// Query the server for the requested component value
_Func->GetObjectRotEuler(m_ID, NULL, &s_Vector3.y, NULL);
// Return the requested information
return s_Vector3.y;
}
// ------------------------------------------------------------------------------------------------
Float32 CObject::GetERotZ() const
{
// Validate the managed identifier
Validate();
// Clear previous rotation information, if any
s_Vector3.z = 0;
if (Validate())
_Func->GetObjectRotEuler(m_ID, NULL, NULL, &s_Vector3.z);
// Query the server for the requested component value
_Func->GetObjectRotEuler(m_ID, NULL, NULL, &s_Vector3.z);
// Return the requested information
return s_Vector3.z;
}
// ------------------------------------------------------------------------------------------------
static Object & CreateObjectEx(Int32 model, Int32 world, Float32 x, Float32 y, Float32 z,
static Object & Object_CreateEx(Int32 model, Int32 world, Float32 x, Float32 y, Float32 z,
Int32 alpha)
{
return _Core->NewObject(model, world, x, y, z, alpha, SQMOD_CREATE_DEFAULT, NullObject());
}
static Object & CreateObjectEx(Int32 model, Int32 world, Float32 x, Float32 y, Float32 z,
static Object & Object_CreateEx(Int32 model, Int32 world, Float32 x, Float32 y, Float32 z,
Int32 alpha, Int32 header, Object & payload)
{
return _Core->NewObject(model, world, x, y, z, alpha, header, payload);
}
// ------------------------------------------------------------------------------------------------
static Object & CreateObject(Int32 model, Int32 world, const Vector3 & pos, Int32 alpha)
static Object & Object_Create(Int32 model, Int32 world, const Vector3 & pos, Int32 alpha)
{
return _Core->NewObject(model, world, pos.x, pos.y, pos.z, alpha,
SQMOD_CREATE_DEFAULT, NullObject());
}
static Object & CreateObject(Int32 model, Int32 world, const Vector3 & pos, Int32 alpha,
static Object & Object_Create(Int32 model, Int32 world, const Vector3 & pos, Int32 alpha,
Int32 header, Object & payload)
{
return _Core->NewObject(model, world, pos.x, pos.y, pos.z, alpha, header, payload);
@ -419,22 +569,24 @@ void Register_CObject(HSQUIRRELVM vm)
{
RootTable(vm).Bind(_SC("SqObject"),
Class< CObject, NoConstructor< CObject > >(vm, _SC("SqObject"))
/* Metamethods */
// Metamethods
.Func(_SC("_cmp"), &CObject::Cmp)
.SquirrelFunc(_SC("_typename"), &CObject::Typename)
.Func(_SC("_tostring"), &CObject::ToString)
/* Core Properties */
// Static values
.SetStaticValue(_SC("MaxID"), CObject::Max)
// Core Properties
.Prop(_SC("ID"), &CObject::GetID)
.Prop(_SC("Tag"), &CObject::GetTag, &CObject::SetTag)
.Prop(_SC("Data"), &CObject::GetData, &CObject::SetData)
.Prop(_SC("MaxID"), &CObject::GetMaxID)
.Prop(_SC("Active"), &CObject::IsActive)
/* Core Functions */
// Core Functions
.Func(_SC("Bind"), &CObject::BindEvent)
/* Core Overloads */
// Core Overloads
.Overload< bool (CObject::*)(void) >(_SC("Destroy"), &CObject::Destroy)
.Overload< bool (CObject::*)(Int32) >(_SC("Destroy"), &CObject::Destroy)
.Overload< bool (CObject::*)(Int32, Object &) >(_SC("Destroy"), &CObject::Destroy)
/* Properties */
// Properties
.Prop(_SC("Model"), &CObject::GetModel)
.Prop(_SC("World"), &CObject::GetWorld, &CObject::SetWorld)
.Prop(_SC("Alpha"), &CObject::GetAlpha, &CObject::SetAlpha)
@ -455,11 +607,11 @@ void Register_CObject(HSQUIRRELVM vm)
.Prop(_SC("EX"), &CObject::GetERotX)
.Prop(_SC("EY"), &CObject::GetERotY)
.Prop(_SC("EZ"), &CObject::GetERotZ)
/* Functions */
// Functions
.Func(_SC("StreamedFor"), &CObject::IsStreamedFor)
.Func(_SC("SetAlpha"), &CObject::SetAlphaEx)
.Func(_SC("SetPosition"), &CObject::SetPositionEx)
/* Overloads */
// Overloads
.Overload< void (CObject::*)(const Vector3 &, Int32) const >
(_SC("MoveTo"), &CObject::MoveTo)
.Overload< void (CObject::*)(Float32, Float32, Float32, Int32) const >
@ -484,17 +636,16 @@ void Register_CObject(HSQUIRRELVM vm)
(_SC("RotateByEuler"), &CObject::RotateByEuler)
.Overload< void (CObject::*)(Float32, Float32, Float32, Int32) const >
(_SC("RotateByEuler"), &CObject::RotateByEulerEx)
// Static Overloads
.StaticOverload< Object & (*)(Int32, Int32, Float32, Float32, Float32, Int32) >
(_SC("CreateEx"), &Object_CreateEx)
.StaticOverload< Object & (*)(Int32, Int32, Float32, Float32, Float32, Int32, Int32, Object &) >
(_SC("CreateEx"), &Object_CreateEx)
.StaticOverload< Object & (*)(Int32, Int32, const Vector3 &, Int32) >
(_SC("Create"), &Object_Create)
.StaticOverload< Object & (*)(Int32, Int32, const Vector3 &, Int32, Int32, Object &) >
(_SC("Create"), &Object_Create)
);
RootTable(vm)
.Overload< Object & (*)(Int32, Int32, Float32, Float32, Float32, Int32) >
(_SC("CreateObjectEx"), &CreateObjectEx)
.Overload< Object & (*)(Int32, Int32, Float32, Float32, Float32, Int32, Int32, Object &) >
(_SC("CreateObjectEx"), &CreateObjectEx)
.Overload< Object & (*)(Int32, Int32, const Vector3 &, Int32) >
(_SC("CreateObject"), &CreateObject)
.Overload< Object & (*)(Int32, Int32, const Vector3 &, Int32, Int32, Object &) >
(_SC("CreateObject"), &CreateObject);
}
} // Namespace:: SqMod
} // Namespace:: SqMod

View File

@ -8,7 +8,7 @@
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Manages Object instances.
* Manages a single object entity.
*/
class CObject
{
@ -21,20 +21,19 @@ private:
static Vector3 s_Vector3;
static Quaternion s_Quaternion;
/* --------------------------------------------------------------------------------------------
* Cached identifiers for fast integer to string conversion.
*/
static SQChar s_StrID[SQMOD_OBJECT_POOL][8];
/* --------------------------------------------------------------------------------------------
* Identifier of the managed entity.
*/
Int32 m_ID;
/* --------------------------------------------------------------------------------------------
* User tag and data associated with this instance.
* User tag associated with this instance.
*/
String m_Tag;
/* --------------------------------------------------------------------------------------------
* User data associated with this instance.
*/
Object m_Data;
/* --------------------------------------------------------------------------------------------
@ -42,20 +41,22 @@ private:
*/
CObject(Int32 id);
public:
/* --------------------------------------------------------------------------------------------
* Maximum possible number that could represent an identifier for this entity type.
*/
static const Int32 Max;
/* --------------------------------------------------------------------------------------------
* Copy constructor. (disabled)
*/
CObject(const CObject &);
CObject(const CObject &) = delete;
/* --------------------------------------------------------------------------------------------
* Copy assignment operator. (disabled)
* Move constructor. (disabled)
*/
CObject & operator = (const CObject &);
public:
// --------------------------------------------------------------------------------------------
static const Int32 Max;
CObject(CObject &&) = delete;
/* --------------------------------------------------------------------------------------------
* Destructor.
@ -63,14 +64,22 @@ public:
~CObject();
/* --------------------------------------------------------------------------------------------
* See whether this instance manages a valid entity.
* Copy assignment operator. (disabled)
*/
bool Validate() const
CObject & operator = (const CObject &) = delete;
/* --------------------------------------------------------------------------------------------
* Move assignment operator. (disabled)
*/
CObject & operator = (CObject &&) = delete;
/* --------------------------------------------------------------------------------------------
* See whether this instance manages a valid entity instance otherwise throw an exception.
*/
void Validate() const
{
if (VALID_ENTITY(m_ID))
return true;
SqThrow("Invalid object reference [%s]", m_Tag.c_str());
return false;
if (INVALID_ENTITY(m_ID))
SqThrowF("Invalid object reference [%s]", m_Tag.c_str());
}
/* --------------------------------------------------------------------------------------------
@ -81,27 +90,33 @@ public:
/* --------------------------------------------------------------------------------------------
* Used by the script engine to convert an instance of this type to a string.
*/
CSStr ToString() const;
const String & ToString() const;
/* --------------------------------------------------------------------------------------------
* Used by the script engine to retrieve the name from instances of this type.
*/
static SQInteger Typename(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Retrieve the identifier of the entity managed by this instance.
*/
Int32 GetID() const { return m_ID; }
/* --------------------------------------------------------------------------------------------
* Retrieve the maximum possible identifier to an entity of this type.
*/
Int32 GetMaxID() const { return SQMOD_OBJECT_POOL; }
Int32 GetID() const
{
return m_ID;
}
/* --------------------------------------------------------------------------------------------
* Check whether this instance manages a valid entity.
*/
bool IsActive() const { return VALID_ENTITY(m_ID); }
bool IsActive() const
{
return VALID_ENTITY(m_ID);
}
/* --------------------------------------------------------------------------------------------
* Retrieve the associated user tag.
*/
CSStr GetTag() const;
const String & GetTag() const;
/* --------------------------------------------------------------------------------------------
* Modify the associated user tag.
@ -118,59 +133,235 @@ public:
*/
void SetData(Object & data);
// --------------------------------------------------------------------------------------------
/* --------------------------------------------------------------------------------------------
* Destroy the managed object entity.
*/
bool Destroy()
{
return Destroy(0, NullObject());
}
/* --------------------------------------------------------------------------------------------
* Destroy the managed object entity.
*/
bool Destroy(Int32 header)
{
return Destroy(header, NullObject());
}
/* --------------------------------------------------------------------------------------------
* Destroy the managed object entity.
*/
bool Destroy(Int32 header, Object & payload);
bool Destroy() { return Destroy(0, NullObject()); }
bool Destroy(Int32 header) { return Destroy(header, NullObject()); }
// --------------------------------------------------------------------------------------------
bool BindEvent(Int32 evid, Object & env, Function & func) const;
/* --------------------------------------------------------------------------------------------
* Bind to an event supported by this entity type.
*/
void BindEvent(Int32 evid, Object & env, Function & func) const;
// --------------------------------------------------------------------------------------------
/* --------------------------------------------------------------------------------------------
* See if the managed object entity is streamed for the specified player.
*/
bool IsStreamedFor(CPlayer & player) const;
/* --------------------------------------------------------------------------------------------
* Retrieve the model of the managed object entity.
*/
Int32 GetModel() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the world in which the managed object entity exists.
*/
Int32 GetWorld() const;
/* --------------------------------------------------------------------------------------------
* Modify the world in which the managed object entity exists.
*/
void SetWorld(Int32 world) const;
/* --------------------------------------------------------------------------------------------
* Retrieve the alpha of the managed object entity.
*/
Int32 GetAlpha() const;
/* --------------------------------------------------------------------------------------------
* Modify the alpha of the managed object entity.
*/
void SetAlpha(Int32 alpha) const;
/* --------------------------------------------------------------------------------------------
* Modify the alpha of the managed object entity over the specified time.
*/
void SetAlphaEx(Int32 alpha, Int32 time) const;
/* --------------------------------------------------------------------------------------------
* Move the managed object entity to the specified position over the specified time.
*/
void MoveTo(const Vector3 & pos, Int32 time) const;
/* --------------------------------------------------------------------------------------------
* Move the managed object entity to the specified position over the specified time.
*/
void MoveToEx(Float32 x, Float32 y, Float32 z, Int32 time) const;
/* --------------------------------------------------------------------------------------------
* Move the managed object entity by the specified position over the specified time.
*/
void MoveBy(const Vector3 & pos, Int32 time) const;
/* --------------------------------------------------------------------------------------------
* Move the managed object entity by the specified position over the specified time.
*/
void MoveByEx(Float32 x, Float32 y, Float32 z, Int32 time) const;
/* --------------------------------------------------------------------------------------------
* Retrieve the position of the managed object entity.
*/
const Vector3 & GetPosition();
/* --------------------------------------------------------------------------------------------
* Modify the position of the managed object entity.
*/
void SetPosition(const Vector3 & pos) const;
/* --------------------------------------------------------------------------------------------
* Modify the position of the managed object entity.
*/
void SetPositionEx(Float32 x, Float32 y, Float32 z) const;
/* --------------------------------------------------------------------------------------------
* Rotate the managed object entity to the specified rotation over the specified time.
*/
void RotateTo(const Quaternion & rot, Int32 time) const;
/* --------------------------------------------------------------------------------------------
* Rotate the managed object entity to the specified rotation over the specified time.
*/
void RotateToEx(Float32 x, Float32 y, Float32 z, Float32 w, Int32 time) const;
/* --------------------------------------------------------------------------------------------
* Rotate the managed object entity to the specified euler rotation over the specified time.
*/
void RotateToEuler(const Vector3 & rot, Int32 time) const;
/* --------------------------------------------------------------------------------------------
* Rotate the managed object entity to the specified euler rotation over the specified time.
*/
void RotateToEulerEx(Float32 x, Float32 y, Float32 z, Int32 time) const;
/* --------------------------------------------------------------------------------------------
* Rotate the managed object entity by the specified rotation over the specified time.
*/
void RotateBy(const Quaternion & rot, Int32 time) const;
/* --------------------------------------------------------------------------------------------
* Rotate the managed object entity by the specified rotation over the specified time.
*/
void RotateByEx(Float32 x, Float32 y, Float32 z, Float32 w, Int32 time) const;
/* --------------------------------------------------------------------------------------------
* Rotate the managed object entity by the specified euler rotation over the specified time.
*/
void RotateByEuler(const Vector3 & rot, Int32 time) const;
/* --------------------------------------------------------------------------------------------
* Rotate the managed object entity by the specified euler rotation over the specified time.
*/
void RotateByEulerEx(Float32 x, Float32 y, Float32 z, Int32 time) const;
/* --------------------------------------------------------------------------------------------
* Retrieve the rotation of the managed object entity.
*/
const Quaternion & GetRotation();
/* --------------------------------------------------------------------------------------------
* Retrieve the euler rotation of the managed object entity.
*/
const Vector3 & GetRotationEuler();
/* --------------------------------------------------------------------------------------------
* See whether the managed object entity reports gunshots.
*/
bool GetShotReport() const;
/* --------------------------------------------------------------------------------------------
* Set whether the managed object entity reports gunshots.
*/
void SetShotReport(bool toggle) const;
/* --------------------------------------------------------------------------------------------
* See whether the managed object entity reports player bumps.
*/
bool GetBumpReport() const;
/* --------------------------------------------------------------------------------------------
* Set whether the managed object entity reports player bumps.
*/
void SetBumpReport(bool toggle) const;
// --------------------------------------------------------------------------------------------
/* --------------------------------------------------------------------------------------------
* Retrieve the position on the x axis of the managed object entity.
*/
Float32 GetPosX() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the position on the y axis of the managed object entity.
*/
Float32 GetPosY() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the position on the z axis of the managed object entity.
*/
Float32 GetPosZ() const;
/* --------------------------------------------------------------------------------------------
* Modify the position on the x axis of the managed object entity.
*/
void SetPosX(Float32 x) const;
/* --------------------------------------------------------------------------------------------
* Modify the position on the y axis of the managed object entity.
*/
void SetPosY(Float32 y) const;
/* --------------------------------------------------------------------------------------------
* Modify the position on the z axis of the managed object entity.
*/
void SetPosZ(Float32 z) const;
// --------------------------------------------------------------------------------------------
/* --------------------------------------------------------------------------------------------
* Retrieve the rotation on the x axis of the managed object entity.
*/
Float32 GetRotX() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the rotation on the y axis of the managed object entity.
*/
Float32 GetRotY() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the rotation on the z axis of the managed object entity.
*/
Float32 GetRotZ() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the rotation amount of the managed object entity.
*/
Float32 GetRotW() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the euler rotation on the x axis of the managed object entity.
*/
Float32 GetERotX() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the euler rotation on the y axis of the managed object entity.
*/
Float32 GetERotY() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the euler rotation on the z axis of the managed object entity.
*/
Float32 GetERotZ() const;
};

View File

@ -11,15 +11,20 @@ namespace SqMod {
Vector3 CPickup::s_Vector3;
// ------------------------------------------------------------------------------------------------
SQChar CPickup::s_StrID[SQMOD_PICKUP_POOL][8];
const Int32 CPickup::Max = SQMOD_PICKUP_POOL;
// ------------------------------------------------------------------------------------------------
const Int32 CPickup::Max = SQMOD_PICKUP_POOL;
SQInteger CPickup::Typename(HSQUIRRELVM vm)
{
static SQChar name[] = _SC("SqPickup");
sq_pushstring(vm, name, sizeof(name));
return 1;
}
// ------------------------------------------------------------------------------------------------
CPickup::CPickup(Int32 id)
: m_ID(VALID_ENTITYGETEX(id, SQMOD_PICKUP_POOL))
, m_Tag(VALID_ENTITY(m_ID) ? s_StrID[m_ID] : _SC("-1"))
, m_Tag(ToStrF("%d", id))
{
/* ... */
}
@ -41,221 +46,289 @@ Int32 CPickup::Cmp(const CPickup & o) const
return -1;
}
CSStr CPickup::ToString() const
// ------------------------------------------------------------------------------------------------
const String & CPickup::ToString() const
{
return VALID_ENTITYEX(m_ID, SQMOD_PICKUP_POOL) ? s_StrID[m_ID] : _SC("-1");
return m_Tag;
}
// ------------------------------------------------------------------------------------------------
CSStr CPickup::GetTag() const
const String & CPickup::GetTag() const
{
return m_Tag.c_str();
return m_Tag;
}
// ------------------------------------------------------------------------------------------------
void CPickup::SetTag(CSStr tag)
{
m_Tag.assign(tag);
}
// ------------------------------------------------------------------------------------------------
Object & CPickup::GetData()
{
if (Validate())
return m_Data;
return NullObject();
// Validate the managed identifier
Validate();
// Return the requested information
return m_Data;
}
// ------------------------------------------------------------------------------------------------
void CPickup::SetData(Object & data)
{
if (Validate())
m_Data = data;
// Validate the managed identifier
Validate();
// Apply the specified value
m_Data = data;
}
// ------------------------------------------------------------------------------------------------
bool CPickup::Destroy(Int32 header, Object & payload)
{
// Validate the managed identifier
Validate();
// Perform the requested operation
return _Core->DelPickup(m_ID, header, payload);
}
// ------------------------------------------------------------------------------------------------
bool CPickup::BindEvent(Int32 evid, Object & env, Function & func) const
void CPickup::BindEvent(Int32 evid, Object & env, Function & func) const
{
if (!Validate())
return false;
// Validate the managed identifier
Validate();
// Obtain the function instance called for this event
Function & event = _Core->GetPickupEvent(m_ID, evid);
// Is the specified callback function null?
if (func.IsNull())
event.Release();
event.Release(); // Then release the current callback
// Assign the specified environment and function
else
event = Function(env.GetVM(), env, func.GetFunc());
return true;
}
// ------------------------------------------------------------------------------------------------
bool CPickup::IsStreamedFor(CPlayer & player) const
{
// Is the specified player even valid?
if (!player.IsActive())
SqThrow("Invalid player argument: null");
else if (Validate())
return _Func->IsPickupStreamedForPlayer(m_ID, player.GetID());
return false;
SqThrowF("Invalid player argument: null");
// Validate the managed identifier
Validate();
// Return the requested information
return _Func->IsPickupStreamedForPlayer(m_ID, player.GetID());
}
// ------------------------------------------------------------------------------------------------
Int32 CPickup::GetModel() const
{
if (Validate())
return _Func->PickupGetModel(m_ID);
return -1;
// Validate the managed identifier
Validate();
// Return the requested information
return _Func->PickupGetModel(m_ID);
}
// ------------------------------------------------------------------------------------------------
Int32 CPickup::GetWorld() const
{
if (Validate())
return _Func->GetPickupWorld(m_ID);
return -1;
// Validate the managed identifier
Validate();
// Return the requested information
return _Func->GetPickupWorld(m_ID);
}
// ------------------------------------------------------------------------------------------------
void CPickup::SetWorld(Int32 world) const
{
if (Validate())
_Func->SetPickupWorld(m_ID, world);
// Validate the managed identifier
Validate();
// Perform the requested operation
_Func->SetPickupWorld(m_ID, world);
}
// ------------------------------------------------------------------------------------------------
Int32 CPickup::GetAlpha() const
{
if (Validate())
return _Func->GetVehicleModel(m_ID);
return -1;
// Validate the managed identifier
Validate();
// Return the requested information
return _Func->GetVehicleModel(m_ID);
}
// ------------------------------------------------------------------------------------------------
void CPickup::SetAlpha(Int32 alpha) const
{
if (Validate())
_Func->PickupSetAlpha(m_ID, alpha);
// Validate the managed identifier
Validate();
// Perform the requested operation
_Func->PickupSetAlpha(m_ID, alpha);
}
// ------------------------------------------------------------------------------------------------
bool CPickup::GetAutomatic() const
{
if (Validate())
return _Func->PickupIsAutomatic(m_ID);
return false;
// Validate the managed identifier
Validate();
// Return the requested information
return _Func->PickupIsAutomatic(m_ID);
}
// ------------------------------------------------------------------------------------------------
void CPickup::SetAutomatic(bool toggle) const
{
if (Validate())
_Func->PickupSetAutomatic(m_ID, toggle);
// Validate the managed identifier
Validate();
// Perform the requested operation
_Func->PickupSetAutomatic(m_ID, toggle);
}
// ------------------------------------------------------------------------------------------------
Int32 CPickup::GetAutoTimer() const
{
if (Validate())
return _Func->GetPickupAutoTimer(m_ID);
return -1;
// Validate the managed identifier
Validate();
// Return the requested information
return _Func->GetPickupAutoTimer(m_ID);
}
// ------------------------------------------------------------------------------------------------
void CPickup::SetAutoTimer(Int32 timer) const
{
if (Validate())
_Func->SetPickupAutoTimer(m_ID, timer);
// Validate the managed identifier
Validate();
// Perform the requested operation
_Func->SetPickupAutoTimer(m_ID, timer);
}
// ------------------------------------------------------------------------------------------------
void CPickup::Refresh() const
{
if (Validate())
_Func->PickupRefresh(m_ID);
// Validate the managed identifier
Validate();
// Perform the requested operation
_Func->PickupRefresh(m_ID);
}
// ------------------------------------------------------------------------------------------------
const Vector3 & CPickup::GetPosition()
{
// Validate the managed identifier
Validate();
// Clear previous position information, if any
s_Vector3.Clear();
if (Validate())
_Func->PickupGetPos(m_ID, &s_Vector3.x, &s_Vector3.y, &s_Vector3.z);
// Query the server for the position values
_Func->PickupGetPos(m_ID, &s_Vector3.x, &s_Vector3.y, &s_Vector3.z);
// Return the requested information
return s_Vector3;
}
// ------------------------------------------------------------------------------------------------
void CPickup::SetPosition(const Vector3 & pos) const
{
if (Validate())
_Func->PickupSetPos(m_ID, pos.x, pos.y, pos.z);
// Validate the managed identifier
Validate();
// Perform the requested operation
_Func->PickupSetPos(m_ID, pos.x, pos.y, pos.z);
}
// ------------------------------------------------------------------------------------------------
void CPickup::SetPositionEx(Float32 x, Float32 y, Float32 z) const
{
if (Validate())
_Func->PickupSetPos(m_ID, x, y, z);
// Validate the managed identifier
Validate();
// Perform the requested operation
_Func->PickupSetPos(m_ID, x, y, z);
}
// ------------------------------------------------------------------------------------------------
Int32 CPickup::GetQuantity() const
{
if (Validate())
return _Func->PickupGetQuantity(m_ID);
return -1;
// Validate the managed identifier
Validate();
// Return the requested information
return _Func->PickupGetQuantity(m_ID);
}
// ------------------------------------------------------------------------------------------------
Float32 CPickup::GetPosX() const
{
// Validate the managed identifier
Validate();
// Clear previous position information, if any
s_Vector3.x = 0;
if (Validate())
_Func->PickupGetPos(m_ID, &s_Vector3.x, NULL, NULL);
// Query the server for the requested component value
_Func->PickupGetPos(m_ID, &s_Vector3.x, NULL, NULL);
// Return the requested information
return s_Vector3.x;
}
// ------------------------------------------------------------------------------------------------
Float32 CPickup::GetPosY() const
{
// Validate the managed identifier
Validate();
// Clear previous position information, if any
s_Vector3.y = 0;
if (Validate())
_Func->PickupGetPos(m_ID, NULL, &s_Vector3.y, NULL);
// Query the server for the requested component value
_Func->PickupGetPos(m_ID, NULL, &s_Vector3.y, NULL);
// Return the requested information
return s_Vector3.y;
}
// ------------------------------------------------------------------------------------------------
Float32 CPickup::GetPosZ() const
{
// Validate the managed identifier
Validate();
// Clear previous position information, if any
s_Vector3.z = 0;
if (Validate())
_Func->PickupGetPos(m_ID, NULL, NULL, &s_Vector3.z);
// Query the server for the requested component value
_Func->PickupGetPos(m_ID, NULL, NULL, &s_Vector3.z);
// Return the requested information
return s_Vector3.z;
}
// ------------------------------------------------------------------------------------------------
void CPickup::SetPosX(Float32 x) const
{
if (Validate())
{
_Func->PickupGetPos(m_ID, NULL, &s_Vector3.y, &s_Vector3.z);
_Func->PickupSetPos(m_ID, x, s_Vector3.y, s_Vector3.z);
}
}
void CPickup::SetPosY(Float32 y) const
{
if (Validate())
{
_Func->PickupGetPos(m_ID, &s_Vector3.x, NULL, &s_Vector3.z);
_Func->PickupSetPos(m_ID, s_Vector3.x, y, s_Vector3.z);
}
}
void CPickup::SetPosZ(Float32 z) const
{
if (Validate())
{
_Func->PickupGetPos(m_ID, &s_Vector3.x, &s_Vector3.y, NULL);
_Func->PickupSetPos(m_ID, s_Vector3.z, s_Vector3.y, z);
}
// Validate the managed identifier
Validate();
// Retrieve the current values for unchanged components
_Func->PickupGetPos(m_ID, NULL, &s_Vector3.y, &s_Vector3.z);
// Perform the requested operation
_Func->PickupSetPos(m_ID, x, s_Vector3.y, s_Vector3.z);
}
// ------------------------------------------------------------------------------------------------
static Object & CreatePickupEx(Int32 model, Int32 world, Int32 quantity,
void CPickup::SetPosY(Float32 y) const
{
// Validate the managed identifier
Validate();
// Retrieve the current values for unchanged components
_Func->PickupGetPos(m_ID, &s_Vector3.x, NULL, &s_Vector3.z);
// Perform the requested operation
_Func->PickupSetPos(m_ID, s_Vector3.x, y, s_Vector3.z);
}
// ------------------------------------------------------------------------------------------------
void CPickup::SetPosZ(Float32 z) const
{
// Validate the managed identifier
Validate();
// Retrieve the current values for unchanged components
_Func->PickupGetPos(m_ID, &s_Vector3.x, &s_Vector3.y, NULL);
// Perform the requested operation
_Func->PickupSetPos(m_ID, s_Vector3.z, s_Vector3.y, z);
}
// ------------------------------------------------------------------------------------------------
static Object & Pickup_CreateEx(Int32 model, Int32 world, Int32 quantity,
Float32 x, Float32 y, Float32 z, Int32 alpha, bool automatic)
{
return _Core->NewPickup(model, world, quantity, x, y, z, alpha, automatic,
SQMOD_CREATE_DEFAULT, NullObject());
}
static Object & CreatePickupEx(Int32 model, Int32 world, Int32 quantity,
static Object & Pickup_CreateEx(Int32 model, Int32 world, Int32 quantity,
Float32 x, Float32 y, Float32 z, Int32 alpha, bool automatic,
Int32 header, Object & payload)
{
@ -263,14 +336,14 @@ static Object & CreatePickupEx(Int32 model, Int32 world, Int32 quantity,
}
// ------------------------------------------------------------------------------------------------
static Object & CreatePickup(Int32 model, Int32 world, Int32 quantity, const Vector3 & pos,
static Object & Pickup_Create(Int32 model, Int32 world, Int32 quantity, const Vector3 & pos,
Int32 alpha, bool automatic)
{
return _Core->NewPickup(model, world, quantity, pos.x, pos.y, pos.z, alpha, automatic,
SQMOD_CREATE_DEFAULT, NullObject());
}
static Object & CreatePickup(Int32 model, Int32 world, Int32 quantity, const Vector3 & pos,
static Object & Pickup_Create(Int32 model, Int32 world, Int32 quantity, const Vector3 & pos,
Int32 alpha, bool automatic, Int32 header, Object & payload)
{
return _Core->NewPickup(model, world, quantity, pos.x, pos.y, pos.z, alpha, automatic,
@ -282,22 +355,24 @@ void Register_CPickup(HSQUIRRELVM vm)
{
RootTable(vm).Bind(_SC("SqPickup"),
Class< CPickup, NoConstructor< CPickup > >(vm, _SC("SqPickup"))
/* Metamethods */
// Metamethods
.Func(_SC("_cmp"), &CPickup::Cmp)
.SquirrelFunc(_SC("_typename"), &CPickup::Typename)
.Func(_SC("_tostring"), &CPickup::ToString)
/* Core Properties */
// Static values
.SetStaticValue(_SC("MaxID"), CPickup::Max)
// Core Properties
.Prop(_SC("ID"), &CPickup::GetID)
.Prop(_SC("Tag"), &CPickup::GetTag, &CPickup::SetTag)
.Prop(_SC("Data"), &CPickup::GetData, &CPickup::SetData)
.Prop(_SC("MaxID"), &CPickup::GetMaxID)
.Prop(_SC("Active"), &CPickup::IsActive)
/* Core Functions */
// Core Functions
.Func(_SC("Bind"), &CPickup::BindEvent)
/* Core Overloads */
// Core Overloads
.Overload< bool (CPickup::*)(void) >(_SC("Destroy"), &CPickup::Destroy)
.Overload< bool (CPickup::*)(Int32) >(_SC("Destroy"), &CPickup::Destroy)
.Overload< bool (CPickup::*)(Int32, Object &) >(_SC("Destroy"), &CPickup::Destroy)
/* Properties */
// Properties
.Prop(_SC("Model"), &CPickup::GetModel)
.Prop(_SC("World"), &CPickup::GetWorld, &CPickup::SetWorld)
.Prop(_SC("Alpha"), &CPickup::GetAlpha, &CPickup::SetAlpha)
@ -311,22 +386,21 @@ void Register_CPickup(HSQUIRRELVM vm)
.Prop(_SC("X"), &CPickup::GetPosX, &CPickup::SetPosX)
.Prop(_SC("Y"), &CPickup::GetPosY, &CPickup::SetPosY)
.Prop(_SC("Z"), &CPickup::GetPosZ, &CPickup::SetPosZ)
/* Functions */
// Functions
.Func(_SC("StreamedFor"), &CPickup::IsStreamedFor)
.Func(_SC("Refresh"), &CPickup::Refresh)
.Func(_SC("SetPos"), &CPickup::SetPositionEx)
.Func(_SC("SetPosition"), &CPickup::SetPositionEx)
// Static Overloads
.StaticOverload< Object & (*)(Int32, Int32, Int32, Float32, Float32, Float32, Int32, bool) >
(_SC("CreateEx"), &Pickup_CreateEx)
.StaticOverload< Object & (*)(Int32, Int32, Int32, Float32, Float32, Float32, Int32, bool, Int32, Object &) >
(_SC("CreateEx"), &Pickup_CreateEx)
.StaticOverload< Object & (*)(Int32, Int32, Int32, const Vector3 &, Int32, bool) >
(_SC("Create"), &Pickup_Create)
.StaticOverload< Object & (*)(Int32, Int32, Int32, const Vector3 &, Int32, bool, Int32, Object &) >
(_SC("Create"), &Pickup_Create)
);
RootTable(vm)
.Overload< Object & (*)(Int32, Int32, Int32, Float32, Float32, Float32, Int32, bool) >
(_SC("CreatePickupEx"), &CreatePickupEx)
.Overload< Object & (*)(Int32, Int32, Int32, Float32, Float32, Float32, Int32, bool, Int32, Object &) >
(_SC("CreatePickupEx"), &CreatePickupEx)
.Overload< Object & (*)(Int32, Int32, Int32, const Vector3 &, Int32, bool) >
(_SC("CreatePickup"), &CreatePickup)
.Overload< Object & (*)(Int32, Int32, Int32, const Vector3 &, Int32, bool, Int32, Object &) >
(_SC("CreatePickup"), &CreatePickup);
}
} // Namespace:: SqMod

View File

@ -8,7 +8,7 @@
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Manages Pickup instances.
* Manages a single pickup entity.
*/
class CPickup
{
@ -20,20 +20,19 @@ private:
// --------------------------------------------------------------------------------------------
static Vector3 s_Vector3;
/* --------------------------------------------------------------------------------------------
* Cached identifiers for fast integer to string conversion.
*/
static SQChar s_StrID[SQMOD_PICKUP_POOL][8];
/* --------------------------------------------------------------------------------------------
* Identifier of the managed entity.
*/
Int32 m_ID;
/* --------------------------------------------------------------------------------------------
* User tag and data associated with this instance.
* User tag associated with this instance.
*/
String m_Tag;
/* --------------------------------------------------------------------------------------------
* User data associated with this instance.
*/
Object m_Data;
/* --------------------------------------------------------------------------------------------
@ -41,20 +40,22 @@ private:
*/
CPickup(Int32 id);
public:
/* --------------------------------------------------------------------------------------------
* Maximum possible number that could represent an identifier for this entity type.
*/
static const Int32 Max;
/* --------------------------------------------------------------------------------------------
* Copy constructor. (disabled)
*/
CPickup(const CPickup &);
CPickup(const CPickup &) = delete;
/* --------------------------------------------------------------------------------------------
* Copy assignment operator. (disabled)
* Move constructor. (disabled)
*/
CPickup & operator = (const CPickup &);
public:
// --------------------------------------------------------------------------------------------
static const Int32 Max;
CPickup(CPickup &&) = delete;
/* --------------------------------------------------------------------------------------------
* Destructor.
@ -62,14 +63,22 @@ public:
~CPickup();
/* --------------------------------------------------------------------------------------------
* See whether this instance manages a valid entity.
* Copy assignment operator. (disabled)
*/
bool Validate() const
CPickup & operator = (const CPickup &) = delete;
/* --------------------------------------------------------------------------------------------
* Move assignment operator. (disabled)
*/
CPickup & operator = (CPickup &&) = delete;
/* --------------------------------------------------------------------------------------------
* See whether this instance manages a valid entity instance otherwise throw an exception.
*/
void Validate() const
{
if (VALID_ENTITY(m_ID))
return true;
SqThrow("Invalid pickup reference [%s]", m_Tag.c_str());
return false;
if (INVALID_ENTITY(m_ID))
SqThrowF("Invalid pickup reference [%s]", m_Tag.c_str());
}
/* --------------------------------------------------------------------------------------------
@ -80,27 +89,33 @@ public:
/* --------------------------------------------------------------------------------------------
* Used by the script engine to convert an instance of this type to a string.
*/
CSStr ToString() const;
const String & ToString() const;
/* --------------------------------------------------------------------------------------------
* Used by the script engine to retrieve the name from instances of this type.
*/
static SQInteger Typename(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Retrieve the identifier of the entity managed by this instance.
*/
Int32 GetID() const { return m_ID; }
/* --------------------------------------------------------------------------------------------
* Retrieve the maximum possible identifier to an entity of this type.
*/
Int32 GetMaxID() const { return SQMOD_PICKUP_POOL; }
Int32 GetID() const
{
return m_ID;
}
/* --------------------------------------------------------------------------------------------
* Check whether this instance manages a valid entity.
*/
bool IsActive() const { return VALID_ENTITY(m_ID); }
bool IsActive() const
{
return VALID_ENTITY(m_ID);
}
/* --------------------------------------------------------------------------------------------
* Retrieve the associated user tag.
*/
CSStr GetTag() const;
const String & GetTag() const;
/* --------------------------------------------------------------------------------------------
* Modify the associated user tag.
@ -117,37 +132,135 @@ public:
*/
void SetData(Object & data);
// --------------------------------------------------------------------------------------------
/* --------------------------------------------------------------------------------------------
* Destroy the managed pickup entity.
*/
bool Destroy()
{
return Destroy(0, NullObject());
}
/* --------------------------------------------------------------------------------------------
* Destroy the managed pickup entity.
*/
bool Destroy(Int32 header)
{
return Destroy(header, NullObject());
}
/* --------------------------------------------------------------------------------------------
* Destroy the managed pickup entity.
*/
bool Destroy(Int32 header, Object & payload);
bool Destroy() { return Destroy(0, NullObject()); }
bool Destroy(Int32 header) { return Destroy(header, NullObject()); }
// --------------------------------------------------------------------------------------------
bool BindEvent(Int32 evid, Object & env, Function & func) const;
/* --------------------------------------------------------------------------------------------
* Bind to an event supported by this entity type.
*/
void BindEvent(Int32 evid, Object & env, Function & func) const;
// --------------------------------------------------------------------------------------------
/* --------------------------------------------------------------------------------------------
* See if the managed pickup entity is streamed for the specified player.
*/
bool IsStreamedFor(CPlayer & player) const;
/* --------------------------------------------------------------------------------------------
* Retrieve the model of the managed pickup entity.
*/
Int32 GetModel() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the world in which the managed pickup entity exists.
*/
Int32 GetWorld() const;
/* --------------------------------------------------------------------------------------------
* Mpdify the world in which the managed pickup entity exists.
*/
void SetWorld(Int32 world) const;
/* --------------------------------------------------------------------------------------------
* Retrieve the alpha of the managed pickup entity.
*/
Int32 GetAlpha() const;
/* --------------------------------------------------------------------------------------------
* Mpdify the alpha of the managed pickup entity.
*/
void SetAlpha(Int32 alpha) const;
/* --------------------------------------------------------------------------------------------
* See whether the managed pickup entity is automatic.
*/
bool GetAutomatic() const;
/* --------------------------------------------------------------------------------------------
* Set whether the managed pickup entity is automatic.
*/
void SetAutomatic(bool toggle) const;
/* --------------------------------------------------------------------------------------------
* Retrieve the automatic timer of the managed pickup entity.
*/
Int32 GetAutoTimer() const;
/* --------------------------------------------------------------------------------------------
* Mpdify the automatic timer of the managed pickup entity.
*/
void SetAutoTimer(Int32 timer) const;
/* --------------------------------------------------------------------------------------------
* Refresh the managed pickup entity.
*/
void Refresh() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the position of the managed pickup entity.
*/
const Vector3 & GetPosition();
/* --------------------------------------------------------------------------------------------
* Mpdify the position of the managed pickup entity.
*/
void SetPosition(const Vector3 & pos) const;
/* --------------------------------------------------------------------------------------------
* Mpdify the position of the managed pickup entity.
*/
void SetPositionEx(Float32 x, Float32 y, Float32 z) const;
/* --------------------------------------------------------------------------------------------
* Retrieve the quantity of the managed pickup entity.
*/
Int32 GetQuantity() const;
// --------------------------------------------------------------------------------------------
/* --------------------------------------------------------------------------------------------
* Retrieve the position on the x axis of the managed pickup entity.
*/
Float32 GetPosX() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the position on the y axis of the managed pickup entity.
*/
Float32 GetPosY() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the position on the z axis of the managed pickup entity.
*/
Float32 GetPosZ() const;
/* --------------------------------------------------------------------------------------------
* Modify the position on the x axis of the managed pickup entity.
*/
void SetPosX(Float32 x) const;
/* --------------------------------------------------------------------------------------------
* Modify the position on the y axis of the managed pickup entity.
*/
void SetPosY(Float32 y) const;
/* --------------------------------------------------------------------------------------------
* Modify the position on the z axis of the managed pickup entity.
*/
void SetPosZ(Float32 z) const;
};

Some files were not shown because too many files have changed in this diff Show More