mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 20:03:02 +01:00
Int128 - new datatype (#220)
* Int128 support - work in progress * Work in progress * Int128 datatype appears to be mostly OK except sort & index * Fixed divide scaling, added sorting & network (xdr) support * Binding control, aggregate nodes, cleanup and documentation * Fixed VS2017 AppVeyor build * Next attempt to fix vs2017 build * Next attempt to fix vs2017 build * Next attempt to fix vs2017 build * Update MSVC build. * Set VS architecture correctly * Fixed a number of issues noticed by Mark
This commit is contained in:
parent
b265743642
commit
861d536fc2
@ -27,9 +27,11 @@ install:
|
||||
- cmd: for /r %%i in (*.bat) do unix2dos "%%i"
|
||||
- cmd: if "%PLATFORM%" == "x64" set FB_PROCESSOR_ARCHITECTURE=AMD64
|
||||
- cmd: if "%PLATFORM%" == "x64" set FB_OUTPUT_SUFFIX=x64
|
||||
- cmd: if "%PLATFORM%" == "x64" set FB_VS_ARCH=amd64
|
||||
- cmd: if "%PLATFORM%" == "x86" set FB_PROCESSOR_ARCHITECTURE=x86
|
||||
- cmd: if "%PLATFORM%" == "x86" set FB_OUTPUT_SUFFIX=win32
|
||||
- cmd: if "%APPVEYOR_BUILD_WORKER_IMAGE%" == "Visual Studio 2017" call "%ProgramFiles(x86)%\Microsoft Visual Studio\2017\Community\Common7\Tools\VsDevCmd.bat"
|
||||
- cmd: if "%PLATFORM%" == "x86" set FB_VS_ARCH=x86
|
||||
- cmd: if "%APPVEYOR_BUILD_WORKER_IMAGE%" == "Visual Studio 2017" call "%ProgramFiles(x86)%\Microsoft Visual Studio\2017\Community\Common7\Tools\VsDevCmd.bat" -arch=%FB_VS_ARCH%
|
||||
- cmd: cd builds\win32
|
||||
- cmd: run_all.bat JUSTBUILD
|
||||
- cmd: set ARTIFACTS_PATH=output_%FB_OUTPUT_SUFFIX%
|
||||
|
@ -41,6 +41,9 @@ if "%ERRLEV%"=="1" goto :END
|
||||
call :decNumber
|
||||
if "%ERRLEV%"=="1" goto :END
|
||||
|
||||
if "%FB_TARGET_PLATFORM%"=="x64" call :ttmath
|
||||
if "%ERRLEV%"=="1" goto :END
|
||||
|
||||
call :re2
|
||||
if "%ERRLEV%"=="1" goto :END
|
||||
|
||||
@ -162,6 +165,23 @@ if errorlevel 1 call :boot2 decNumber_%FB_OBJ_DIR%
|
||||
@call set_build_target.bat %*
|
||||
goto :EOF
|
||||
|
||||
::===================
|
||||
:: BUILD ttmath
|
||||
:ttmath
|
||||
@echo.
|
||||
@call set_build_target.bat %* RELEASE
|
||||
@echo Building ttmath (%FB_OBJ_DIR%)...
|
||||
@mkdir %FB_TEMP_DIR%\..\%FB_OBJ_DIR%\common 2>nul
|
||||
@ml64.exe /c /Fo %FB_TEMP_DIR%\..\%FB_OBJ_DIR%\common\ttmathuint_x86_64_msvc.obj %FB_ROOT_PATH%\extern\ttmath\ttmathuint_x86_64_msvc.asm
|
||||
if errorlevel 1 call :boot2 ttmath_%FB_OBJ_DIR%
|
||||
@call set_build_target.bat %* DEBUG
|
||||
@echo Building decNumber (%FB_OBJ_DIR%)...
|
||||
@mkdir %FB_TEMP_DIR%\..\%FB_OBJ_DIR%\common 2>nul
|
||||
@ml64.exe /c /Zi /Fo %FB_TEMP_DIR%\..\%FB_OBJ_DIR%\common\ttmathuint_x86_64_msvc.obj %FB_ROOT_PATH%\extern\ttmath\ttmathuint_x86_64_msvc.asm
|
||||
if errorlevel 1 call :boot2 ttmath_%FB_OBJ_DIR%
|
||||
@call set_build_target.bat %*
|
||||
goto :EOF
|
||||
|
||||
::===================
|
||||
:: BUILD re2
|
||||
:re2
|
||||
|
@ -72,6 +72,7 @@
|
||||
<ClCompile Include="..\..\..\src\common\DynamicStrings.cpp" />
|
||||
<ClCompile Include="..\..\..\src\common\enc.cpp" />
|
||||
<ClCompile Include="..\..\..\src\common\fb_exception.cpp" />
|
||||
<ClCompile Include="..\..\..\src\common\Int128.cpp" />
|
||||
<ClCompile Include="..\..\..\src\common\IntlParametersBlock.cpp" />
|
||||
<ClCompile Include="..\..\..\src\common\IntlUtil.cpp" />
|
||||
<ClCompile Include="..\..\..\src\common\isc.cpp" />
|
||||
@ -180,6 +181,7 @@
|
||||
<ClInclude Include="..\..\..\src\common\enc_proto.h" />
|
||||
<ClInclude Include="..\..\..\src\common\file_params.h" />
|
||||
<ClInclude Include="..\..\..\src\common\gdsassert.h" />
|
||||
<ClInclude Include="..\..\..\src\common\Int128.h" />
|
||||
<ClInclude Include="..\..\..\src\common\intlobj_new.h" />
|
||||
<ClInclude Include="..\..\..\src\common\IntlParametersBlock.h" />
|
||||
<ClInclude Include="..\..\..\src\common\IntlUtil.h" />
|
||||
@ -335,7 +337,7 @@
|
||||
<Culture>0x041d</Culture>
|
||||
</ResourceCompile>
|
||||
<Lib>
|
||||
<AdditionalDependencies>ws2_32.lib;../../../extern/libtommath/lib/$(PlatformName)\$(Configuration)\tommath.lib;../../../extern/libtomcrypt/lib/$(PlatformName)\$(Configuration)\tomcrypt.lib;../../../extern/decNumber/lib/$(PlatformName)\$(Configuration)\decnumber.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>ws2_32.lib;../../../extern/libtommath/lib/$(PlatformName)\$(Configuration)\tommath.lib;../../../extern/libtomcrypt/lib/$(PlatformName)\$(Configuration)\tomcrypt.lib;../../../extern/decNumber/lib/$(PlatformName)\$(Configuration)\decnumber.lib;$(TargetDir)\ttmathuint_x86_64_msvc.obj;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
@ -353,7 +355,7 @@
|
||||
<Culture>0x041d</Culture>
|
||||
</ResourceCompile>
|
||||
<Lib>
|
||||
<AdditionalDependencies>ws2_32.lib;../../../extern/libtommath/lib/$(PlatformName)\$(Configuration)\tommath.lib;../../../extern/libtomcrypt/lib/$(PlatformName)\$(Configuration)\tomcrypt.lib;../../../extern/decNumber/lib/$(PlatformName)\$(Configuration)\decnumber.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>ws2_32.lib;../../../extern/libtommath/lib/$(PlatformName)\$(Configuration)\tommath.lib;../../../extern/libtomcrypt/lib/$(PlatformName)\$(Configuration)\tomcrypt.lib;../../../extern/decNumber/lib/$(PlatformName)\$(Configuration)\decnumber.lib;$(TargetDir)\ttmathuint_x86_64_msvc.obj;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
|
@ -240,6 +240,9 @@
|
||||
<ClCompile Include="..\..\..\src\common\keywords.cpp">
|
||||
<Filter>common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\src\common\Int128.cpp">
|
||||
<Filter>common</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\src\common\xdr_proto.h">
|
||||
@ -581,5 +584,8 @@
|
||||
<ClInclude Include="..\..\..\src\common\keywords.h">
|
||||
<Filter>headers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\src\common\Int128.h">
|
||||
<Filter>headers</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -68,6 +68,7 @@
|
||||
<ClCompile Include="..\..\..\src\common\DynamicStrings.cpp" />
|
||||
<ClCompile Include="..\..\..\src\common\enc.cpp" />
|
||||
<ClCompile Include="..\..\..\src\common\fb_exception.cpp" />
|
||||
<ClCompile Include="..\..\..\src\common\Int128.cpp" />
|
||||
<ClCompile Include="..\..\..\src\common\IntlParametersBlock.cpp" />
|
||||
<ClCompile Include="..\..\..\src\common\IntlUtil.cpp" />
|
||||
<ClCompile Include="..\..\..\src\common\isc.cpp" />
|
||||
@ -176,6 +177,7 @@
|
||||
<ClInclude Include="..\..\..\src\common\enc_proto.h" />
|
||||
<ClInclude Include="..\..\..\src\common\file_params.h" />
|
||||
<ClInclude Include="..\..\..\src\common\gdsassert.h" />
|
||||
<ClInclude Include="..\..\..\src\common\Int128.h" />
|
||||
<ClInclude Include="..\..\..\src\common\intlobj_new.h" />
|
||||
<ClInclude Include="..\..\..\src\common\IntlParametersBlock.h" />
|
||||
<ClInclude Include="..\..\..\src\common\IntlUtil.h" />
|
||||
@ -335,7 +337,7 @@
|
||||
<Culture>0x041d</Culture>
|
||||
</ResourceCompile>
|
||||
<Lib>
|
||||
<AdditionalDependencies>ws2_32.lib;../../../extern/libtommath/lib/$(PlatformName)\$(Configuration)\tommath.lib;../../../extern/libtomcrypt/lib/$(PlatformName)\$(Configuration)\tomcrypt.lib;../../../extern/decNumber/lib/$(PlatformName)\$(Configuration)\decnumber.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>ws2_32.lib;../../../extern/libtommath/lib/$(PlatformName)\$(Configuration)\tommath.lib;../../../extern/libtomcrypt/lib/$(PlatformName)\$(Configuration)\tomcrypt.lib;../../../extern/decNumber/lib/$(PlatformName)\$(Configuration)\decnumber.lib;$(TargetDir)\ttmathuint_x86_64_msvc.obj;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
@ -353,7 +355,7 @@
|
||||
<Culture>0x041d</Culture>
|
||||
</ResourceCompile>
|
||||
<Lib>
|
||||
<AdditionalDependencies>ws2_32.lib;../../../extern/libtommath/lib/$(PlatformName)\$(Configuration)\tommath.lib;../../../extern/libtomcrypt/lib/$(PlatformName)\$(Configuration)\tomcrypt.lib;../../../extern/decNumber/lib/$(PlatformName)\$(Configuration)\decnumber.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>ws2_32.lib;../../../extern/libtommath/lib/$(PlatformName)\$(Configuration)\tommath.lib;../../../extern/libtomcrypt/lib/$(PlatformName)\$(Configuration)\tomcrypt.lib;../../../extern/decNumber/lib/$(PlatformName)\$(Configuration)\decnumber.lib;$(TargetDir)\ttmathuint_x86_64_msvc.obj;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
|
@ -240,6 +240,9 @@
|
||||
<ClCompile Include="..\..\..\src\common\keywords.cpp">
|
||||
<Filter>common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\src\common\Int128.cpp">
|
||||
<Filter>common</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\src\common\xdr_proto.h">
|
||||
@ -581,5 +584,8 @@
|
||||
<ClInclude Include="..\..\..\src\common\classes\ParsedList.h">
|
||||
<Filter>headers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\src\common\Int128.h">
|
||||
<Filter>headers</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -68,6 +68,7 @@
|
||||
<ClCompile Include="..\..\..\src\common\DynamicStrings.cpp" />
|
||||
<ClCompile Include="..\..\..\src\common\enc.cpp" />
|
||||
<ClCompile Include="..\..\..\src\common\fb_exception.cpp" />
|
||||
<ClCompile Include="..\..\..\src\common\Int128.cpp" />
|
||||
<ClCompile Include="..\..\..\src\common\IntlParametersBlock.cpp" />
|
||||
<ClCompile Include="..\..\..\src\common\IntlUtil.cpp" />
|
||||
<ClCompile Include="..\..\..\src\common\isc.cpp" />
|
||||
@ -177,6 +178,7 @@
|
||||
<ClInclude Include="..\..\..\src\common\enc_proto.h" />
|
||||
<ClInclude Include="..\..\..\src\common\file_params.h" />
|
||||
<ClInclude Include="..\..\..\src\common\gdsassert.h" />
|
||||
<ClInclude Include="..\..\..\src\common\Int128.h" />
|
||||
<ClInclude Include="..\..\..\src\common\intlobj_new.h" />
|
||||
<ClInclude Include="..\..\..\src\common\IntlParametersBlock.h" />
|
||||
<ClInclude Include="..\..\..\src\common\IntlUtil.h" />
|
||||
@ -337,7 +339,7 @@
|
||||
<Culture>0x041d</Culture>
|
||||
</ResourceCompile>
|
||||
<Lib>
|
||||
<AdditionalDependencies>ws2_32.lib;../../../extern/libtommath/lib/$(PlatformName)\$(Configuration)\tommath.lib;../../../extern/libtomcrypt/lib/$(PlatformName)\$(Configuration)\tomcrypt.lib;../../../extern/decNumber/lib/$(PlatformName)\$(Configuration)\decnumber.lib;../../../extern/re2/builds/$(PlatformName)\$(Configuration)\re2.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>ws2_32.lib;../../../extern/libtommath/lib/$(PlatformName)\$(Configuration)\tommath.lib;../../../extern/libtomcrypt/lib/$(PlatformName)\$(Configuration)\tomcrypt.lib;../../../extern/decNumber/lib/$(PlatformName)\$(Configuration)\decnumber.lib;../../../extern/re2/builds/$(PlatformName)\$(Configuration)\re2.lib;$(TargetDir)\ttmathuint_x86_64_msvc.obj;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
@ -355,7 +357,7 @@
|
||||
<Culture>0x041d</Culture>
|
||||
</ResourceCompile>
|
||||
<Lib>
|
||||
<AdditionalDependencies>ws2_32.lib;../../../extern/libtommath/lib/$(PlatformName)\$(Configuration)\tommath.lib;../../../extern/libtomcrypt/lib/$(PlatformName)\$(Configuration)\tomcrypt.lib;../../../extern/decNumber/lib/$(PlatformName)\$(Configuration)\decnumber.lib;../../../extern/re2/builds/$(PlatformName)\$(Configuration)\re2.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>ws2_32.lib;../../../extern/libtommath/lib/$(PlatformName)\$(Configuration)\tommath.lib;../../../extern/libtomcrypt/lib/$(PlatformName)\$(Configuration)\tomcrypt.lib;../../../extern/decNumber/lib/$(PlatformName)\$(Configuration)\decnumber.lib;../../../extern/re2/builds/$(PlatformName)\$(Configuration)\re2.lib;$(TargetDir)\ttmathuint_x86_64_msvc.obj;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
|
@ -243,6 +243,9 @@
|
||||
<ClCompile Include="..\..\..\src\common\keywords.cpp">
|
||||
<Filter>common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\src\common\Int128.cpp">
|
||||
<Filter>common</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\src\common\xdr_proto.h">
|
||||
@ -587,5 +590,8 @@
|
||||
<ClInclude Include="..\..\..\src\common\keywords.h">
|
||||
<Filter>headers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\src\common\Int128.h">
|
||||
<Filter>headers</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
@ -68,6 +68,7 @@
|
||||
<ClCompile Include="..\..\..\src\common\DynamicStrings.cpp" />
|
||||
<ClCompile Include="..\..\..\src\common\enc.cpp" />
|
||||
<ClCompile Include="..\..\..\src\common\fb_exception.cpp" />
|
||||
<ClCompile Include="..\..\..\src\common\Int128.cpp" />
|
||||
<ClCompile Include="..\..\..\src\common\IntlParametersBlock.cpp" />
|
||||
<ClCompile Include="..\..\..\src\common\IntlUtil.cpp" />
|
||||
<ClCompile Include="..\..\..\src\common\isc.cpp" />
|
||||
@ -177,6 +178,7 @@
|
||||
<ClInclude Include="..\..\..\src\common\enc_proto.h" />
|
||||
<ClInclude Include="..\..\..\src\common\file_params.h" />
|
||||
<ClInclude Include="..\..\..\src\common\gdsassert.h" />
|
||||
<ClInclude Include="..\..\..\src\common\Int128.h" />
|
||||
<ClInclude Include="..\..\..\src\common\intlobj_new.h" />
|
||||
<ClInclude Include="..\..\..\src\common\IntlParametersBlock.h" />
|
||||
<ClInclude Include="..\..\..\src\common\IntlUtil.h" />
|
||||
@ -338,7 +340,7 @@
|
||||
<Culture>0x041d</Culture>
|
||||
</ResourceCompile>
|
||||
<Lib>
|
||||
<AdditionalDependencies>ws2_32.lib;../../../extern/libtommath/lib/$(PlatformName)\$(Configuration)\tommath.lib;../../../extern/libtomcrypt/lib/$(PlatformName)\$(Configuration)\tomcrypt.lib;../../../extern/decNumber/lib/$(PlatformName)\$(Configuration)\decnumber.lib;../../../extern/re2/builds/$(PlatformName)\$(Configuration)\re2.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>ws2_32.lib;../../../extern/libtommath/lib/$(PlatformName)\$(Configuration)\tommath.lib;../../../extern/libtomcrypt/lib/$(PlatformName)\$(Configuration)\tomcrypt.lib;../../../extern/decNumber/lib/$(PlatformName)\$(Configuration)\decnumber.lib;$(TargetDir)\ttmathuint_x86_64_msvc.obj;../../../extern/re2/builds/$(PlatformName)\$(Configuration)\re2.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
@ -356,7 +358,7 @@
|
||||
<Culture>0x041d</Culture>
|
||||
</ResourceCompile>
|
||||
<Lib>
|
||||
<AdditionalDependencies>ws2_32.lib;../../../extern/libtommath/lib/$(PlatformName)\$(Configuration)\tommath.lib;../../../extern/libtomcrypt/lib/$(PlatformName)\$(Configuration)\tomcrypt.lib;../../../extern/decNumber/lib/$(PlatformName)\$(Configuration)\decnumber.lib;../../../extern/re2/builds/$(PlatformName)\$(Configuration)\re2.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>ws2_32.lib;../../../extern/libtommath/lib/$(PlatformName)\$(Configuration)\tommath.lib;../../../extern/libtomcrypt/lib/$(PlatformName)\$(Configuration)\tomcrypt.lib;../../../extern/decNumber/lib/$(PlatformName)\$(Configuration)\decnumber.lib;../../../extern/re2/builds/$(PlatformName)\$(Configuration)\re2.lib;$(TargetDir)\ttmathuint_x86_64_msvc.obj;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
|
@ -243,6 +243,9 @@
|
||||
<ClCompile Include="..\..\..\src\common\keywords.cpp">
|
||||
<Filter>common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\src\common\Int128.cpp">
|
||||
<Filter>common</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\src\common\xdr_proto.h">
|
||||
@ -587,5 +590,8 @@
|
||||
<ClInclude Include="..\..\..\src\common\keywords.h">
|
||||
<Filter>headers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\src\common\Int128.h">
|
||||
<Filter>headers</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -200,7 +200,7 @@ Enhancement in precision of calculations with NUMERIC/DECIMAL (FB 4.0)
|
||||
--------------
|
||||
|
||||
Function:
|
||||
Maximum precision of NUMERIC and DECIMAL data types is increased to 34 digits.
|
||||
Maximum precision of NUMERIC and DECIMAL data types is increased to 38 digits.
|
||||
|
||||
Author:
|
||||
Alex Peshkoff <peshkoff@mail.ru>
|
||||
@ -208,20 +208,35 @@ Enhancement in precision of calculations with NUMERIC/DECIMAL (FB 4.0)
|
||||
Syntax rules:
|
||||
NUMERIC ( P {, N} )
|
||||
DECIMAL ( P {, N} )
|
||||
where P is precision (P <= 34, was limited prior with 18 digits) and N is optional number
|
||||
where P is precision (P <= 38, was limited prior with 18 digits) and N is optional number
|
||||
of digits after decimal separator (as before).
|
||||
|
||||
Storage:
|
||||
128-bit, format according to IEEE 754.
|
||||
128-bit signed integer.
|
||||
|
||||
Example(s):
|
||||
1. DECLARE VARIABLE VAR1 DECIMAL(25);
|
||||
2. CREATE TABLE TABLE1 (FIELD1 NUMERIC(34, 17));
|
||||
2. CREATE TABLE TABLE1 (FIELD1 NUMERIC(38, 19));
|
||||
|
||||
Note(s):
|
||||
Numerics with precision less than 19 digits use SMALLINT, INTEGER, BIGINT or DOUBLE PRECISION
|
||||
as base datatype depending upon number of digits and dialect. When precision is between 19 and
|
||||
34 digits DECFLOAT(34) is used for it. Actual precision is always increased to 34 digits. For
|
||||
complex calculations such digits are casted (internally, in trivial way) to DECFLOAT(34) and
|
||||
the result of various math (log, exp, etc.) and aggregate functions using high precision
|
||||
numeric argument is DECFLOAT(34).
|
||||
38 digits 128-bit integer is used for it. Actual precision is always increased to 38 digits.
|
||||
For complex calculations such digits are casted (internally) to DECFLOAT(34) and the result of
|
||||
various math (log, exp, etc.) and aggregate functions using high precision numeric argument is
|
||||
DECFLOAT(34).
|
||||
|
||||
SET INT128 BIND <bind-type> - controls how are INT128 values represented in outer
|
||||
world (i.e. in messages or in XSQLDA). Valid binding types are: NATIVE (use 128-bit
|
||||
binary representation), CHAR/CHARACTER (use ASCII string), DOUBLE PRECISION (use
|
||||
8-byte FP representation - same as used for DOUBLE PRECISION fields) or BIGINT
|
||||
with possible comma-separated SCALE clause (i.e. 'BIGINT, 3'). Various bindings
|
||||
are useful if one plans to use 128-bit integers with some old client not supporting
|
||||
native format. One can choose between strings (ideal precision, but poor support
|
||||
for further processing), floating point values (ideal support for further processing
|
||||
but poor precision) or scaled integers (good support for further processing and
|
||||
required precision but range of values is very limited). When using in a tool like
|
||||
generic purporse GUI client choice of CHAR binding is OK in most cases. By default
|
||||
NATIVE binding is used.
|
||||
The initial configuration may be specified with DPB isc_dpb_int128_bind followed
|
||||
by a string with its value (case does not matter).
|
||||
|
2843
extern/ttmath/ttmath.h
vendored
Normal file
2843
extern/ttmath/ttmath.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1917
extern/ttmath/ttmathint.h
vendored
Normal file
1917
extern/ttmath/ttmathint.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
250
extern/ttmath/ttmathmisc.h
vendored
Normal file
250
extern/ttmath/ttmathmisc.h
vendored
Normal file
@ -0,0 +1,250 @@
|
||||
/*
|
||||
* This file is a part of TTMath Bignum Library
|
||||
* and is distributed under the (new) BSD licence.
|
||||
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006-2010, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * 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.
|
||||
*
|
||||
* * Neither the name Tomasz Sowa nor the names of contributors to this
|
||||
* project may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
|
||||
*/
|
||||
|
||||
#ifndef headerfilettmathmisc
|
||||
#define headerfilettmathmisc
|
||||
|
||||
|
||||
/*!
|
||||
\file ttmathmisc.h
|
||||
\brief some helpful functions
|
||||
*/
|
||||
|
||||
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace ttmath
|
||||
{
|
||||
|
||||
/*!
|
||||
some helpful functions
|
||||
*/
|
||||
class Misc
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* AssignString(result, str)
|
||||
* result = str
|
||||
*
|
||||
*/
|
||||
|
||||
/*!
|
||||
result = str
|
||||
*/
|
||||
static void AssignString(std::string & result, const char * str)
|
||||
{
|
||||
result = str;
|
||||
}
|
||||
|
||||
|
||||
#ifndef TTMATH_DONT_USE_WCHAR
|
||||
|
||||
/*!
|
||||
result = str
|
||||
*/
|
||||
static void AssignString(std::wstring & result, const char * str)
|
||||
{
|
||||
result.clear();
|
||||
|
||||
for( ; *str ; ++str )
|
||||
result += *str;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
result = str
|
||||
*/
|
||||
static void AssignString(std::wstring & result, const std::string & str)
|
||||
{
|
||||
return AssignString(result, str.c_str());
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
result = str
|
||||
*/
|
||||
static void AssignString(std::string & result, const wchar_t * str)
|
||||
{
|
||||
result.clear();
|
||||
|
||||
for( ; *str ; ++str )
|
||||
result += static_cast<char>(*str);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
result = str
|
||||
*/
|
||||
static void AssignString(std::string & result, const std::wstring & str)
|
||||
{
|
||||
return AssignString(result, str.c_str());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* AddString(result, str)
|
||||
* result += str
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
result += str
|
||||
*/
|
||||
static void AddString(std::string & result, const char * str)
|
||||
{
|
||||
result += str;
|
||||
}
|
||||
|
||||
|
||||
#ifndef TTMATH_DONT_USE_WCHAR
|
||||
|
||||
/*!
|
||||
result += str
|
||||
*/
|
||||
static void AddString(std::wstring & result, const char * str)
|
||||
{
|
||||
for( ; *str ; ++str )
|
||||
result += *str;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
this method omits any white characters from the string
|
||||
char_type is char or wchar_t
|
||||
*/
|
||||
template<class char_type>
|
||||
static void SkipWhiteCharacters(const char_type * & c)
|
||||
{
|
||||
// 13 is at the end in a DOS text file (\r\n)
|
||||
while( (*c==' ' ) || (*c=='\t') || (*c==13 ) || (*c=='\n') )
|
||||
++c;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
this static method converts one character into its value
|
||||
|
||||
for example:
|
||||
1 -> 1
|
||||
8 -> 8
|
||||
A -> 10
|
||||
f -> 15
|
||||
|
||||
this method don't check whether c is correct or not
|
||||
*/
|
||||
static uint CharToDigit(uint c)
|
||||
{
|
||||
if(c>='0' && c<='9')
|
||||
return c-'0';
|
||||
|
||||
if(c>='a' && c<='z')
|
||||
return c-'a'+10;
|
||||
|
||||
return c-'A'+10;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this method changes a character 'c' into its value
|
||||
(if there can't be a correct value it returns -1)
|
||||
|
||||
for example:
|
||||
c=2, base=10 -> function returns 2
|
||||
c=A, base=10 -> function returns -1
|
||||
c=A, base=16 -> function returns 10
|
||||
*/
|
||||
static sint CharToDigit(uint c, uint base)
|
||||
{
|
||||
if( c>='0' && c<='9' )
|
||||
c=c-'0';
|
||||
else
|
||||
if( c>='a' && c<='z' )
|
||||
c=c-'a'+10;
|
||||
else
|
||||
if( c>='A' && c<='Z' )
|
||||
c=c-'A'+10;
|
||||
else
|
||||
return -1;
|
||||
|
||||
|
||||
if( c >= base )
|
||||
return -1;
|
||||
|
||||
|
||||
return sint(c);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
this method converts a digit into a char
|
||||
digit should be from <0,F>
|
||||
(we don't have to get a base)
|
||||
|
||||
for example:
|
||||
1 -> 1
|
||||
8 -> 8
|
||||
10 -> A
|
||||
15 -> F
|
||||
*/
|
||||
static uint DigitToChar(uint digit)
|
||||
{
|
||||
if( digit < 10 )
|
||||
return digit + '0';
|
||||
|
||||
return digit - 10 + 'A';
|
||||
}
|
||||
|
||||
|
||||
}; // struct Misc
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
809
extern/ttmath/ttmathobjects.h
vendored
Normal file
809
extern/ttmath/ttmathobjects.h
vendored
Normal file
@ -0,0 +1,809 @@
|
||||
/*
|
||||
* This file is a part of TTMath Mathematical Library
|
||||
* and is distributed under the (new) BSD licence.
|
||||
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006-2010, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * 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.
|
||||
*
|
||||
* * Neither the name Tomasz Sowa nor the names of contributors to this
|
||||
* project may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef headerfilettmathobject
|
||||
#define headerfilettmathobject
|
||||
|
||||
/*!
|
||||
\file ttmathobjects.h
|
||||
\brief Mathematic functions.
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
#include "ttmathtypes.h"
|
||||
#include "ttmathmisc.h"
|
||||
|
||||
|
||||
namespace ttmath
|
||||
{
|
||||
|
||||
/*!
|
||||
objects of this class are used with the mathematical parser
|
||||
they hold variables or functions defined by a user
|
||||
|
||||
each object has its own table in which we're keeping variables or functions
|
||||
*/
|
||||
class Objects
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
/*!
|
||||
one item (variable or function)
|
||||
'items' will be on the table
|
||||
*/
|
||||
struct Item
|
||||
{
|
||||
// name of a variable of a function
|
||||
// internally we store variables and funcions as std::string (not std::wstring even when wide characters are used)
|
||||
std::string value;
|
||||
|
||||
// number of parameters required by the function
|
||||
// (if there's a variable this 'param' is ignored)
|
||||
int param;
|
||||
|
||||
Item() {}
|
||||
Item(const std::string & v, int p) : value(v), param(p) {}
|
||||
};
|
||||
|
||||
// 'Table' is the type of our table
|
||||
typedef std::map<std::string, Item> Table;
|
||||
typedef Table::iterator Iterator;
|
||||
typedef Table::const_iterator CIterator;
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
this method returns true if a character 'c' is a character
|
||||
which can be in a name
|
||||
|
||||
if 'can_be_digit' is true that means when the 'c' is a digit this
|
||||
method returns true otherwise it returns false
|
||||
*/
|
||||
static bool CorrectCharacter(int c, bool can_be_digit)
|
||||
{
|
||||
if( (c>='a' && c<='z') || (c>='A' && c<='Z') )
|
||||
return true;
|
||||
|
||||
if( can_be_digit && ((c>='0' && c<='9') || c=='_') )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this method returns true if the name can be as a name of an object
|
||||
*/
|
||||
template<class string_type>
|
||||
static bool IsNameCorrect(const string_type & name)
|
||||
{
|
||||
if( name.empty() )
|
||||
return false;
|
||||
|
||||
if( !CorrectCharacter(name[0], false) )
|
||||
return false;
|
||||
|
||||
typename string_type::const_iterator i = name.begin();
|
||||
|
||||
for(++i ; i!=name.end() ; ++i)
|
||||
if( !CorrectCharacter(*i, true) )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this method returns true if such an object is defined (name exists)
|
||||
*/
|
||||
bool IsDefined(const std::string & name)
|
||||
{
|
||||
Iterator i = table.find(name);
|
||||
|
||||
if( i != table.end() )
|
||||
// we have this object in our table
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifndef TTMATH_DONT_USE_WCHAR
|
||||
|
||||
/*!
|
||||
this method returns true if such an object is defined (name exists)
|
||||
*/
|
||||
bool IsDefined(const std::wstring & name)
|
||||
{
|
||||
// we should check whether the name (in wide characters) are correct
|
||||
// before calling AssignString() function
|
||||
if( !IsNameCorrect(name) )
|
||||
return false;
|
||||
|
||||
Misc::AssignString(str_tmp1, name);
|
||||
|
||||
return IsDefined(str_tmp1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*!
|
||||
this method adds one object (variable of function) into the table
|
||||
*/
|
||||
ErrorCode Add(const std::string & name, const std::string & value, int param = 0)
|
||||
{
|
||||
if( !IsNameCorrect(name) )
|
||||
return err_incorrect_name;
|
||||
|
||||
Iterator i = table.find(name);
|
||||
|
||||
if( i != table.end() )
|
||||
// we have this object in our table
|
||||
return err_object_exists;
|
||||
|
||||
table.insert( std::make_pair(name, Item(value, param)) );
|
||||
|
||||
return err_ok;
|
||||
}
|
||||
|
||||
|
||||
#ifndef TTMATH_DONT_USE_WCHAR
|
||||
|
||||
/*!
|
||||
this method adds one object (variable of function) into the table
|
||||
*/
|
||||
ErrorCode Add(const std::wstring & name, const std::wstring & value, int param = 0)
|
||||
{
|
||||
// we should check whether the name (in wide characters) are correct
|
||||
// before calling AssignString() function
|
||||
if( !IsNameCorrect(name) )
|
||||
return err_incorrect_name;
|
||||
|
||||
Misc::AssignString(str_tmp1, name);
|
||||
Misc::AssignString(str_tmp2, value);
|
||||
|
||||
return Add(str_tmp1, str_tmp2, param);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*!
|
||||
this method returns 'true' if the table is empty
|
||||
*/
|
||||
bool Empty() const
|
||||
{
|
||||
return table.empty();
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this method clears the table
|
||||
*/
|
||||
void Clear()
|
||||
{
|
||||
return table.clear();
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this method returns 'const_iterator' on the first item on the table
|
||||
*/
|
||||
CIterator Begin() const
|
||||
{
|
||||
return table.begin();
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this method returns 'const_iterator' pointing at the space after last item
|
||||
(returns table.end())
|
||||
*/
|
||||
CIterator End() const
|
||||
{
|
||||
return table.end();
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this method changes the value and the number of parameters for a specific object
|
||||
*/
|
||||
ErrorCode EditValue(const std::string & name, const std::string & value, int param = 0)
|
||||
{
|
||||
if( !IsNameCorrect(name) )
|
||||
return err_incorrect_name;
|
||||
|
||||
Iterator i = table.find(name);
|
||||
|
||||
if( i == table.end() )
|
||||
return err_unknown_object;
|
||||
|
||||
i->second.value = value;
|
||||
i->second.param = param;
|
||||
|
||||
return err_ok;
|
||||
}
|
||||
|
||||
|
||||
#ifndef TTMATH_DONT_USE_WCHAR
|
||||
|
||||
|
||||
/*!
|
||||
this method changes the value and the number of parameters for a specific object
|
||||
*/
|
||||
ErrorCode EditValue(const std::wstring & name, const std::wstring & value, int param = 0)
|
||||
{
|
||||
// we should check whether the name (in wide characters) are correct
|
||||
// before calling AssignString() function
|
||||
if( !IsNameCorrect(name) )
|
||||
return err_incorrect_name;
|
||||
|
||||
Misc::AssignString(str_tmp1, name);
|
||||
Misc::AssignString(str_tmp2, value);
|
||||
|
||||
return EditValue(str_tmp1, str_tmp2, param);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*!
|
||||
this method changes the name of a specific object
|
||||
*/
|
||||
ErrorCode EditName(const std::string & old_name, const std::string & new_name)
|
||||
{
|
||||
if( !IsNameCorrect(old_name) || !IsNameCorrect(new_name) )
|
||||
return err_incorrect_name;
|
||||
|
||||
Iterator old_i = table.find(old_name);
|
||||
if( old_i == table.end() )
|
||||
return err_unknown_object;
|
||||
|
||||
if( old_name == new_name )
|
||||
// the new name is the same as the old one
|
||||
// we treat it as a normal situation
|
||||
return err_ok;
|
||||
|
||||
ErrorCode err = Add(new_name, old_i->second.value, old_i->second.param);
|
||||
|
||||
if( err == err_ok )
|
||||
{
|
||||
old_i = table.find(old_name);
|
||||
TTMATH_ASSERT( old_i != table.end() )
|
||||
|
||||
table.erase(old_i);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifndef TTMATH_DONT_USE_WCHAR
|
||||
|
||||
|
||||
/*!
|
||||
this method changes the name of a specific object
|
||||
*/
|
||||
ErrorCode EditName(const std::wstring & old_name, const std::wstring & new_name)
|
||||
{
|
||||
// we should check whether the name (in wide characters) are correct
|
||||
// before calling AssignString() function
|
||||
if( !IsNameCorrect(old_name) || !IsNameCorrect(new_name) )
|
||||
return err_incorrect_name;
|
||||
|
||||
Misc::AssignString(str_tmp1, old_name);
|
||||
Misc::AssignString(str_tmp2, new_name);
|
||||
|
||||
return EditName(str_tmp1, str_tmp2);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*!
|
||||
this method deletes an object
|
||||
*/
|
||||
ErrorCode Delete(const std::string & name)
|
||||
{
|
||||
if( !IsNameCorrect(name) )
|
||||
return err_incorrect_name;
|
||||
|
||||
Iterator i = table.find(name);
|
||||
|
||||
if( i == table.end() )
|
||||
return err_unknown_object;
|
||||
|
||||
table.erase( i );
|
||||
|
||||
return err_ok;
|
||||
}
|
||||
|
||||
|
||||
#ifndef TTMATH_DONT_USE_WCHAR
|
||||
|
||||
|
||||
/*!
|
||||
this method deletes an object
|
||||
*/
|
||||
ErrorCode Delete(const std::wstring & name)
|
||||
{
|
||||
// we should check whether the name (in wide characters) are correct
|
||||
// before calling AssignString() function
|
||||
if( !IsNameCorrect(name) )
|
||||
return err_incorrect_name;
|
||||
|
||||
Misc::AssignString(str_tmp1, name);
|
||||
|
||||
return Delete(str_tmp1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*!
|
||||
this method gets the value of a specific object
|
||||
*/
|
||||
ErrorCode GetValue(const std::string & name, std::string & value) const
|
||||
{
|
||||
if( !IsNameCorrect(name) )
|
||||
return err_incorrect_name;
|
||||
|
||||
CIterator i = table.find(name);
|
||||
|
||||
if( i == table.end() )
|
||||
{
|
||||
value.clear();
|
||||
return err_unknown_object;
|
||||
}
|
||||
|
||||
value = i->second.value;
|
||||
|
||||
return err_ok;
|
||||
}
|
||||
|
||||
|
||||
#ifndef TTMATH_DONT_USE_WCHAR
|
||||
|
||||
/*!
|
||||
this method gets the value of a specific object
|
||||
*/
|
||||
ErrorCode GetValue(const std::wstring & name, std::wstring & value)
|
||||
{
|
||||
// we should check whether the name (in wide characters) are correct
|
||||
// before calling AssignString() function
|
||||
if( !IsNameCorrect(name) )
|
||||
return err_incorrect_name;
|
||||
|
||||
Misc::AssignString(str_tmp1, name);
|
||||
ErrorCode err = GetValue(str_tmp1, str_tmp2);
|
||||
Misc::AssignString(value, str_tmp2);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*!
|
||||
this method gets the value of a specific object
|
||||
(this version is used for not copying the whole string)
|
||||
*/
|
||||
ErrorCode GetValue(const std::string & name, const char ** value) const
|
||||
{
|
||||
if( !IsNameCorrect(name) )
|
||||
return err_incorrect_name;
|
||||
|
||||
CIterator i = table.find(name);
|
||||
|
||||
if( i == table.end() )
|
||||
{
|
||||
*value = 0;
|
||||
return err_unknown_object;
|
||||
}
|
||||
|
||||
*value = i->second.value.c_str();
|
||||
|
||||
return err_ok;
|
||||
}
|
||||
|
||||
|
||||
#ifndef TTMATH_DONT_USE_WCHAR
|
||||
|
||||
/*!
|
||||
this method gets the value of a specific object
|
||||
(this version is used for not copying the whole string)
|
||||
*/
|
||||
ErrorCode GetValue(const std::wstring & name, const char ** value)
|
||||
{
|
||||
// we should check whether the name (in wide characters) are correct
|
||||
// before calling AssignString() function
|
||||
if( !IsNameCorrect(name) )
|
||||
return err_incorrect_name;
|
||||
|
||||
Misc::AssignString(str_tmp1, name);
|
||||
|
||||
return GetValue(str_tmp1, value);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*!
|
||||
this method gets the value and the number of parameters
|
||||
of a specific object
|
||||
*/
|
||||
ErrorCode GetValueAndParam(const std::string & name, std::string & value, int * param) const
|
||||
{
|
||||
if( !IsNameCorrect(name) )
|
||||
return err_incorrect_name;
|
||||
|
||||
CIterator i = table.find(name);
|
||||
|
||||
if( i == table.end() )
|
||||
{
|
||||
value.empty();
|
||||
*param = 0;
|
||||
return err_unknown_object;
|
||||
}
|
||||
|
||||
value = i->second.value;
|
||||
*param = i->second.param;
|
||||
|
||||
return err_ok;
|
||||
}
|
||||
|
||||
|
||||
#ifndef TTMATH_DONT_USE_WCHAR
|
||||
|
||||
/*!
|
||||
this method gets the value and the number of parameters
|
||||
of a specific object
|
||||
*/
|
||||
ErrorCode GetValueAndParam(const std::wstring & name, std::wstring & value, int * param)
|
||||
{
|
||||
// we should check whether the name (in wide characters) are correct
|
||||
// before calling AssignString() function
|
||||
if( !IsNameCorrect(name) )
|
||||
return err_incorrect_name;
|
||||
|
||||
Misc::AssignString(str_tmp1, name);
|
||||
ErrorCode err = GetValueAndParam(str_tmp1, str_tmp2, param);
|
||||
Misc::AssignString(value, str_tmp2);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*!
|
||||
this method sets the value and the number of parameters
|
||||
of a specific object
|
||||
(this version is used for not copying the whole string)
|
||||
*/
|
||||
ErrorCode GetValueAndParam(const std::string & name, const char ** value, int * param) const
|
||||
{
|
||||
if( !IsNameCorrect(name) )
|
||||
return err_incorrect_name;
|
||||
|
||||
CIterator i = table.find(name);
|
||||
|
||||
if( i == table.end() )
|
||||
{
|
||||
*value = 0;
|
||||
*param = 0;
|
||||
return err_unknown_object;
|
||||
}
|
||||
|
||||
*value = i->second.value.c_str();
|
||||
*param = i->second.param;
|
||||
|
||||
return err_ok;
|
||||
}
|
||||
|
||||
|
||||
#ifndef TTMATH_DONT_USE_WCHAR
|
||||
|
||||
|
||||
/*!
|
||||
this method sets the value and the number of parameters
|
||||
of a specific object
|
||||
(this version is used for not copying the whole string
|
||||
but in fact we make one copying during AssignString())
|
||||
*/
|
||||
ErrorCode GetValueAndParam(const std::wstring & name, const char ** value, int * param)
|
||||
{
|
||||
// we should check whether the name (in wide characters) are correct
|
||||
// before calling AssignString() function
|
||||
if( !IsNameCorrect(name) )
|
||||
return err_incorrect_name;
|
||||
|
||||
Misc::AssignString(str_tmp1, name);
|
||||
|
||||
return GetValueAndParam(str_tmp1, value, param);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*!
|
||||
this method returns a pointer into the table
|
||||
*/
|
||||
Table * GetTable()
|
||||
{
|
||||
return &table;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
Table table;
|
||||
std::string str_tmp1, str_tmp2;
|
||||
|
||||
}; // end of class Objects
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
objects of the class History are used to keep values in functions
|
||||
which take a lot of time during calculating, for instance in the
|
||||
function Factorial(x)
|
||||
|
||||
it means that when we're calculating e.g. Factorial(1000) and the
|
||||
Factorial finds that we have calculated it before, the value (result)
|
||||
is taken from the history
|
||||
*/
|
||||
template<class ValueType>
|
||||
class History
|
||||
{
|
||||
/*!
|
||||
one item in the History's object holds a key, a value for the key
|
||||
and a corresponding error code
|
||||
*/
|
||||
struct Item
|
||||
{
|
||||
ValueType key, value;
|
||||
ErrorCode err;
|
||||
};
|
||||
|
||||
|
||||
/*!
|
||||
we use std::list for simply deleting the first item
|
||||
but because we're searching through the whole container
|
||||
(in the method Get) the container should not be too big
|
||||
(linear time of searching)
|
||||
*/
|
||||
typedef std::list<Item> buffer_type;
|
||||
buffer_type buffer;
|
||||
typename buffer_type::size_type buffer_max_size;
|
||||
|
||||
public:
|
||||
|
||||
/*!
|
||||
default constructor
|
||||
default max size of the History's container is 15 items
|
||||
*/
|
||||
History()
|
||||
{
|
||||
buffer_max_size = 15;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
a constructor which takes another value of the max size
|
||||
of the History's container
|
||||
*/
|
||||
History(typename buffer_type::size_type new_size)
|
||||
{
|
||||
buffer_max_size = new_size;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this method adds one item into the History
|
||||
if the size of the container is greater than buffer_max_size
|
||||
the first item will be removed
|
||||
*/
|
||||
void Add(const ValueType & key, const ValueType & value, ErrorCode err)
|
||||
{
|
||||
Item item;
|
||||
item.key = key;
|
||||
item.value = value;
|
||||
item.err = err;
|
||||
|
||||
buffer.insert( buffer.end(), item );
|
||||
|
||||
if( buffer.size() > buffer_max_size )
|
||||
buffer.erase(buffer.begin());
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this method checks whether we have an item which has the key equal 'key'
|
||||
|
||||
if there's such item the method sets the 'value' and the 'err'
|
||||
and returns true otherwise it returns false and 'value' and 'err'
|
||||
remain unchanged
|
||||
*/
|
||||
bool Get(const ValueType & key, ValueType & value, ErrorCode & err)
|
||||
{
|
||||
typename buffer_type::iterator i = buffer.begin();
|
||||
|
||||
for( ; i != buffer.end() ; ++i )
|
||||
{
|
||||
if( i->key == key )
|
||||
{
|
||||
value = i->value;
|
||||
err = i->err;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this methods deletes an item
|
||||
|
||||
we assume that there is only one item with the 'key'
|
||||
(this methods removes the first one)
|
||||
*/
|
||||
bool Remove(const ValueType & key)
|
||||
{
|
||||
typename buffer_type::iterator i = buffer.begin();
|
||||
|
||||
for( ; i != buffer.end() ; ++i )
|
||||
{
|
||||
if( i->key == key )
|
||||
{
|
||||
buffer.erase(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}; // end of class History
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
this is an auxiliary class used when calculating Gamma() or Factorial()
|
||||
|
||||
in multithreaded environment you can provide an object of this class to
|
||||
the Gamma() or Factorial() function, e.g;
|
||||
typedef Big<1, 3> MyBig;
|
||||
MyBig x = 123456;
|
||||
CGamma<MyBig> cgamma;
|
||||
std::cout << Gamma(x, cgamma);
|
||||
each thread should have its own CGamma<> object
|
||||
|
||||
in a single-thread environment a CGamma<> object is a static variable
|
||||
in a second version of Gamma() and you don't have to explicitly use it, e.g.
|
||||
typedef Big<1, 3> MyBig;
|
||||
MyBig x = 123456;
|
||||
std::cout << Gamma(x);
|
||||
*/
|
||||
template<class ValueType>
|
||||
struct CGamma
|
||||
{
|
||||
/*!
|
||||
this table holds factorials
|
||||
1
|
||||
1
|
||||
2
|
||||
6
|
||||
24
|
||||
120
|
||||
720
|
||||
.......
|
||||
*/
|
||||
std::vector<ValueType> fact;
|
||||
|
||||
|
||||
/*!
|
||||
this table holds Bernoulli numbers
|
||||
1
|
||||
-0.5
|
||||
0.166666666666666666666666667
|
||||
0
|
||||
-0.0333333333333333333333333333
|
||||
0
|
||||
0.0238095238095238095238095238
|
||||
0
|
||||
-0.0333333333333333333333333333
|
||||
0
|
||||
0.075757575757575757575757576
|
||||
.....
|
||||
*/
|
||||
std::vector<ValueType> bern;
|
||||
|
||||
|
||||
/*!
|
||||
here we store some calculated values
|
||||
(this is for speeding up, if the next argument of Gamma() or Factorial()
|
||||
is in the 'history' then the result we are not calculating but simply
|
||||
return from the 'history' object)
|
||||
*/
|
||||
History<ValueType> history;
|
||||
|
||||
|
||||
/*!
|
||||
this method prepares some coefficients: factorials and Bernoulli numbers
|
||||
stored in 'fact' and 'bern' objects
|
||||
|
||||
how many values should be depends on the size of the mantissa - if
|
||||
the mantissa is larger then we must calculate more values
|
||||
for a mantissa which consists of 256 bits (8 words on a 32bit platform)
|
||||
we have to calculate about 30 values (the size of fact and bern will be 30),
|
||||
and for a 2048 bits mantissa we have to calculate 306 coefficients
|
||||
|
||||
you don't have to call this method, these coefficients will be automatically calculated
|
||||
when they are needed
|
||||
|
||||
you must note that calculating these coefficients is a little time-consuming operation,
|
||||
(especially when the mantissa is large) and first call to Gamma() or Factorial()
|
||||
can take more time than next calls, and in the end this is the point when InitAll()
|
||||
comes in handy: you can call this method somewhere at the beginning of your program
|
||||
*/
|
||||
void InitAll();
|
||||
// definition is in ttmath.h
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
250
extern/ttmath/ttmaththreads.h
vendored
Normal file
250
extern/ttmath/ttmaththreads.h
vendored
Normal file
@ -0,0 +1,250 @@
|
||||
/*
|
||||
* This file is a part of TTMath Bignum Library
|
||||
* and is distributed under the (new) BSD licence.
|
||||
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006-2009, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * 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.
|
||||
*
|
||||
* * Neither the name Tomasz Sowa nor the names of contributors to this
|
||||
* project may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef headerfilettmaththreads
|
||||
#define headerfilettmaththreads
|
||||
|
||||
#include "ttmathtypes.h"
|
||||
|
||||
#ifdef TTMATH_WIN32_THREADS
|
||||
#include <windows.h>
|
||||
#include <cstdio>
|
||||
#endif
|
||||
|
||||
#ifdef TTMATH_POSIX_THREADS
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
\file ttmaththreads.h
|
||||
\brief Some objects used in multithreads environment
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
this is a simple skeleton of a program in multithreads environment:
|
||||
|
||||
#define TTMATH_MULTITHREADS
|
||||
#include<ttmath/ttmath.h>
|
||||
|
||||
TTMATH_MULTITHREADS_HELPER
|
||||
|
||||
int main()
|
||||
{
|
||||
[...]
|
||||
}
|
||||
|
||||
make sure that macro TTMATH_MULTITHREADS is defined and (somewhere in *.cpp file)
|
||||
use TTMATH_MULTITHREADS_HELPER macro (outside of any classes/functions/namespaces scope)
|
||||
*/
|
||||
|
||||
|
||||
namespace ttmath
|
||||
{
|
||||
|
||||
|
||||
#ifdef TTMATH_WIN32_THREADS
|
||||
|
||||
/*
|
||||
we use win32 threads
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
in multithreads environment you should use TTMATH_MULTITHREADS_HELPER macro
|
||||
somewhere in *.cpp file
|
||||
|
||||
(at the moment in win32 this macro does nothing)
|
||||
*/
|
||||
#define TTMATH_MULTITHREADS_HELPER
|
||||
|
||||
|
||||
/*!
|
||||
objects of this class are used to synchronize
|
||||
*/
|
||||
class ThreadLock
|
||||
{
|
||||
HANDLE mutex_handle;
|
||||
|
||||
|
||||
void CreateName(char * buffer) const
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (disable : 4996)
|
||||
// warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead.
|
||||
#endif
|
||||
|
||||
sprintf(buffer, "TTMATH_LOCK_%ul", (unsigned long)GetCurrentProcessId());
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (default : 4996)
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
|
||||
bool Lock()
|
||||
{
|
||||
char buffer[50];
|
||||
|
||||
CreateName(buffer);
|
||||
mutex_handle = CreateMutexA(0, false, buffer);
|
||||
|
||||
if( mutex_handle == 0 )
|
||||
return false;
|
||||
|
||||
WaitForSingleObject(mutex_handle, INFINITE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
ThreadLock()
|
||||
{
|
||||
mutex_handle = 0;
|
||||
}
|
||||
|
||||
|
||||
~ThreadLock()
|
||||
{
|
||||
if( mutex_handle != 0 )
|
||||
{
|
||||
ReleaseMutex(mutex_handle);
|
||||
CloseHandle(mutex_handle);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif // #ifdef TTMATH_WIN32_THREADS
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef TTMATH_POSIX_THREADS
|
||||
|
||||
/*
|
||||
we use posix threads
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
in multithreads environment you should use TTMATH_MULTITHREADS_HELPER macro
|
||||
somewhere in *.cpp file
|
||||
(this macro defines a pthread_mutex_t object used by TTMath library)
|
||||
*/
|
||||
#define TTMATH_MULTITHREADS_HELPER \
|
||||
namespace ttmath \
|
||||
{ \
|
||||
pthread_mutex_t ttmath_mutex = PTHREAD_MUTEX_INITIALIZER; \
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
ttmath_mutex will be defined by TTMATH_MULTITHREADS_HELPER macro
|
||||
*/
|
||||
extern pthread_mutex_t ttmath_mutex;
|
||||
|
||||
|
||||
/*!
|
||||
objects of this class are used to synchronize
|
||||
*/
|
||||
class ThreadLock
|
||||
{
|
||||
public:
|
||||
|
||||
bool Lock()
|
||||
{
|
||||
if( pthread_mutex_lock(&ttmath_mutex) != 0 )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
~ThreadLock()
|
||||
{
|
||||
pthread_mutex_unlock(&ttmath_mutex);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // #ifdef TTMATH_POSIX_THREADS
|
||||
|
||||
|
||||
|
||||
|
||||
#if !defined(TTMATH_POSIX_THREADS) && !defined(TTMATH_WIN32_THREADS)
|
||||
|
||||
/*!
|
||||
we don't use win32 and pthreads
|
||||
*/
|
||||
|
||||
/*!
|
||||
*/
|
||||
#define TTMATH_MULTITHREADS_HELPER
|
||||
|
||||
|
||||
/*!
|
||||
objects of this class are used to synchronize
|
||||
actually we don't synchronize, the method Lock() returns always 'false'
|
||||
*/
|
||||
class ThreadLock
|
||||
{
|
||||
public:
|
||||
|
||||
bool Lock()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif // #if !defined(TTMATH_POSIX_THREADS) && !defined(TTMATH_WIN32_THREADS)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
|
676
extern/ttmath/ttmathtypes.h
vendored
Normal file
676
extern/ttmath/ttmathtypes.h
vendored
Normal file
@ -0,0 +1,676 @@
|
||||
/*
|
||||
* This file is a part of TTMath Bignum Library
|
||||
* and is distributed under the (new) BSD licence.
|
||||
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * 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.
|
||||
*
|
||||
* * Neither the name Tomasz Sowa nor the names of contributors to this
|
||||
* project may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef headerfilettmathtypes
|
||||
#define headerfilettmathtypes
|
||||
|
||||
/*!
|
||||
\file ttmathtypes.h
|
||||
\brief constants used in the library
|
||||
|
||||
As our library is written in header files (templates) we cannot use
|
||||
constants like 'const int' etc. because we should have some source files
|
||||
*.cpp to define this variables. Only what we can have are constants
|
||||
defined by #define preprocessor macros.
|
||||
|
||||
All macros are preceded by TTMATH_ prefix
|
||||
*/
|
||||
|
||||
|
||||
#include <stdexcept>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#include <stdint.h>
|
||||
// for uint64_t and int64_t on a 32 bit platform
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
the version of the library
|
||||
|
||||
TTMATH_PRERELEASE_VER is either zero or one
|
||||
zero means that this is the release version of the library
|
||||
(one means something like beta)
|
||||
*/
|
||||
#define TTMATH_MAJOR_VER 0
|
||||
#define TTMATH_MINOR_VER 9
|
||||
#define TTMATH_REVISION_VER 3
|
||||
|
||||
#define TTMATH_PRERELEASE_VER 0
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
you can define a platform explicitly by defining either
|
||||
TTMATH_PLATFORM32 or TTMATH_PLATFORM64 macro
|
||||
*/
|
||||
#if !defined TTMATH_PLATFORM32 && !defined TTMATH_PLATFORM64
|
||||
|
||||
#if !defined _M_X64 && !defined __x86_64__
|
||||
|
||||
/*
|
||||
other platforms than x86 and amd64 are not recognized at the moment
|
||||
so you should set TTMATH_PLATFORMxx manually
|
||||
*/
|
||||
|
||||
// we're using a 32bit platform
|
||||
#define TTMATH_PLATFORM32
|
||||
|
||||
#else
|
||||
|
||||
// we're using a 64bit platform
|
||||
#define TTMATH_PLATFORM64
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*!
|
||||
asm version of the library is available by default only for:
|
||||
x86 and amd64 platforms and for Microsoft Visual and GCC compilers
|
||||
|
||||
but you can force using asm version (the same asm as for Microsoft Visual)
|
||||
by defining TTMATH_FORCEASM macro
|
||||
you have to be sure that your compiler accept such an asm format
|
||||
*/
|
||||
#ifndef TTMATH_FORCEASM
|
||||
|
||||
#if !defined __i386__ && !defined _X86_ && !defined _M_IX86 && !defined __x86_64__ && !defined _M_X64
|
||||
/*!
|
||||
x86 architecture:
|
||||
__i386__ defined by GNU C
|
||||
_X86_ defined by MinGW32
|
||||
_M_IX86 defined by Visual Studio, Intel C/C++, Digital Mars and Watcom C/C++
|
||||
|
||||
amd64 architecture:
|
||||
__x86_64__ defined by GNU C, CLANG (LLVM) and Sun Studio
|
||||
_M_X64 defined by Visual Studio
|
||||
|
||||
asm version is available only for x86 or amd64 platforms
|
||||
*/
|
||||
#define TTMATH_NOASM
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if !defined _MSC_VER && !defined __GNUC__
|
||||
/*!
|
||||
another compilers than MS VC or GCC or CLANG (LLVM) by default use no asm version
|
||||
(CLANG defines __GNUC__ too)
|
||||
*/
|
||||
#define TTMATH_NOASM
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
namespace ttmath
|
||||
{
|
||||
|
||||
|
||||
#ifdef TTMATH_PLATFORM32
|
||||
|
||||
/*!
|
||||
on 32bit platforms one word (uint, sint) will be equal 32bits
|
||||
*/
|
||||
typedef unsigned int uint;
|
||||
typedef signed int sint;
|
||||
|
||||
/*!
|
||||
on 32 bit platform ulint and slint will be equal 64 bits
|
||||
*/
|
||||
#ifdef _MSC_VER
|
||||
// long long on MS Windows (Visual and GCC mingw compilers) have 64 bits
|
||||
// stdint.h is not available on Visual Studio prior to VS 2010 version
|
||||
typedef unsigned long long int ulint;
|
||||
typedef signed long long int slint;
|
||||
#else
|
||||
// we do not use 'long' here because there is a difference in unix and windows
|
||||
// environments: in unix 'long' has 64 bits but in windows it has only 32 bits
|
||||
typedef uint64_t ulint;
|
||||
typedef int64_t slint;
|
||||
#endif
|
||||
|
||||
/*!
|
||||
how many bits there are in the uint type
|
||||
*/
|
||||
#define TTMATH_BITS_PER_UINT 32u
|
||||
|
||||
/*!
|
||||
the mask for the highest bit in the unsigned 32bit word (2^31)
|
||||
*/
|
||||
#define TTMATH_UINT_HIGHEST_BIT 2147483648u
|
||||
|
||||
/*!
|
||||
the max value of the unsigned 32bit word (2^32 - 1)
|
||||
(all bits equal one)
|
||||
*/
|
||||
#define TTMATH_UINT_MAX_VALUE 4294967295u
|
||||
|
||||
/*!
|
||||
the number of words (32bit words on 32bit platform)
|
||||
which are kept in built-in variables for a Big<> type
|
||||
(these variables are defined in ttmathbig.h)
|
||||
*/
|
||||
#define TTMATH_BUILTIN_VARIABLES_SIZE 256u
|
||||
|
||||
/*!
|
||||
this macro returns the number of machine words
|
||||
capable to hold min_bits bits
|
||||
e.g. TTMATH_BITS(128) returns 4
|
||||
*/
|
||||
#define TTMATH_BITS(min_bits) ((min_bits-1)/32 + 1)
|
||||
|
||||
#else
|
||||
|
||||
/*!
|
||||
on 64bit platforms one word (uint, sint) will be equal 64bits
|
||||
*/
|
||||
#ifdef _MSC_VER
|
||||
/* in VC 'long' type has 32 bits, __int64 is VC extension */
|
||||
typedef unsigned __int64 uint;
|
||||
typedef signed __int64 sint;
|
||||
#else
|
||||
typedef unsigned long uint;
|
||||
typedef signed long sint;
|
||||
#endif
|
||||
|
||||
/*!
|
||||
on 64bit platforms we do not define ulint and slint
|
||||
*/
|
||||
|
||||
/*!
|
||||
how many bits there are in the uint type
|
||||
*/
|
||||
#define TTMATH_BITS_PER_UINT 64ul
|
||||
|
||||
/*!
|
||||
the mask for the highest bit in the unsigned 64bit word (2^63)
|
||||
*/
|
||||
#define TTMATH_UINT_HIGHEST_BIT 9223372036854775808ul
|
||||
|
||||
/*!
|
||||
the max value of the unsigned 64bit word (2^64 - 1)
|
||||
(all bits equal one)
|
||||
*/
|
||||
#define TTMATH_UINT_MAX_VALUE 18446744073709551615ul
|
||||
|
||||
/*!
|
||||
the number of words (64bit words on 64bit platforms)
|
||||
which are kept in built-in variables for a Big<> type
|
||||
(these variables are defined in ttmathbig.h)
|
||||
*/
|
||||
#define TTMATH_BUILTIN_VARIABLES_SIZE 128ul
|
||||
|
||||
/*!
|
||||
this macro returns the number of machine words
|
||||
capable to hold min_bits bits
|
||||
e.g. TTMATH_BITS(128) returns 2
|
||||
*/
|
||||
#define TTMATH_BITS(min_bits) ((min_bits-1)/64 + 1)
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#if defined(TTMATH_MULTITHREADS) && !defined(TTMATH_MULTITHREADS_NOSYNC)
|
||||
#if !defined(TTMATH_POSIX_THREADS) && !defined(TTMATH_WIN32_THREADS)
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define TTMATH_WIN32_THREADS
|
||||
#elif defined(unix) || defined(__unix__) || defined(__unix)
|
||||
#define TTMATH_POSIX_THREADS
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
this variable defines how many iterations are performed
|
||||
during some kind of calculating when we're making any long formulas
|
||||
(for example Taylor series)
|
||||
|
||||
it's used in ExpSurrounding0(...), LnSurrounding1(...), Sin0pi05(...), etc.
|
||||
|
||||
note! there'll not be so many iterations, iterations are stopped when
|
||||
there is no sense to continue calculating (for example when the result
|
||||
still remains unchanged after adding next series and we know that the next
|
||||
series are smaller than previous ones)
|
||||
*/
|
||||
#define TTMATH_ARITHMETIC_MAX_LOOP 10000
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
this is a limit when calculating Karatsuba multiplication
|
||||
if the size of a vector is smaller than TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE
|
||||
the Karatsuba algorithm will use standard schoolbook multiplication
|
||||
*/
|
||||
#ifdef TTMATH_DEBUG_LOG
|
||||
// if TTMATH_DEBUG_LOG is defined then we should use the same size regardless of the compiler
|
||||
#define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 3
|
||||
#else
|
||||
#ifdef __GNUC__
|
||||
#define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 3
|
||||
#else
|
||||
#define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 5
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/*!
|
||||
this is a special value used when calculating the Gamma(x) function
|
||||
if x is greater than this value then the Gamma(x) will be calculated using
|
||||
some kind of series
|
||||
|
||||
don't use smaller values than about 100
|
||||
*/
|
||||
#define TTMATH_GAMMA_BOUNDARY 2000
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
namespace ttmath
|
||||
{
|
||||
|
||||
/*!
|
||||
lib type codes:
|
||||
asm_vc_32 - with asm code designed for Microsoft Visual C++ (32 bits)
|
||||
asm_gcc_32 - with asm code designed for GCC (32 bits)
|
||||
asm_vc_64 - with asm for VC (64 bit)
|
||||
asm_gcc_64 - with asm for GCC (64 bit)
|
||||
no_asm_32 - pure C++ version (32 bit) - without any asm code
|
||||
no_asm_64 - pure C++ version (64 bit) - without any asm code
|
||||
*/
|
||||
enum LibTypeCode
|
||||
{
|
||||
asm_vc_32 = 0,
|
||||
asm_gcc_32,
|
||||
asm_vc_64,
|
||||
asm_gcc_64,
|
||||
no_asm_32,
|
||||
no_asm_64
|
||||
};
|
||||
|
||||
|
||||
/*!
|
||||
error codes
|
||||
*/
|
||||
enum ErrorCode
|
||||
{
|
||||
err_ok = 0,
|
||||
err_nothing_has_read,
|
||||
err_unknown_character,
|
||||
err_unexpected_final_bracket,
|
||||
err_stack_not_clear,
|
||||
err_unknown_variable,
|
||||
err_division_by_zero,
|
||||
err_interrupt,
|
||||
err_overflow,
|
||||
err_unknown_function,
|
||||
err_unknown_operator,
|
||||
err_unexpected_semicolon_operator,
|
||||
err_improper_amount_of_arguments,
|
||||
err_improper_argument,
|
||||
err_unexpected_end,
|
||||
err_internal_error,
|
||||
err_incorrect_name,
|
||||
err_incorrect_value,
|
||||
err_variable_exists,
|
||||
err_variable_loop,
|
||||
err_functions_loop,
|
||||
err_must_be_only_one_value,
|
||||
err_object_exists,
|
||||
err_unknown_object,
|
||||
err_still_calculating,
|
||||
err_in_short_form_used_function,
|
||||
err_percent_from
|
||||
};
|
||||
|
||||
|
||||
/*!
|
||||
this struct is used when converting to/from a string
|
||||
/temporarily only in Big::ToString() and Big::FromString()/
|
||||
*/
|
||||
struct Conv
|
||||
{
|
||||
/*!
|
||||
base (radix) on which the value will be shown (or read)
|
||||
default: 10
|
||||
*/
|
||||
uint base;
|
||||
|
||||
|
||||
/*!
|
||||
used only in Big::ToString()
|
||||
if true the value will be always shown in the scientific mode, e.g: 123e+30
|
||||
default: false
|
||||
*/
|
||||
bool scient;
|
||||
|
||||
|
||||
/*!
|
||||
used only in Big::ToString()
|
||||
if scient is false then the value will be printed in the scientific mode
|
||||
only if the exponent is greater than scien_from
|
||||
default: 15
|
||||
*/
|
||||
sint scient_from;
|
||||
|
||||
|
||||
/*!
|
||||
if 'base_round' is true and 'base' is different from 2, 4, 8, or 16
|
||||
and the result value is not an integer then we make an additional rounding
|
||||
(after converting the last digit from the result is skipped)
|
||||
default: true
|
||||
|
||||
e.g.
|
||||
Conv c;
|
||||
c.base_round = false;
|
||||
Big<1, 1> a = "0.1"; // decimal input
|
||||
std::cout << a.ToString(c) << std::endl; // the result is: 0.099999999
|
||||
*/
|
||||
bool base_round;
|
||||
|
||||
|
||||
/*!
|
||||
used only in Big::ToString()
|
||||
tells how many digits after comma are possible
|
||||
default: -1 which means all digits are printed
|
||||
|
||||
set it to zero if you want integer value only
|
||||
|
||||
for example when the value is:
|
||||
12.345678 and 'round' is 4
|
||||
then the result will be
|
||||
12.3457 (the last digit was rounded)
|
||||
*/
|
||||
sint round;
|
||||
|
||||
|
||||
/*!
|
||||
if true that not mattered digits in the mantissa will be cut off
|
||||
(zero characters at the end -- after the comma operator)
|
||||
e.g. 1234,78000 will be: 1234,78
|
||||
default: true
|
||||
*/
|
||||
bool trim_zeroes;
|
||||
|
||||
|
||||
/*!
|
||||
the main comma operator (used when reading and writing)
|
||||
default is a dot '.'
|
||||
*/
|
||||
uint comma;
|
||||
|
||||
|
||||
/*!
|
||||
additional comma operator (used only when reading)
|
||||
if you don't want it just set it to zero
|
||||
default is a comma ','
|
||||
|
||||
this allowes you to convert from a value:
|
||||
123.45 as well as from 123,45
|
||||
*/
|
||||
uint comma2;
|
||||
|
||||
|
||||
/*!
|
||||
it sets the character which is used for grouping
|
||||
if group=' ' then: 1234,56789 will be printed as: 1 234,567 89
|
||||
|
||||
if you don't want grouping just set it to zero (which is default)
|
||||
*/
|
||||
uint group;
|
||||
|
||||
|
||||
/*!
|
||||
how many digits should be grouped (it is used if 'group' is non zero)
|
||||
default: 3
|
||||
*/
|
||||
uint group_digits;
|
||||
|
||||
|
||||
/*!
|
||||
*/
|
||||
uint group_exp; // not implemented yet
|
||||
|
||||
|
||||
|
||||
|
||||
Conv()
|
||||
{
|
||||
// default values
|
||||
base = 10;
|
||||
scient = false;
|
||||
scient_from = 15;
|
||||
base_round = true;
|
||||
round = -1;
|
||||
trim_zeroes = true;
|
||||
comma = '.';
|
||||
comma2 = ',';
|
||||
group = 0;
|
||||
group_digits = 3;
|
||||
group_exp = 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
this simple class can be used in multithreading model
|
||||
(you can write your own class derived from this one)
|
||||
|
||||
for example: in some functions like Factorial()
|
||||
/at the moment only Factorial/ you can give a pointer to
|
||||
the 'stop object', if the method WasStopSignal() of this
|
||||
object returns true that means we should break the calculating
|
||||
and return
|
||||
*/
|
||||
class StopCalculating
|
||||
{
|
||||
public:
|
||||
virtual bool WasStopSignal() const volatile { return false; }
|
||||
virtual ~StopCalculating(){}
|
||||
};
|
||||
|
||||
|
||||
/*!
|
||||
a small class which is useful when compiling with gcc
|
||||
|
||||
object of this type holds the name and the line of a file
|
||||
in which the macro TTMATH_ASSERT or TTMATH_REFERENCE_ASSERT was used
|
||||
*/
|
||||
class ExceptionInfo
|
||||
{
|
||||
const char * file;
|
||||
int line;
|
||||
|
||||
public:
|
||||
ExceptionInfo() : file(0), line(0) {}
|
||||
ExceptionInfo(const char * f, int l) : file(f), line(l) {}
|
||||
|
||||
std::string Where() const
|
||||
{
|
||||
if( !file )
|
||||
return "unknown";
|
||||
|
||||
std::ostringstream result;
|
||||
result << file << ":" << line;
|
||||
|
||||
return result.str();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*!
|
||||
A small class used for reporting 'reference' errors
|
||||
|
||||
In the library is used macro TTMATH_REFERENCE_ASSERT which
|
||||
can throw an exception of this type
|
||||
|
||||
** from version 0.9.2 this macro is removed from all methods
|
||||
in public interface so you don't have to worry about it **
|
||||
|
||||
If you compile with gcc you can get a small benefit
|
||||
from using method Where() (it returns std::string) with
|
||||
the name and the line of a file where the macro TTMATH_REFERENCE_ASSERT
|
||||
was used)
|
||||
*/
|
||||
class ReferenceError : public std::logic_error, public ExceptionInfo
|
||||
{
|
||||
public:
|
||||
|
||||
ReferenceError() : std::logic_error("reference error")
|
||||
{
|
||||
}
|
||||
|
||||
ReferenceError(const char * f, int l) :
|
||||
std::logic_error("reference error"), ExceptionInfo(f,l)
|
||||
{
|
||||
}
|
||||
|
||||
std::string Where() const
|
||||
{
|
||||
return ExceptionInfo::Where();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*!
|
||||
a small class used for reporting errors
|
||||
|
||||
in the library is used macro TTMATH_ASSERT which
|
||||
(if the condition in it is false) throw an exception
|
||||
of this type
|
||||
|
||||
if you compile with gcc you can get a small benefit
|
||||
from using method Where() (it returns std::string) with
|
||||
the name and the line of a file where the macro TTMATH_ASSERT
|
||||
was used)
|
||||
*/
|
||||
class RuntimeError : public std::runtime_error, public ExceptionInfo
|
||||
{
|
||||
public:
|
||||
|
||||
RuntimeError() : std::runtime_error("internal error")
|
||||
{
|
||||
}
|
||||
|
||||
RuntimeError(const char * f, int l) :
|
||||
std::runtime_error("internal error"), ExceptionInfo(f,l)
|
||||
{
|
||||
}
|
||||
|
||||
std::string Where() const
|
||||
{
|
||||
return ExceptionInfo::Where();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
TTMATH_DEBUG
|
||||
this macro enables further testing during writing your code
|
||||
you don't have to define it in a release mode
|
||||
|
||||
if this macro is set then macros TTMATH_ASSERT and TTMATH_REFERENCE_ASSERT
|
||||
are set as well and these macros can throw an exception if a condition in it
|
||||
is not fulfilled (look at the definition of TTMATH_ASSERT and TTMATH_REFERENCE_ASSERT)
|
||||
|
||||
TTMATH_DEBUG is set automatically if DEBUG or _DEBUG are defined
|
||||
*/
|
||||
#if defined DEBUG || defined _DEBUG
|
||||
#define TTMATH_DEBUG
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef TTMATH_DEBUG
|
||||
|
||||
#if defined(__FILE__) && defined(__LINE__)
|
||||
|
||||
#define TTMATH_REFERENCE_ASSERT(expression) \
|
||||
if( &(expression) == this ) throw ttmath::ReferenceError(__FILE__, __LINE__);
|
||||
|
||||
#define TTMATH_ASSERT(expression) \
|
||||
if( !(expression) ) throw ttmath::RuntimeError(__FILE__, __LINE__);
|
||||
|
||||
#else
|
||||
|
||||
#define TTMATH_REFERENCE_ASSERT(expression) \
|
||||
if( &(expression) == this ) throw ReferenceError();
|
||||
|
||||
#define TTMATH_ASSERT(expression) \
|
||||
if( !(expression) ) throw RuntimeError();
|
||||
#endif
|
||||
|
||||
#else
|
||||
#define TTMATH_REFERENCE_ASSERT(expression)
|
||||
#define TTMATH_ASSERT(expression)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef TTMATH_DEBUG_LOG
|
||||
#define TTMATH_LOG(msg) PrintLog(msg, std::cout);
|
||||
#define TTMATH_LOGC(msg, carry) PrintLog(msg, carry, std::cout);
|
||||
#define TTMATH_VECTOR_LOG(msg, vector, len) PrintVectorLog(msg, std::cout, vector, len);
|
||||
#define TTMATH_VECTOR_LOGC(msg, carry, vector, len) PrintVectorLog(msg, carry, std::cout, vector, len);
|
||||
#else
|
||||
#define TTMATH_LOG(msg)
|
||||
#define TTMATH_LOGC(msg, carry)
|
||||
#define TTMATH_VECTOR_LOG(msg, vector, len)
|
||||
#define TTMATH_VECTOR_LOGC(msg, carry, vector, len)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
#endif
|
||||
|
4126
extern/ttmath/ttmathuint.h
vendored
Normal file
4126
extern/ttmath/ttmathuint.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1017
extern/ttmath/ttmathuint_noasm.h
vendored
Normal file
1017
extern/ttmath/ttmathuint_noasm.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1602
extern/ttmath/ttmathuint_x86.h
vendored
Normal file
1602
extern/ttmath/ttmathuint_x86.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1146
extern/ttmath/ttmathuint_x86_64.h
vendored
Normal file
1146
extern/ttmath/ttmathuint_x86_64.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
548
extern/ttmath/ttmathuint_x86_64_msvc.asm
vendored
Normal file
548
extern/ttmath/ttmathuint_x86_64_msvc.asm
vendored
Normal file
@ -0,0 +1,548 @@
|
||||
;
|
||||
; This file is a part of TTMath Bignum Library
|
||||
; and is distributed under the (new) BSD licence.
|
||||
; Author: Christian Kaiser <chk@online.de>
|
||||
;
|
||||
|
||||
;
|
||||
; Copyright (c) 2009, Christian Kaiser
|
||||
; All rights reserved.
|
||||
;
|
||||
; Redistribution and use in source and binary forms, with or without
|
||||
; modification, are permitted provided that the following conditions are met:
|
||||
;
|
||||
; * Redistributions of source code must retain the above copyright notice,
|
||||
; this list of conditions and the following disclaimer.
|
||||
;
|
||||
; * 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.
|
||||
;
|
||||
; * Neither the name Christian Kaiser nor the names of contributors to this
|
||||
; project may be used to endorse or promote products derived
|
||||
; from this software without specific prior written permission.
|
||||
;
|
||||
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
|
||||
;
|
||||
|
||||
;
|
||||
; compile with debug info: ml64.exe /c /Zd /Zi ttmathuint_x86_64_msvc.asm
|
||||
; compile without debug info: ml64.exe /c ttmathuint_x86_64_msvc.asm
|
||||
; this creates ttmathuint_x86_64_msvc.obj file which can be linked with your program
|
||||
;
|
||||
|
||||
PUBLIC ttmath_adc_x64
|
||||
PUBLIC ttmath_addindexed_x64
|
||||
PUBLIC ttmath_addindexed2_x64
|
||||
PUBLIC ttmath_addvector_x64
|
||||
|
||||
PUBLIC ttmath_sbb_x64
|
||||
PUBLIC ttmath_subindexed_x64
|
||||
PUBLIC ttmath_subvector_x64
|
||||
|
||||
PUBLIC ttmath_rcl_x64
|
||||
PUBLIC ttmath_rcr_x64
|
||||
|
||||
PUBLIC ttmath_rcl2_x64
|
||||
PUBLIC ttmath_rcr2_x64
|
||||
|
||||
PUBLIC ttmath_div_x64
|
||||
|
||||
;
|
||||
; Microsoft x86_64 convention: http://msdn.microsoft.com/en-us/library/9b372w95.aspx
|
||||
;
|
||||
; "rax, rcx, rdx, r8-r11 are volatile."
|
||||
; "rbx, rbp, rdi, rsi, r12-r15 are nonvolatile."
|
||||
;
|
||||
|
||||
|
||||
.CODE
|
||||
|
||||
|
||||
ALIGN 8
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
ttmath_adc_x64 PROC
|
||||
; rcx = p1
|
||||
; rdx = p2
|
||||
; r8 = nSize
|
||||
; r9 = nCarry
|
||||
|
||||
xor rax, rax
|
||||
xor r11, r11
|
||||
sub rax, r9 ; sets CARRY if r9 != 0
|
||||
|
||||
ALIGN 16
|
||||
loop1:
|
||||
mov rax,qword ptr [rdx + r11 * 8]
|
||||
adc qword ptr [rcx + r11 * 8], rax
|
||||
lea r11, [r11+1]
|
||||
dec r8
|
||||
jnz loop1
|
||||
|
||||
setc al
|
||||
movzx rax, al
|
||||
|
||||
ret
|
||||
|
||||
ttmath_adc_x64 ENDP
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
ALIGN 8
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
ttmath_addindexed_x64 PROC
|
||||
|
||||
; rcx = p1
|
||||
; rdx = nSize
|
||||
; r8 = nPos
|
||||
; r9 = nValue
|
||||
|
||||
xor rax, rax ; rax = result
|
||||
sub rdx, r8 ; rdx = remaining count of uints
|
||||
|
||||
add qword ptr [rcx + r8 * 8], r9
|
||||
jc next1
|
||||
|
||||
ret
|
||||
|
||||
next1:
|
||||
mov r9, 1
|
||||
|
||||
ALIGN 16
|
||||
loop1:
|
||||
dec rdx
|
||||
jz done_with_cy
|
||||
lea r8, [r8+1]
|
||||
add qword ptr [rcx + r8 * 8], r9
|
||||
jc loop1
|
||||
|
||||
ret
|
||||
|
||||
done_with_cy:
|
||||
lea rax, [rax+1] ; rax = 1
|
||||
|
||||
ret
|
||||
|
||||
ttmath_addindexed_x64 ENDP
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
ALIGN 8
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
ttmath_addindexed2_x64 PROC
|
||||
|
||||
; rcx = p1 (pointer)
|
||||
; rdx = b (value size)
|
||||
; r8 = nPos
|
||||
; r9 = nValue1
|
||||
; [esp+0x28] = nValue2
|
||||
|
||||
xor rax, rax ; return value
|
||||
mov r11, rcx ; table
|
||||
sub rdx, r8 ; rdx = remaining count of uints
|
||||
mov r10, [esp+028h] ; r10 = nValue2
|
||||
|
||||
add qword ptr [r11 + r8 * 8], r9
|
||||
lea r8, [r8+1]
|
||||
lea rdx, [rdx-1]
|
||||
adc qword ptr [r11 + r8 * 8], r10
|
||||
jc next
|
||||
ret
|
||||
|
||||
ALIGN 16
|
||||
loop1:
|
||||
lea r8, [r8+1]
|
||||
add qword ptr [r11 + r8 * 8], 1
|
||||
jc next
|
||||
ret
|
||||
|
||||
next:
|
||||
dec rdx ; does not modify CY too...
|
||||
jnz loop1
|
||||
lea rax, [rax+1]
|
||||
ret
|
||||
|
||||
ttmath_addindexed2_x64 ENDP
|
||||
|
||||
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
ALIGN 8
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
|
||||
ttmath_addvector_x64 PROC
|
||||
; rcx = ss1
|
||||
; rdx = ss2
|
||||
; r8 = ss1_size
|
||||
; r9 = ss2_size
|
||||
; [esp+0x28] = result
|
||||
|
||||
mov r10, [esp+028h]
|
||||
sub r8, r9
|
||||
xor r11, r11 ; r11=0, cf=0
|
||||
|
||||
ALIGN 16
|
||||
loop1:
|
||||
mov rax, qword ptr [rcx + r11 * 8]
|
||||
adc rax, qword ptr [rdx + r11 * 8]
|
||||
mov qword ptr [r10 + r11 * 8], rax
|
||||
inc r11
|
||||
dec r9
|
||||
jnz loop1
|
||||
|
||||
adc r9, r9 ; r9 has the cf state
|
||||
|
||||
or r8, r8
|
||||
jz done
|
||||
|
||||
neg r9 ; setting cf from r9
|
||||
mov r9, 0 ; don't use xor here (cf is used)
|
||||
loop2:
|
||||
mov rax, qword ptr [rcx + r11 * 8]
|
||||
adc rax, r9
|
||||
mov qword ptr [r10 + r11 * 8], rax
|
||||
inc r11
|
||||
dec r8
|
||||
jnz loop2
|
||||
|
||||
adc r8, r8
|
||||
mov rax, r8
|
||||
|
||||
ret
|
||||
|
||||
done:
|
||||
mov rax, r9
|
||||
ret
|
||||
|
||||
ttmath_addvector_x64 ENDP
|
||||
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
ALIGN 8
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
ttmath_sbb_x64 PROC
|
||||
|
||||
; rcx = p1
|
||||
; rdx = p2
|
||||
; r8 = nCount
|
||||
; r9 = nCarry
|
||||
|
||||
xor rax, rax
|
||||
xor r11, r11
|
||||
sub rax, r9 ; sets CARRY if r9 != 0
|
||||
|
||||
ALIGN 16
|
||||
loop1:
|
||||
mov rax,qword ptr [rdx + r11 * 8]
|
||||
sbb qword ptr [rcx + r11 * 8], rax
|
||||
lea r11, [r11+1]
|
||||
dec r8
|
||||
jnz loop1
|
||||
|
||||
setc al
|
||||
movzx rax, al
|
||||
|
||||
ret
|
||||
|
||||
ttmath_sbb_x64 ENDP
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
ALIGN 8
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
ttmath_subindexed_x64 PROC
|
||||
; rcx = p1
|
||||
; rdx = nSize
|
||||
; r8 = nPos
|
||||
; r9 = nValue
|
||||
|
||||
sub rdx, r8 ; rdx = remaining count of uints
|
||||
|
||||
ALIGN 16
|
||||
loop1:
|
||||
sub qword ptr [rcx + r8 * 8], r9
|
||||
jnc done
|
||||
|
||||
lea r8, [r8+1]
|
||||
mov r9, 1
|
||||
dec rdx
|
||||
jnz loop1
|
||||
|
||||
mov rax, 1
|
||||
ret
|
||||
|
||||
done:
|
||||
xor rax, rax
|
||||
ret
|
||||
|
||||
ttmath_subindexed_x64 ENDP
|
||||
|
||||
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
ALIGN 8
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
; the same asm code as in addvector_x64 only two instructions 'adc' changed to 'sbb'
|
||||
|
||||
ttmath_subvector_x64 PROC
|
||||
; rcx = ss1
|
||||
; rdx = ss2
|
||||
; r8 = ss1_size
|
||||
; r9 = ss2_size
|
||||
; [esp+0x28] = result
|
||||
|
||||
mov r10, [esp+028h]
|
||||
sub r8, r9
|
||||
xor r11, r11 ; r11=0, cf=0
|
||||
|
||||
ALIGN 16
|
||||
loop1:
|
||||
mov rax, qword ptr [rcx + r11 * 8]
|
||||
sbb rax, qword ptr [rdx + r11 * 8]
|
||||
mov qword ptr [r10 + r11 * 8], rax
|
||||
inc r11
|
||||
dec r9
|
||||
jnz loop1
|
||||
|
||||
adc r9, r9 ; r9 has the cf state
|
||||
|
||||
or r8, r8
|
||||
jz done
|
||||
|
||||
neg r9 ; setting cf from r9
|
||||
mov r9, 0 ; don't use xor here (cf is used)
|
||||
loop2:
|
||||
mov rax, qword ptr [rcx + r11 * 8]
|
||||
sbb rax, r9
|
||||
mov qword ptr [r10 + r11 * 8], rax
|
||||
inc r11
|
||||
dec r8
|
||||
jnz loop2
|
||||
|
||||
adc r8, r8
|
||||
mov rax, r8
|
||||
|
||||
ret
|
||||
|
||||
done:
|
||||
mov rax, r9
|
||||
ret
|
||||
|
||||
ttmath_subvector_x64 ENDP
|
||||
|
||||
|
||||
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
ALIGN 8
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
ttmath_rcl_x64 PROC
|
||||
; rcx = p1
|
||||
; rdx = b
|
||||
; r8 = nLowestBit
|
||||
|
||||
mov r11, rcx ; table
|
||||
xor r10, r10
|
||||
neg r8 ; CY set if r8 <> 0
|
||||
|
||||
ALIGN 16
|
||||
loop1:
|
||||
rcl qword ptr [r11 + r10 * 8], 1
|
||||
lea r10, [r10+1]
|
||||
dec rdx
|
||||
jnz loop1
|
||||
|
||||
setc al
|
||||
movzx rax, al
|
||||
|
||||
ret
|
||||
|
||||
ttmath_rcl_x64 ENDP
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
ALIGN 8
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
ttmath_rcr_x64 PROC
|
||||
; rcx = p1
|
||||
; rdx = nSize
|
||||
; r8 = nLowestBit
|
||||
|
||||
xor r10, r10
|
||||
neg r8 ; CY set if r8 <> 0
|
||||
|
||||
ALIGN 16
|
||||
loop1:
|
||||
rcr qword ptr -8[rcx + rdx * 8], 1
|
||||
dec rdx
|
||||
jnz loop1
|
||||
|
||||
setc al
|
||||
movzx rax, al
|
||||
|
||||
ret
|
||||
|
||||
ttmath_rcr_x64 ENDP
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
ALIGN 8
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
ttmath_div_x64 PROC
|
||||
|
||||
; rcx = &Hi
|
||||
; rdx = &Lo
|
||||
; r8 = nDiv
|
||||
|
||||
mov r11, rcx
|
||||
mov r10, rdx
|
||||
|
||||
mov rdx, qword ptr [r11]
|
||||
mov rax, qword ptr [r10]
|
||||
div r8
|
||||
mov qword ptr [r10], rdx ; remainder
|
||||
mov qword ptr [r11], rax ; value
|
||||
|
||||
ret
|
||||
|
||||
ttmath_div_x64 ENDP
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
ALIGN 8
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
ttmath_rcl2_x64 PROC
|
||||
; rcx = p1
|
||||
; rdx = nSize
|
||||
; r8 = bits
|
||||
; r9 = c
|
||||
|
||||
push rbx
|
||||
|
||||
mov r10, rcx ; r10 = p1
|
||||
xor rax, rax
|
||||
|
||||
mov rcx, 64
|
||||
sub rcx, r8
|
||||
|
||||
mov r11, -1
|
||||
shr r11, cl ; r11 = mask
|
||||
|
||||
mov rcx, r8 ; rcx = count of bits
|
||||
|
||||
mov rbx, rax ; rbx = old value = 0
|
||||
or r9, r9
|
||||
cmovnz rbx, r11 ; if (c) then old value = mask
|
||||
|
||||
mov r9, rax ; r9 = index (0..nSize-1)
|
||||
|
||||
ALIGN 16
|
||||
loop1:
|
||||
rol qword ptr [r10+r9*8], cl
|
||||
mov rax, qword ptr [r10+r9*8]
|
||||
and rax, r11
|
||||
xor qword ptr [r10+r9*8], rax
|
||||
or qword ptr [r10+r9*8], rbx
|
||||
mov rbx, rax
|
||||
|
||||
lea r9, [r9+1]
|
||||
dec rdx
|
||||
|
||||
jnz loop1
|
||||
|
||||
and rax, 1
|
||||
pop rbx
|
||||
ret
|
||||
|
||||
ttmath_rcl2_x64 ENDP
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
ALIGN 8
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
ttmath_rcr2_x64 PROC
|
||||
; rcx = p1
|
||||
; rdx = nSize
|
||||
; r8 = bits
|
||||
; r9 = c
|
||||
|
||||
push rbx
|
||||
mov r10, rcx ; r10 = p1
|
||||
xor rax, rax
|
||||
|
||||
mov rcx, 64
|
||||
sub rcx, r8
|
||||
|
||||
mov r11, -1
|
||||
shl r11, cl ; r11 = mask
|
||||
|
||||
mov rcx, r8 ; rcx = count of bits
|
||||
|
||||
mov rbx, rax ; rbx = old value = 0
|
||||
or r9, r9
|
||||
cmovnz rbx, r11 ; if (c) then old value = mask
|
||||
|
||||
mov r9, rdx ; r9 = index (0..nSize-1)
|
||||
lea r9, [r9-1]
|
||||
|
||||
ALIGN 16
|
||||
loop1:
|
||||
ror qword ptr [r10+r9*8], cl
|
||||
mov rax, qword ptr [r10+r9*8]
|
||||
and rax, r11
|
||||
xor qword ptr [r10+r9*8], rax
|
||||
or qword ptr [r10+r9*8], rbx
|
||||
mov rbx, rax
|
||||
|
||||
lea r9, [r9-1]
|
||||
dec rdx
|
||||
|
||||
jnz loop1
|
||||
|
||||
rol rax, 1
|
||||
and rax, 1
|
||||
pop rbx
|
||||
|
||||
ret
|
||||
|
||||
ttmath_rcr2_x64 ENDP
|
||||
|
||||
END
|
@ -1472,8 +1472,8 @@ void put_data(burp_rel* relation)
|
||||
add_byte(blr, field->fld_scale);
|
||||
break;
|
||||
|
||||
case blr_dec_fixed:
|
||||
alignment = type_alignments[dtype_dec_fixed];
|
||||
case blr_int128:
|
||||
alignment = type_alignments[dtype_int128];
|
||||
add_byte(blr, field->fld_type);
|
||||
add_byte(blr, field->fld_scale);
|
||||
break;
|
||||
|
@ -170,11 +170,15 @@ ULONG CAN_encode_decode(burp_rel* relation, lstring* buffer, UCHAR* data, bool d
|
||||
break;
|
||||
|
||||
case dtype_dec128:
|
||||
case dtype_dec_fixed:
|
||||
if (!xdr_dec128(xdrs, (Firebird::Decimal128*) p))
|
||||
return FALSE;
|
||||
break;
|
||||
|
||||
case dtype_int128:
|
||||
if (!xdr_int128(xdrs, (Firebird::Int128*) p))
|
||||
return FALSE;
|
||||
break;
|
||||
|
||||
case dtype_timestamp:
|
||||
if (!xdr_long(xdrs, &((SLONG*) p)[0]))
|
||||
return FALSE;
|
||||
|
@ -3579,7 +3579,7 @@ rec_type get_data_old(BurpGlobals* tdgbl, burp_rel* relation)
|
||||
case blr_long:
|
||||
case blr_quad:
|
||||
case blr_int64:
|
||||
case blr_dec_fixed:
|
||||
case blr_int128:
|
||||
add_byte(blr, field->fld_type);
|
||||
add_byte(blr, field->fld_scale);
|
||||
break;
|
||||
|
@ -28,6 +28,7 @@
|
||||
|
||||
#include "firebird.h"
|
||||
#include "DecFloat.h"
|
||||
#include "Int128.h"
|
||||
|
||||
#include "StatusArg.h"
|
||||
#include "gen/iberror.h"
|
||||
@ -49,7 +50,7 @@ extern "C"
|
||||
using namespace Firebird;
|
||||
|
||||
const DecimalStatus DecimalStatus::DEFAULT(FB_DEC_Errors);
|
||||
const DecimalBinding DecimalBinding::DEFAULT;
|
||||
const NumericBinding NumericBinding::DEFAULT;
|
||||
|
||||
namespace {
|
||||
|
||||
@ -77,7 +78,7 @@ public:
|
||||
init(DEC_INIT_DECIMAL64);
|
||||
}
|
||||
|
||||
DecimalContext(const Decimal128Base*, DecimalStatus ds)
|
||||
DecimalContext(const Decimal128*, DecimalStatus ds)
|
||||
: decSt(ds)
|
||||
{
|
||||
init(DEC_INIT_DECIMAL128);
|
||||
@ -126,6 +127,8 @@ const CDecimal128 dmax(DBL_MAX, DecimalStatus(0)), dmin(-DBL_MAX, DecimalStatus(
|
||||
const CDecimal128 dzup(DBL_MIN, DecimalStatus(0)), dzlw(-DBL_MIN, DecimalStatus(0));
|
||||
const CDecimal128 i64max(MAX_SINT64, DecimalStatus(0)), i64min(MIN_SINT64, DecimalStatus(0));
|
||||
const CDecimal128 c1(1);
|
||||
const CDecimal128 pow2_32("4294967296", DecimalStatus(0));
|
||||
const CDecimal128 pow2_64("18446744073709551616", DecimalStatus(0));
|
||||
|
||||
unsigned digits(const unsigned pMax, unsigned char* const coeff, int& exp)
|
||||
{
|
||||
@ -265,7 +268,7 @@ Decimal64 Decimal64::set(SLONG value, DecimalStatus decSt, int scale)
|
||||
return *this;
|
||||
}
|
||||
|
||||
Decimal64 Decimal64::set(DecimalFixed value, DecimalStatus decSt, int scale)
|
||||
Decimal64 Decimal64::set(Int128 value, DecimalStatus decSt, int scale)
|
||||
{
|
||||
Decimal128 tmp;
|
||||
tmp.set(value, decSt, scale);
|
||||
@ -518,11 +521,21 @@ Decimal128 Decimal128::set(SLONG value, DecimalStatus decSt, int scale)
|
||||
return *this;
|
||||
}
|
||||
|
||||
Decimal128 Decimal128::set(DecimalFixed value, DecimalStatus decSt, int scale)
|
||||
Decimal128 Decimal128::set(Int128 value, DecimalStatus decSt, int scale)
|
||||
{
|
||||
*this = value;
|
||||
setScale(decSt, -scale);
|
||||
unsigned dwords[4];
|
||||
value.getTable32(dwords);
|
||||
|
||||
DecimalContext context(this, decSt);
|
||||
decQuadFromInt32(&dec, dwords[3]);
|
||||
for (int i = 3; i--; )
|
||||
{
|
||||
decQuad dw;
|
||||
decQuadFromUInt32(&dw, dwords[i]);
|
||||
decQuadFMA(&dec, &dec, &pow2_32.dec, &dw, &context);
|
||||
}
|
||||
|
||||
setScale(decSt, -scale);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -533,13 +546,10 @@ Decimal128 Decimal128::set(SINT64 value, DecimalStatus decSt, int scale)
|
||||
unsigned low = value & 0xFFFFFFFF;
|
||||
|
||||
DecimalContext context(this, decSt);
|
||||
decQuad pow2_32;
|
||||
decQuadFromString(&pow2_32, "4294967296", &context);
|
||||
|
||||
decQuad up, down;
|
||||
decQuadFromInt32(&up, high);
|
||||
decQuadFromUInt32(&down, low);
|
||||
decQuadFMA(&dec, &up, &pow2_32, &down, &context);
|
||||
decQuadFMA(&dec, &up, &pow2_32.dec, &down, &context);
|
||||
}
|
||||
|
||||
setScale(decSt, -scale);
|
||||
@ -565,80 +575,6 @@ Decimal128 Decimal128::set(double value, DecimalStatus decSt)
|
||||
return *this;
|
||||
}
|
||||
|
||||
DecimalFixed DecimalFixed::set(SLONG value)
|
||||
{
|
||||
decQuadFromInt32(&dec, value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
DecimalFixed DecimalFixed::set(SINT64 value)
|
||||
{
|
||||
int high = value >> 32;
|
||||
unsigned low = value & 0xFFFFFFFF;
|
||||
|
||||
DecimalContext context(this, DecimalStatus(0));
|
||||
decQuad pow2_32;
|
||||
decQuadFromString(&pow2_32, "4294967296", &context);
|
||||
|
||||
decQuad up, down;
|
||||
decQuadFromInt32(&up, high);
|
||||
decQuadFromUInt32(&down, low);
|
||||
decQuadFMA(&dec, &up, &pow2_32, &down, &context);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
DecimalFixed DecimalFixed::set(const char* value, int scale, DecimalStatus decSt)
|
||||
{
|
||||
{ // scope for 'context'
|
||||
DecimalContext context(this, decSt);
|
||||
decQuadFromString(&dec, value, &context);
|
||||
}
|
||||
|
||||
exactInt(decSt, scale);
|
||||
return *this;
|
||||
}
|
||||
|
||||
DecimalFixed DecimalFixed::set(double value, int scale, DecimalStatus decSt)
|
||||
{
|
||||
char s[50];
|
||||
sprintf(s, "%18.016e", value);
|
||||
{ // scope for 'context'
|
||||
DecimalContext context(this, decSt);
|
||||
decQuadFromString(&dec, s, &context);
|
||||
}
|
||||
|
||||
exactInt(decSt, scale);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void DecimalFixed::exactInt(DecimalStatus decSt, int scale)
|
||||
{
|
||||
setScale(decSt, -scale);
|
||||
|
||||
try
|
||||
{
|
||||
DecimalContext context(this, decSt);
|
||||
decQuadToIntegralExact(&dec, &dec, &context);
|
||||
decQuadQuantize(&dec, &dec, &c1.dec, &context);
|
||||
}
|
||||
catch (const Exception& ex)
|
||||
{
|
||||
FbLocalStatus st;
|
||||
ex.stuffException(&st);
|
||||
|
||||
switch (st->getErrors()[1])
|
||||
{
|
||||
case isc_decfloat_invalid_operation:
|
||||
(Arg::Gds(isc_decfloat_invalid_operation) <<
|
||||
Arg::Gds(isc_numeric_out_of_range)).raise();
|
||||
break;
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
Decimal128 Decimal128::operator=(Decimal64 d64)
|
||||
{
|
||||
decDoubleToWider(&d64.dec, &dec);
|
||||
@ -654,13 +590,6 @@ int Decimal128::toInteger(DecimalStatus decSt, int scale) const
|
||||
return decQuadToInt32(&tmp.dec, &context, rMode);
|
||||
}
|
||||
|
||||
int DecimalFixed::toInteger(DecimalStatus decSt) const
|
||||
{
|
||||
DecimalContext context(this, decSt);
|
||||
enum rounding rMode = decContextGetRounding(&context);
|
||||
return decQuadToInt32(&dec, &context, rMode);
|
||||
}
|
||||
|
||||
void Decimal128::toString(DecimalStatus decSt, unsigned length, char* to) const
|
||||
{
|
||||
DecimalContext context(this, decSt);
|
||||
@ -690,24 +619,7 @@ void Decimal128::toString(string& to) const
|
||||
to.recalculate_length();
|
||||
}
|
||||
|
||||
Decimal128 DecimalFixed::scaled128(DecimalStatus decSt, int scale) const
|
||||
{
|
||||
Decimal128 tmp;
|
||||
tmp.set(*this, decSt, -scale);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void DecimalFixed::toString(DecimalStatus decSt, int scale, unsigned length, char* to) const
|
||||
{
|
||||
scaled128(decSt, scale).toString(decSt, length, to);
|
||||
}
|
||||
|
||||
void DecimalFixed::toString(DecimalStatus decSt, int scale, string& to) const
|
||||
{
|
||||
scaled128(decSt, scale).toString(to);
|
||||
}
|
||||
|
||||
double Decimal128Base::toDouble(DecimalStatus decSt) const
|
||||
double Decimal128::toDouble(DecimalStatus decSt) const
|
||||
{
|
||||
DecimalContext context(this, decSt);
|
||||
|
||||
@ -764,37 +676,12 @@ SINT64 Decimal128::toInt64(DecimalStatus decSt, int scale) const
|
||||
return rc;
|
||||
}
|
||||
|
||||
SINT64 DecimalFixed::toInt64(DecimalStatus decSt) const
|
||||
{
|
||||
if (compare(decSt, i64min) < 0 || compare(decSt, i64max) > 0)
|
||||
{
|
||||
DecimalContext context(this, decSt);
|
||||
decContextSetStatus(&context, DEC_Invalid_operation);
|
||||
return 0; // in case of no trap on invalid operation
|
||||
}
|
||||
|
||||
unsigned char coeff[DECQUAD_Pmax];
|
||||
int sign = decQuadGetCoefficient(&dec, coeff);
|
||||
SINT64 rc = 0;
|
||||
|
||||
for (int i = 0; i < DECQUAD_Pmax; ++i)
|
||||
{
|
||||
rc *= 10;
|
||||
if (sign)
|
||||
rc -= coeff[i];
|
||||
else
|
||||
rc += coeff[i];
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
UCHAR* Decimal128Base::getBytes()
|
||||
UCHAR* Decimal128::getBytes()
|
||||
{
|
||||
return dec.bytes;
|
||||
}
|
||||
|
||||
Decimal64 Decimal128Base::toDecimal64(DecimalStatus decSt) const
|
||||
Decimal64 Decimal128::toDecimal64(DecimalStatus decSt) const
|
||||
{
|
||||
Decimal64 rc;
|
||||
DecimalContext context(this, decSt);
|
||||
@ -802,7 +689,7 @@ Decimal64 Decimal128Base::toDecimal64(DecimalStatus decSt) const
|
||||
return rc;
|
||||
}
|
||||
|
||||
void Decimal128Base::setScale(DecimalStatus decSt, int scale)
|
||||
void Decimal128::setScale(DecimalStatus decSt, int scale)
|
||||
{
|
||||
if (scale)
|
||||
{
|
||||
@ -812,7 +699,7 @@ void Decimal128Base::setScale(DecimalStatus decSt, int scale)
|
||||
}
|
||||
}
|
||||
|
||||
int Decimal128Base::compare(DecimalStatus decSt, Decimal128Base tgt) const
|
||||
int Decimal128::compare(DecimalStatus decSt, Decimal128 tgt) const
|
||||
{
|
||||
DecimalContext context(this, decSt);
|
||||
decQuad r;
|
||||
@ -820,7 +707,7 @@ int Decimal128Base::compare(DecimalStatus decSt, Decimal128Base tgt) const
|
||||
return decQuadToInt32(&r, &context, DEC_ROUND_HALF_UP);
|
||||
}
|
||||
|
||||
bool Decimal128Base::isInf() const
|
||||
bool Decimal128::isInf() const
|
||||
{
|
||||
switch(decQuadClass(&dec))
|
||||
{
|
||||
@ -832,7 +719,7 @@ bool Decimal128Base::isInf() const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Decimal128Base::isNan() const
|
||||
bool Decimal128::isNan() const
|
||||
{
|
||||
switch(decQuadClass(&dec))
|
||||
{
|
||||
@ -844,7 +731,7 @@ bool Decimal128Base::isNan() const
|
||||
return false;
|
||||
}
|
||||
|
||||
int Decimal128Base::sign() const
|
||||
int Decimal128::sign() const
|
||||
{
|
||||
if (decQuadIsZero(&dec))
|
||||
return 0;
|
||||
@ -870,7 +757,7 @@ Decimal128 Decimal128::floor(DecimalStatus decSt) const
|
||||
}
|
||||
|
||||
#ifdef DEV_BUILD
|
||||
int Decimal128Base::show()
|
||||
int Decimal128::show()
|
||||
{
|
||||
decQuadShow(&dec, "");
|
||||
return 0;
|
||||
@ -915,50 +802,6 @@ Decimal128 Decimal128::mul(DecimalStatus decSt, Decimal128 op2) const
|
||||
return rc;
|
||||
}
|
||||
|
||||
DecimalFixed DecimalFixed::abs() const
|
||||
{
|
||||
DecimalFixed rc;
|
||||
decQuadCopyAbs(&rc.dec, &dec);
|
||||
return rc;
|
||||
}
|
||||
|
||||
DecimalFixed DecimalFixed::neg() const
|
||||
{
|
||||
DecimalFixed rc;
|
||||
decQuadCopyNegate(&rc.dec, &dec);
|
||||
return rc;
|
||||
}
|
||||
|
||||
DecimalFixed DecimalFixed::add(DecimalStatus decSt, DecimalFixed op2) const
|
||||
{
|
||||
DecimalContext context(this, decSt);
|
||||
DecimalFixed rc;
|
||||
decQuadAdd(&rc.dec, &dec, &op2.dec, &context);
|
||||
context.checkForExceptions();
|
||||
decQuadQuantize(&rc.dec, &rc.dec, &c1.dec, &context);
|
||||
return rc;
|
||||
}
|
||||
|
||||
DecimalFixed DecimalFixed::sub(DecimalStatus decSt, DecimalFixed op2) const
|
||||
{
|
||||
DecimalContext context(this, decSt);
|
||||
DecimalFixed rc;
|
||||
decQuadSubtract(&rc.dec, &dec, &op2.dec, &context);
|
||||
context.checkForExceptions();
|
||||
decQuadQuantize(&rc.dec, &rc.dec, &c1.dec, &context);
|
||||
return rc;
|
||||
}
|
||||
|
||||
DecimalFixed DecimalFixed::mul(DecimalStatus decSt, DecimalFixed op2) const
|
||||
{
|
||||
DecimalContext context(this, decSt);
|
||||
DecimalFixed rc;
|
||||
decQuadMultiply(&rc.dec, &dec, &op2.dec, &context);
|
||||
context.checkForExceptions();
|
||||
decQuadQuantize(&rc.dec, &rc.dec, &c1.dec, &context);
|
||||
return rc;
|
||||
}
|
||||
|
||||
Decimal128 Decimal128::div(DecimalStatus decSt, Decimal128 op2) const
|
||||
{
|
||||
DecimalContext context(this, decSt);
|
||||
@ -967,27 +810,6 @@ Decimal128 Decimal128::div(DecimalStatus decSt, Decimal128 op2) const
|
||||
return rc;
|
||||
}
|
||||
|
||||
DecimalFixed DecimalFixed::div(DecimalStatus decSt, DecimalFixed op2, int scale) const
|
||||
{
|
||||
DecimalContext context(this, decSt);
|
||||
DecimalFixed rc;
|
||||
|
||||
// first divide with full decfloat precision
|
||||
decQuadDivide(&rc.dec, &dec, &op2.dec, &context);
|
||||
|
||||
// next re-scale & int-ize
|
||||
rc.exactInt(decSt, scale);
|
||||
return rc;
|
||||
}
|
||||
|
||||
DecimalFixed DecimalFixed::mod(DecimalStatus decSt, DecimalFixed op2) const
|
||||
{
|
||||
DecimalContext context(this, decSt);
|
||||
DecimalFixed rc;
|
||||
decQuadRemainder(&rc.dec, &dec, &op2.dec, &context);
|
||||
return rc;
|
||||
}
|
||||
|
||||
Decimal128 Decimal128::fma(DecimalStatus decSt, Decimal128 op2, Decimal128 op3) const
|
||||
{
|
||||
DecimalContext context(this, decSt);
|
||||
@ -1049,7 +871,7 @@ Decimal128 Decimal128::log10(DecimalStatus decSt) const
|
||||
return rc;
|
||||
}
|
||||
|
||||
void Decimal128Base::makeKey(ULONG* key) const
|
||||
void Decimal128::makeKey(ULONG* key) const
|
||||
{
|
||||
unsigned char coeff[DECQUAD_Pmax];
|
||||
int sign = decQuadGetCoefficient(&dec, coeff);
|
||||
@ -1058,7 +880,7 @@ void Decimal128Base::makeKey(ULONG* key) const
|
||||
make(key, DECQUAD_Pmax, DECQUAD_Bias, sizeof(dec), coeff, sign, exp);
|
||||
}
|
||||
|
||||
void Decimal128Base::grabKey(ULONG* key)
|
||||
void Decimal128::grabKey(ULONG* key)
|
||||
{
|
||||
int exp, sign;
|
||||
unsigned char bcd[DECQUAD_Pmax];
|
||||
@ -1068,12 +890,12 @@ void Decimal128Base::grabKey(ULONG* key)
|
||||
decQuadFromBCD(&dec, exp, bcd, sign);
|
||||
}
|
||||
|
||||
ULONG Decimal128Base::getIndexKeyLength()
|
||||
ULONG Decimal128::getIndexKeyLength()
|
||||
{
|
||||
return 17;
|
||||
}
|
||||
|
||||
ULONG Decimal128Base::makeIndexKey(vary* buf)
|
||||
ULONG Decimal128::makeIndexKey(vary* buf)
|
||||
{
|
||||
unsigned char coeff[DECQUAD_Pmax + 2];
|
||||
int sign = decQuadGetCoefficient(&dec, coeff);
|
||||
@ -1207,4 +1029,9 @@ short Decimal128::decCompare(Decimal128 op2) const
|
||||
return 3;
|
||||
}
|
||||
|
||||
void Decimal128::getBcd(BCD* bcd) const
|
||||
{
|
||||
bcd->sign = decQuadToBCD(&dec, &bcd->exp, bcd->bcd);
|
||||
}
|
||||
|
||||
} // namespace Firebird
|
||||
|
@ -115,27 +115,27 @@ struct DecimalStatus
|
||||
USHORT decExtFlag, roundingMode;
|
||||
};
|
||||
|
||||
struct DecimalBinding
|
||||
struct NumericBinding
|
||||
{
|
||||
enum Bind
|
||||
{
|
||||
DEC_NATIVE,
|
||||
DEC_TEXT,
|
||||
DEC_DOUBLE,
|
||||
DEC_NUMERIC
|
||||
NUM_NATIVE,
|
||||
NUM_TEXT,
|
||||
NUM_DOUBLE,
|
||||
NUM_INT64
|
||||
};
|
||||
|
||||
DecimalBinding()
|
||||
: bind(DEC_NATIVE),
|
||||
NumericBinding()
|
||||
: bind(NUM_NATIVE),
|
||||
numScale(0)
|
||||
{}
|
||||
|
||||
DecimalBinding(Bind aBind, SCHAR aNumScale = 0)
|
||||
NumericBinding(Bind aBind, SCHAR aNumScale = 0)
|
||||
: bind(aBind),
|
||||
numScale(aNumScale)
|
||||
{}
|
||||
|
||||
static const DecimalBinding DEFAULT;
|
||||
static const NumericBinding DEFAULT;
|
||||
static const SCHAR MAX_SCALE = 18;
|
||||
|
||||
Bind bind;
|
||||
@ -143,13 +143,11 @@ struct DecimalBinding
|
||||
};
|
||||
|
||||
|
||||
class DecimalFixed;
|
||||
class Int128;
|
||||
|
||||
class Decimal64
|
||||
{
|
||||
friend class Decimal128;
|
||||
friend class DecimalFixed;
|
||||
friend class Decimal128Base;
|
||||
|
||||
public:
|
||||
#if SIZEOF_LONG < 8
|
||||
@ -159,7 +157,7 @@ public:
|
||||
Decimal64 set(SINT64 value, DecimalStatus decSt, int scale);
|
||||
Decimal64 set(const char* value, DecimalStatus decSt);
|
||||
Decimal64 set(double value, DecimalStatus decSt);
|
||||
Decimal64 set(DecimalFixed value, DecimalStatus decSt, int scale);
|
||||
Decimal64 set(Int128 value, DecimalStatus decSt, int scale);
|
||||
|
||||
UCHAR* getBytes();
|
||||
Decimal64 abs() const;
|
||||
@ -193,38 +191,7 @@ private:
|
||||
decDouble dec;
|
||||
};
|
||||
|
||||
class Decimal128Base
|
||||
{
|
||||
friend class Decimal128;
|
||||
friend class DecimalFixed;
|
||||
|
||||
public:
|
||||
double toDouble(DecimalStatus decSt) const;
|
||||
Decimal64 toDecimal64(DecimalStatus decSt) const;
|
||||
|
||||
UCHAR* getBytes();
|
||||
int compare(DecimalStatus decSt, Decimal128Base tgt) const;
|
||||
|
||||
void setScale(DecimalStatus decSt, int scale);
|
||||
|
||||
bool isInf() const;
|
||||
bool isNan() const;
|
||||
int sign() const;
|
||||
|
||||
void makeKey(ULONG* key) const;
|
||||
void grabKey(ULONG* key);
|
||||
static ULONG getIndexKeyLength();
|
||||
ULONG makeIndexKey(vary* buf);
|
||||
|
||||
#ifdef DEV_BUILD
|
||||
int show();
|
||||
#endif
|
||||
|
||||
private:
|
||||
decQuad dec;
|
||||
};
|
||||
|
||||
class Decimal128 : public Decimal128Base
|
||||
class Decimal128
|
||||
{
|
||||
friend class Decimal64;
|
||||
|
||||
@ -237,7 +204,7 @@ public:
|
||||
Decimal128 set(SINT64 value, DecimalStatus decSt, int scale);
|
||||
Decimal128 set(const char* value, DecimalStatus decSt);
|
||||
Decimal128 set(double value, DecimalStatus decSt);
|
||||
Decimal128 set(DecimalFixed value, DecimalStatus decSt, int scale);
|
||||
Decimal128 set(Int128 value, DecimalStatus decSt, int scale);
|
||||
|
||||
Decimal128 operator=(Decimal64 d64);
|
||||
|
||||
@ -265,12 +232,37 @@ public:
|
||||
short totalOrder(Decimal128 op2) const;
|
||||
short decCompare(Decimal128 op2) const;
|
||||
|
||||
private:
|
||||
Decimal128 operator=(Decimal128Base d128b)
|
||||
double toDouble(DecimalStatus decSt) const;
|
||||
Decimal64 toDecimal64(DecimalStatus decSt) const;
|
||||
|
||||
UCHAR* getBytes();
|
||||
int compare(DecimalStatus decSt, Decimal128 tgt) const;
|
||||
|
||||
void setScale(DecimalStatus decSt, int scale);
|
||||
|
||||
bool isInf() const;
|
||||
bool isNan() const;
|
||||
int sign() const;
|
||||
|
||||
void makeKey(ULONG* key) const;
|
||||
void grabKey(ULONG* key);
|
||||
static ULONG getIndexKeyLength();
|
||||
ULONG makeIndexKey(vary* buf);
|
||||
|
||||
#ifdef DEV_BUILD
|
||||
int show();
|
||||
#endif
|
||||
|
||||
struct BCD
|
||||
{
|
||||
memcpy(&dec, &d128b.dec, sizeof(dec));
|
||||
return *this;
|
||||
}
|
||||
int sign, exp;
|
||||
unsigned char bcd[DECQUAD_Pmax];
|
||||
};
|
||||
|
||||
void getBcd(BCD* bcd) const;
|
||||
|
||||
private:
|
||||
decQuad dec;
|
||||
};
|
||||
|
||||
class CDecimal128 : public Decimal128
|
||||
@ -290,45 +282,11 @@ public:
|
||||
{
|
||||
set(value, DecimalStatus(0), 0);
|
||||
}
|
||||
};
|
||||
|
||||
class DecimalFixed : public Decimal128Base
|
||||
{
|
||||
public:
|
||||
#if SIZEOF_LONG < 8
|
||||
DecimalFixed set(int value)
|
||||
CDecimal128(const char* value, DecimalStatus decSt)
|
||||
{
|
||||
return set(SLONG(value));
|
||||
set(value, decSt);
|
||||
}
|
||||
#endif
|
||||
DecimalFixed set(SLONG value);
|
||||
DecimalFixed set(SINT64 value);
|
||||
DecimalFixed set(const char* value, int scale, DecimalStatus decSt);
|
||||
DecimalFixed set(double value, int scale, DecimalStatus decSt);
|
||||
|
||||
int toInteger(DecimalStatus decSt) const;
|
||||
SINT64 toInt64(DecimalStatus decSt) const;
|
||||
void toString(DecimalStatus decSt, int scale, unsigned length, char* to) const;
|
||||
void toString(DecimalStatus decSt, int scale, string& to) const;
|
||||
|
||||
DecimalFixed abs() const;
|
||||
DecimalFixed neg() const;
|
||||
DecimalFixed add(DecimalStatus decSt, DecimalFixed op2) const;
|
||||
DecimalFixed sub(DecimalStatus decSt, DecimalFixed op2) const;
|
||||
DecimalFixed mul(DecimalStatus decSt, DecimalFixed op2) const;
|
||||
DecimalFixed div(DecimalStatus decSt, DecimalFixed op2, int scale) const;
|
||||
DecimalFixed mod(DecimalStatus decSt, DecimalFixed op2) const;
|
||||
|
||||
DecimalFixed operator=(Decimal128Base d128b)
|
||||
{
|
||||
memcpy(&dec, &d128b.dec, sizeof(dec));
|
||||
return *this;
|
||||
}
|
||||
|
||||
void exactInt(DecimalStatus decSt, int scale); // rescale & make it integer after conversions
|
||||
|
||||
private:
|
||||
Decimal128 scaled128(DecimalStatus decSt, int scale) const;
|
||||
};
|
||||
|
||||
} // namespace Firebird
|
||||
|
492
src/common/Int128.cpp
Normal file
492
src/common/Int128.cpp
Normal file
@ -0,0 +1,492 @@
|
||||
/*
|
||||
* PROGRAM: Integer 128 type.
|
||||
* MODULE: Int128.cpp
|
||||
* DESCRIPTION: Big integer support.
|
||||
*
|
||||
* The contents of this file are subject to the Initial
|
||||
* Developer's Public License Version 1.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.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
|
||||
*
|
||||
* Software distributed under the License is distributed AS IS,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing rights
|
||||
* and limitations under the License.
|
||||
*
|
||||
* The Original Code was created by Alex Peshkov
|
||||
* for the Firebird Open Source RDBMS project.
|
||||
*
|
||||
* Copyright (c) 2019 Alex Peshkov <peshkoff at mail dot ru>
|
||||
* and all contributors signed below.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "firebird.h"
|
||||
#include "Int128.h"
|
||||
|
||||
#include "StatusArg.h"
|
||||
#include "gen/iberror.h"
|
||||
#include "status.h"
|
||||
#include "DecFloat.h"
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <float.h>
|
||||
|
||||
using namespace Firebird;
|
||||
|
||||
namespace {
|
||||
|
||||
const CInt128 i64max(MAX_SINT64), i64min(MIN_SINT64);
|
||||
const double p2_32 = 4294967296.0;
|
||||
const I128limit i128limit;
|
||||
const CInt128 minus1(-1);
|
||||
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
|
||||
namespace Firebird {
|
||||
|
||||
Int128 Int128::set(SLONG value, int scale)
|
||||
{
|
||||
v = value;
|
||||
setScale(scale);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Int128 Int128::set(SINT64 value, int scale)
|
||||
{
|
||||
#ifdef TTMATH_PLATFORM32
|
||||
v = ttmath::slint(value);
|
||||
#else
|
||||
v = ttmath::sint(value);
|
||||
#endif
|
||||
setScale(scale);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Int128 Int128::set(const char* value)
|
||||
{
|
||||
// This is simplified method - it does not perform all what's needed for CVT_decompose
|
||||
v.FromString(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Int128 Int128::set(double value)
|
||||
{
|
||||
bool sgn = false;
|
||||
if (value < 0.0)
|
||||
{
|
||||
value = -value;
|
||||
sgn = true;
|
||||
}
|
||||
|
||||
double parts[4];
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
parts[i] = value;
|
||||
value /= p2_32;
|
||||
}
|
||||
fb_assert(value < 1.0);
|
||||
|
||||
unsigned dwords[4];
|
||||
value = 0.0;
|
||||
for (int i = 4; i--;)
|
||||
{
|
||||
dwords[i] = (parts[i] - value);
|
||||
value += p2_32 * dwords[i];
|
||||
}
|
||||
|
||||
setTable32(dwords);
|
||||
if (sgn)
|
||||
v.ChangeSign();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Int128 Int128::set(DecimalStatus decSt, Decimal128 value)
|
||||
{
|
||||
static CDecimal128 quant(1);
|
||||
value = value.quantize(decSt, quant);
|
||||
|
||||
Decimal128::BCD bcd;
|
||||
value.getBcd(&bcd);
|
||||
fb_assert(bcd.exp == 0);
|
||||
|
||||
v.SetZero();
|
||||
for (unsigned b = 0; b < sizeof(bcd.bcd); ++b)
|
||||
{
|
||||
v.MulInt(10);
|
||||
v.AddInt(bcd.bcd[b]);
|
||||
}
|
||||
if (bcd.sign < 0)
|
||||
v.ChangeSign();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Int128::setScale(int scale)
|
||||
{
|
||||
if (scale > 0)
|
||||
{
|
||||
ttmath::sint rem = 0;
|
||||
while (scale--)
|
||||
v.DivInt(10, scale == 0 ? &rem : nullptr);
|
||||
|
||||
if (rem > 4)
|
||||
v++;
|
||||
else if (rem < -4)
|
||||
v--;
|
||||
}
|
||||
else if (scale < 0)
|
||||
{
|
||||
while (scale++) {
|
||||
if (v > i128limit.v || v < -i128limit.v)
|
||||
(Arg::Gds(isc_arith_except) << Arg::Gds(isc_numeric_out_of_range)).raise();
|
||||
v.MulInt(10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int Int128::toInteger(int scale) const
|
||||
{
|
||||
Int128 tmp(*this);
|
||||
tmp.setScale(scale);
|
||||
int rc;
|
||||
if (tmp.v.ToInt(rc))
|
||||
overflow();
|
||||
return rc;
|
||||
}
|
||||
|
||||
void Int128::toString(int scale, unsigned length, char* to) const
|
||||
{
|
||||
string buffer;
|
||||
toString(scale, buffer);
|
||||
if (buffer.length() + 1 > length)
|
||||
{
|
||||
(Arg::Gds(isc_arith_except) << Arg::Gds(isc_string_truncation) <<
|
||||
Arg::Gds(isc_trunc_limits) << Arg::Num(length) << Arg::Num(buffer.length() + 1)).raise();
|
||||
}
|
||||
buffer.copyTo(to, length);
|
||||
}
|
||||
|
||||
void Int128::toString(int scale, string& to) const
|
||||
{
|
||||
v.ToStringBase(to);
|
||||
bool sgn = to[0] == '-';
|
||||
if (sgn)
|
||||
to.erase(0, 1);
|
||||
|
||||
if (scale)
|
||||
{
|
||||
if (scale < -38 || scale > 4)
|
||||
{
|
||||
string tmp;
|
||||
tmp.printf("E%d", scale);
|
||||
to += tmp;
|
||||
}
|
||||
else if (scale > 0)
|
||||
{
|
||||
string tmp(scale, '0');
|
||||
to += tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned posScale = -scale;
|
||||
if (posScale > to.length())
|
||||
{
|
||||
string tmp(posScale - to.length(), '0');
|
||||
to.insert(0, tmp);
|
||||
}
|
||||
if (posScale == to.length())
|
||||
{
|
||||
to.insert(0, "0.");
|
||||
}
|
||||
else
|
||||
to.insert(to.length() - posScale, ".");
|
||||
}
|
||||
}
|
||||
|
||||
if (sgn)
|
||||
to.insert(0, "-");
|
||||
}
|
||||
|
||||
SINT64 Int128::toInt64(int scale) const
|
||||
{
|
||||
Int128 tmp(*this);
|
||||
tmp.setScale(scale);
|
||||
if (tmp.v < i64min.v || tmp.v > i64max.v)
|
||||
overflow();
|
||||
|
||||
unsigned dwords[4];
|
||||
tmp.getTable32(dwords);
|
||||
SINT64 rc = int(dwords[1]);
|
||||
rc <<= 32;
|
||||
rc += dwords[0];
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
double Int128::toDouble() const
|
||||
{
|
||||
unsigned dwords[4];
|
||||
getTable32(dwords);
|
||||
double rc = int(dwords[3]);
|
||||
for (int i = 3; i--;)
|
||||
{
|
||||
rc *= p2_32;
|
||||
rc += dwords[i];
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int Int128::compare(Int128 tgt) const
|
||||
{
|
||||
return v < tgt.v ? -1 : v > tgt.v ? 1 : 0;
|
||||
}
|
||||
|
||||
Int128 Int128::abs() const
|
||||
{
|
||||
Int128 rc(*this);
|
||||
if (rc.v.Abs())
|
||||
overflow();
|
||||
return rc;
|
||||
}
|
||||
|
||||
Int128 Int128::neg() const
|
||||
{
|
||||
Int128 rc(*this);
|
||||
if (rc.v.ChangeSign())
|
||||
overflow();
|
||||
return rc;
|
||||
}
|
||||
|
||||
Int128 Int128::add(Int128 op2) const
|
||||
{
|
||||
Int128 rc(*this);
|
||||
if (rc.v.Add(op2.v))
|
||||
overflow();
|
||||
return rc;
|
||||
}
|
||||
|
||||
Int128 Int128::sub(Int128 op2) const
|
||||
{
|
||||
Int128 rc(*this);
|
||||
if (rc.v.Sub(op2.v))
|
||||
overflow();
|
||||
return rc;
|
||||
}
|
||||
|
||||
Int128 Int128::mul(Int128 op2) const
|
||||
{
|
||||
Int128 rc(*this);
|
||||
if (rc.v.Mul(op2.v))
|
||||
overflow();
|
||||
return rc;
|
||||
}
|
||||
|
||||
Int128 Int128::div(Int128 op2, int scale) const
|
||||
{
|
||||
if (compare(MIN_Int128) == 0 && op2.compare(minus1) == 0)
|
||||
Arg::Gds(isc_exception_integer_overflow).raise();
|
||||
|
||||
static const CInt128 MIN_BY10(MIN_Int128 / 10);
|
||||
static const CInt128 MAX_BY10(MAX_Int128 / 10);
|
||||
|
||||
// Scale op1 by as many of the needed powers of 10 as possible without an overflow.
|
||||
CInt128 op1(*this);
|
||||
int sign1 = op1.sign();
|
||||
while ((scale < 0) && (sign1 >= 0 ? op1.compare(MAX_BY10) <= 0 : op1.compare(MIN_BY10) >= 0))
|
||||
{
|
||||
op1 *= 10;
|
||||
++scale;
|
||||
}
|
||||
|
||||
// Scale op2 shifting it to the right as long as only zeroes are thrown away.
|
||||
CInt128 tmp(op2);
|
||||
while (scale < 0)
|
||||
{
|
||||
ttmath::sint rem = 0;
|
||||
tmp.v.DivInt(10, &rem);
|
||||
if (rem)
|
||||
break;
|
||||
op2 = tmp;
|
||||
++scale;
|
||||
}
|
||||
|
||||
if (op1.v.Div(op2.v))
|
||||
zerodivide();
|
||||
|
||||
op1.setScale(scale);
|
||||
return op1;
|
||||
}
|
||||
|
||||
Int128 Int128::mod(Int128 op2) const
|
||||
{
|
||||
Int128 tmp(*this);
|
||||
Int128 rc;
|
||||
if (tmp.v.Div(op2.v, rc.v))
|
||||
zerodivide();
|
||||
return rc;
|
||||
}
|
||||
|
||||
int Int128::sign() const
|
||||
{
|
||||
return v.IsSign() ? -1 : v.IsZero() ? 0 : 1;
|
||||
}
|
||||
|
||||
UCHAR* Int128::getBytes()
|
||||
{
|
||||
return (UCHAR*)(v.table);
|
||||
}
|
||||
|
||||
void Int128::getTable32(unsigned* dwords) const
|
||||
{
|
||||
static_assert((sizeof(v.table[0]) == 4) || (sizeof(v.table[0]) == 8),
|
||||
"Unsupported size of integer in ttmath");
|
||||
|
||||
if (sizeof(v.table[0]) == 4)
|
||||
{
|
||||
for (int i = 0; i < 4; ++i)
|
||||
dwords[i] = v.table[i];
|
||||
}
|
||||
else if (sizeof(v.table[0]) == 8)
|
||||
{
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
dwords[i * 2] = v.table[i] & 0xFFFFFFFF;
|
||||
dwords[i * 2 + 1] = (v.table[i] >> 32) & 0xFFFFFFFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Int128::setTable32(const unsigned* dwords)
|
||||
{
|
||||
static_assert((sizeof(v.table[0]) == 4) || (sizeof(v.table[0]) == 8),
|
||||
"Unsupported size of integer in ttmath");
|
||||
|
||||
if (sizeof(v.table[0]) == 4)
|
||||
{
|
||||
for (int i = 0; i < 4; ++i)
|
||||
v.table[i] = dwords[i];
|
||||
}
|
||||
else if (sizeof(v.table[0]) == 8)
|
||||
{
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
v.table[i] = dwords[i * 2 + 1];
|
||||
v.table[i] <<= 32;
|
||||
v.table[i] += dwords[i * 2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Int128 Int128::operator&=(FB_UINT64 mask)
|
||||
{
|
||||
v.table[0] &= mask;
|
||||
unsigned i = 1;
|
||||
if (sizeof(v.table[0]) == 4)
|
||||
{
|
||||
i = 2;
|
||||
v.table[1] &= (mask >> 32);
|
||||
}
|
||||
|
||||
for (; i < FB_NELEM(v.table); ++i)
|
||||
v.table[i] = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Int128 Int128::operator&=(ULONG mask)
|
||||
{
|
||||
v.table[0] &= mask;
|
||||
|
||||
for (unsigned i = 1; i < FB_NELEM(v.table); ++i)
|
||||
v.table[i] = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Int128 Int128::operator/(unsigned value) const
|
||||
{
|
||||
Int128 rc;
|
||||
rc.v.DivInt(value);
|
||||
return rc;
|
||||
}
|
||||
|
||||
Int128 Int128::operator-() const
|
||||
{
|
||||
return neg();
|
||||
}
|
||||
|
||||
Int128 Int128::operator+=(unsigned value)
|
||||
{
|
||||
v.AddInt(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Int128 Int128::operator*=(unsigned value)
|
||||
{
|
||||
v.MulInt(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool Int128::operator>(Int128 value) const
|
||||
{
|
||||
return v > value.v;
|
||||
}
|
||||
|
||||
bool Int128::operator==(Int128 value) const
|
||||
{
|
||||
return v == value.v;
|
||||
}
|
||||
|
||||
void Int128::zerodivide()
|
||||
{
|
||||
(Arg::Gds(isc_arith_except) << Arg::Gds(isc_exception_integer_divide_by_zero)).raise();
|
||||
}
|
||||
|
||||
void Int128::overflow()
|
||||
{
|
||||
(Arg::Gds(isc_arith_except) << Arg::Gds(isc_exception_integer_overflow)).raise();
|
||||
}
|
||||
|
||||
#ifdef DEV_BUILD
|
||||
const char* Int128::show()
|
||||
{
|
||||
static char to[64];
|
||||
toString(0, sizeof(to), to);
|
||||
return to;
|
||||
}
|
||||
#endif
|
||||
|
||||
CInt128::CInt128(SINT64 value)
|
||||
{
|
||||
set(value, 0);
|
||||
}
|
||||
|
||||
CInt128::CInt128(minmax mm)
|
||||
{
|
||||
switch(mm)
|
||||
{
|
||||
case MkMax:
|
||||
v.SetMax();
|
||||
break;
|
||||
case MkMin:
|
||||
v.SetMin();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CInt128 MIN_Int128(CInt128::MkMin);
|
||||
CInt128 MAX_Int128(CInt128::MkMax);
|
||||
|
||||
} // namespace Firebird
|
147
src/common/Int128.h
Normal file
147
src/common/Int128.h
Normal file
@ -0,0 +1,147 @@
|
||||
/*
|
||||
* PROGRAM: Integer 128 type.
|
||||
* MODULE: Int128.h
|
||||
* DESCRIPTION: Big integer support.
|
||||
*
|
||||
* The contents of this file are subject to the Initial
|
||||
* Developer's Public License Version 1.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.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
|
||||
*
|
||||
* Software distributed under the License is distributed AS IS,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing rights
|
||||
* and limitations under the License.
|
||||
*
|
||||
* The Original Code was created by Alex Peshkov
|
||||
* for the Firebird Open Source RDBMS project.
|
||||
*
|
||||
* Copyright (c) 2019 Alex Peshkov <peshkoff at mail dot ru>
|
||||
* and all contributors signed below.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef FB_INT128
|
||||
#define FB_INT128
|
||||
|
||||
#include "firebird/Interface.h"
|
||||
#include "fb_exception.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "classes/fb_string.h"
|
||||
#include "classes/MetaName.h"
|
||||
|
||||
#include "../../extern/ttmath/ttmath.h"
|
||||
|
||||
namespace Firebird {
|
||||
|
||||
class Decimal64;
|
||||
class Decimal128;
|
||||
struct DecimalStatus;
|
||||
|
||||
class Int128 //: public Decimal128Base
|
||||
{
|
||||
public:
|
||||
#if SIZEOF_LONG < 8
|
||||
Int128 set(int value)
|
||||
{
|
||||
return set(SLONG(value));
|
||||
}
|
||||
#endif
|
||||
Int128 set(SLONG value, int scale);
|
||||
Int128 set(SINT64 value, int scale);
|
||||
Int128 set(double value);
|
||||
Int128 set(DecimalStatus decSt, Decimal128 value);
|
||||
Int128 set(Int128 value)
|
||||
{
|
||||
v = value.v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Int128 operator=(SINT64 value)
|
||||
{
|
||||
set(value, 0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#ifdef DEV_BUILD
|
||||
const char* show();
|
||||
#endif
|
||||
|
||||
int toInteger(int scale) const;
|
||||
SINT64 toInt64(int scale) const;
|
||||
void toString(int scale, unsigned length, char* to) const;
|
||||
void toString(int scale, string& to) const;
|
||||
double toDouble() const;
|
||||
|
||||
Int128 operator&=(FB_UINT64 mask);
|
||||
Int128 operator&=(ULONG mask);
|
||||
Int128 operator-() const;
|
||||
Int128 operator/(unsigned value) const;
|
||||
Int128 operator+=(unsigned value);
|
||||
Int128 operator*=(unsigned value);
|
||||
|
||||
int compare(Int128 tgt) const;
|
||||
bool operator>(Int128 value) const;
|
||||
bool operator==(Int128 value) const;
|
||||
int sign() const;
|
||||
|
||||
Int128 abs() const;
|
||||
Int128 neg() const;
|
||||
Int128 add(Int128 op2) const;
|
||||
Int128 sub(Int128 op2) const;
|
||||
Int128 mul(Int128 op2) const;
|
||||
Int128 div(Int128 op2, int scale) const;
|
||||
Int128 mod(Int128 op2) const;
|
||||
|
||||
void getTable32(unsigned* dwords) const; // internal data in per-32bit form
|
||||
void setTable32(const unsigned* dwords);
|
||||
void setScale(int scale);
|
||||
UCHAR* getBytes();
|
||||
|
||||
protected:
|
||||
ttmath::Int<TTMATH_BITS(128)> v;
|
||||
|
||||
static void overflow();
|
||||
static void zerodivide();
|
||||
|
||||
Int128 set(const char* value);
|
||||
};
|
||||
|
||||
class CInt128 : public Int128
|
||||
{
|
||||
public:
|
||||
enum minmax {MkMax, MkMin};
|
||||
|
||||
CInt128(SINT64 value);
|
||||
CInt128(minmax mm);
|
||||
CInt128(const Int128& value)
|
||||
{
|
||||
set(value);
|
||||
}
|
||||
};
|
||||
|
||||
extern CInt128 MAX_Int128, MIN_Int128;
|
||||
|
||||
class I128limit : public Int128
|
||||
{
|
||||
public:
|
||||
I128limit()
|
||||
{
|
||||
v.SetOne();
|
||||
for (int i = 0; i < 126; ++i)
|
||||
v.MulInt(2);
|
||||
v.DivInt(5);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Firebird
|
||||
|
||||
|
||||
#endif // FB_INT128
|
@ -192,9 +192,9 @@ MetadataFromBlr::MetadataFromBlr(unsigned aBlrLength, const unsigned char* aBlr,
|
||||
item->length = sizeof(Decimal128);
|
||||
break;
|
||||
|
||||
case blr_dec_fixed:
|
||||
item->type = SQL_DEC_FIXED;
|
||||
item->length = sizeof(DecimalFixed);
|
||||
case blr_int128:
|
||||
item->type = SQL_INT128;
|
||||
item->length = sizeof(Int128);
|
||||
item->scale = rdr.getByte();
|
||||
break;
|
||||
|
||||
|
@ -504,7 +504,10 @@ namespace Firebird
|
||||
memset(baseInsert(p0, n), c, n);
|
||||
return *this;
|
||||
}
|
||||
// iterator insert(iterator it, char_type c); // what to return here?
|
||||
void insert(iterator it, char_type c)
|
||||
{
|
||||
insert(it - c_str(), 1, c);
|
||||
}
|
||||
void insert(iterator it, size_type n, char_type c)
|
||||
{
|
||||
insert(it - c_str(), n, c);
|
||||
@ -519,6 +522,11 @@ namespace Firebird
|
||||
baseErase(p0, n);
|
||||
return *this;
|
||||
}
|
||||
AbstractString& clear() throw()
|
||||
{
|
||||
erase();
|
||||
return *this;
|
||||
}
|
||||
iterator erase(iterator it) throw()
|
||||
{
|
||||
erase(it - c_str(), 1);
|
||||
|
@ -133,7 +133,7 @@ static void datetime_to_text(const dsc*, dsc*, Callbacks*);
|
||||
static void float_to_text(const dsc*, dsc*, Callbacks*);
|
||||
static void decimal_float_to_text(const dsc*, dsc*, DecimalStatus, Callbacks*);
|
||||
static void integer_to_text(const dsc*, dsc*, Callbacks*);
|
||||
static SINT64 hex_to_value(const char*& string, const char* end);
|
||||
static void int128_to_text(const dsc*, dsc*, Callbacks* cb);
|
||||
static void localError(const Firebird::Arg::StatusVector&);
|
||||
|
||||
class DummyException {};
|
||||
@ -305,7 +305,35 @@ static void decimal_float_to_text(const dsc* from, dsc* to, DecimalStatus decSt,
|
||||
else if (from->dsc_dtype == dtype_dec128)
|
||||
((Decimal128*) from->dsc_address)->toString(decSt, sizeof(temp), temp);
|
||||
else
|
||||
((DecimalFixed*) from->dsc_address)->toString(decSt, from->dsc_scale, sizeof(temp), temp);
|
||||
fb_assert(false);
|
||||
}
|
||||
catch (const Exception& ex)
|
||||
{
|
||||
// reraise using function passed in callbacks
|
||||
Arg::StatusVector v(ex);
|
||||
cb->err(v);
|
||||
}
|
||||
|
||||
dsc intermediate;
|
||||
intermediate.dsc_dtype = dtype_text;
|
||||
intermediate.dsc_ttype() = ttype_ascii;
|
||||
intermediate.dsc_address = reinterpret_cast<UCHAR*>(temp);
|
||||
intermediate.dsc_length = strlen(temp);
|
||||
|
||||
CVT_move_common(&intermediate, to, 0, cb);
|
||||
}
|
||||
|
||||
|
||||
static void int128_to_text(const dsc* from, dsc* to, Callbacks* cb)
|
||||
{
|
||||
char temp[50];
|
||||
|
||||
try
|
||||
{
|
||||
if (from->dsc_dtype == dtype_int128)
|
||||
((Int128*) from->dsc_address)->toString(from->dsc_scale, sizeof(temp), temp);
|
||||
else
|
||||
fb_assert(false);
|
||||
}
|
||||
catch (const Exception& ex)
|
||||
{
|
||||
@ -1070,9 +1098,8 @@ SLONG CVT_get_long(const dsc* desc, SSHORT scale, DecimalStatus decSt, ErrorFunc
|
||||
|
||||
return d128.toInteger(decSt, scale);
|
||||
|
||||
case dtype_dec_fixed:
|
||||
value = ((DecimalFixed*) p)->toInteger(decSt);
|
||||
break;
|
||||
case dtype_int128:
|
||||
return ((Int128*) p)->toInteger(scale);
|
||||
|
||||
case dtype_real:
|
||||
case dtype_double:
|
||||
@ -1121,7 +1148,7 @@ SLONG CVT_get_long(const dsc* desc, SSHORT scale, DecimalStatus decSt, ErrorFunc
|
||||
{
|
||||
USHORT length =
|
||||
CVT_make_string(desc, ttype_ascii, &p, &buffer, sizeof(buffer), decSt, err);
|
||||
scale -= CVT_decompose(p, length, dtype_long, &value, err);
|
||||
scale -= CVT_decompose(p, length, &value, err);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1274,8 +1301,8 @@ double CVT_get_double(const dsc* desc, DecimalStatus decSt, ErrorFunction err, b
|
||||
return d128.toDouble(decSt);
|
||||
}
|
||||
|
||||
case dtype_dec_fixed:
|
||||
value = ((DecimalFixed*) desc->dsc_address)->toDouble(decSt);
|
||||
case dtype_int128:
|
||||
value = ((Int128*) desc->dsc_address)->toDouble();
|
||||
break;
|
||||
|
||||
case dtype_varying:
|
||||
@ -1578,7 +1605,7 @@ void CVT_move_common(const dsc* from, dsc* to, DecimalStatus decSt, Callbacks* c
|
||||
case dtype_boolean:
|
||||
case dtype_dec64:
|
||||
case dtype_dec128:
|
||||
case dtype_dec_fixed:
|
||||
case dtype_int128:
|
||||
CVT_conversion_error(from, cb->err);
|
||||
break;
|
||||
}
|
||||
@ -1629,7 +1656,7 @@ void CVT_move_common(const dsc* from, dsc* to, DecimalStatus decSt, Callbacks* c
|
||||
case dtype_boolean:
|
||||
case dtype_dec64:
|
||||
case dtype_dec128:
|
||||
case dtype_dec_fixed:
|
||||
case dtype_int128:
|
||||
CVT_conversion_error(from, cb->err);
|
||||
break;
|
||||
}
|
||||
@ -1671,7 +1698,7 @@ void CVT_move_common(const dsc* from, dsc* to, DecimalStatus decSt, Callbacks* c
|
||||
case dtype_boolean:
|
||||
case dtype_dec64:
|
||||
case dtype_dec128:
|
||||
case dtype_dec_fixed:
|
||||
case dtype_int128:
|
||||
CVT_conversion_error(from, cb->err);
|
||||
break;
|
||||
}
|
||||
@ -1716,7 +1743,7 @@ void CVT_move_common(const dsc* from, dsc* to, DecimalStatus decSt, Callbacks* c
|
||||
case dtype_boolean:
|
||||
case dtype_dec64:
|
||||
case dtype_dec128:
|
||||
case dtype_dec_fixed:
|
||||
case dtype_int128:
|
||||
CVT_conversion_error(from, cb->err);
|
||||
break;
|
||||
}
|
||||
@ -1763,7 +1790,7 @@ void CVT_move_common(const dsc* from, dsc* to, DecimalStatus decSt, Callbacks* c
|
||||
case dtype_boolean:
|
||||
case dtype_dec64:
|
||||
case dtype_dec128:
|
||||
case dtype_dec_fixed:
|
||||
case dtype_int128:
|
||||
CVT_conversion_error(from, cb->err);
|
||||
break;
|
||||
}
|
||||
@ -1946,6 +1973,10 @@ void CVT_move_common(const dsc* from, dsc* to, DecimalStatus decSt, Callbacks* c
|
||||
integer_to_text(from, to, cb);
|
||||
return;
|
||||
|
||||
case dtype_int128:
|
||||
int128_to_text(from, to, cb);
|
||||
return;
|
||||
|
||||
case dtype_real:
|
||||
case dtype_double:
|
||||
float_to_text(from, to, cb);
|
||||
@ -1953,7 +1984,6 @@ void CVT_move_common(const dsc* from, dsc* to, DecimalStatus decSt, Callbacks* c
|
||||
|
||||
case dtype_dec64:
|
||||
case dtype_dec128:
|
||||
case dtype_dec_fixed:
|
||||
decimal_float_to_text(from, to, decSt, cb);
|
||||
return;
|
||||
|
||||
@ -2082,8 +2112,8 @@ void CVT_move_common(const dsc* from, dsc* to, DecimalStatus decSt, Callbacks* c
|
||||
*((Decimal128*) p) = CVT_get_dec128(from, decSt, cb->err);
|
||||
return;
|
||||
|
||||
case dtype_dec_fixed:
|
||||
*((DecimalFixed*) p) = CVT_get_dec_fixed(from, (SSHORT) to->dsc_scale, decSt, cb->err);
|
||||
case dtype_int128:
|
||||
*((Int128*) p) = CVT_get_int128(from, (SSHORT) to->dsc_scale, decSt, cb->err);
|
||||
return;
|
||||
|
||||
case dtype_boolean:
|
||||
@ -2108,7 +2138,7 @@ void CVT_move_common(const dsc* from, dsc* to, DecimalStatus decSt, Callbacks* c
|
||||
case dtype_double:
|
||||
case dtype_dec64:
|
||||
case dtype_dec128:
|
||||
case dtype_dec_fixed:
|
||||
case dtype_int128:
|
||||
CVT_conversion_error(from, cb->err);
|
||||
break;
|
||||
}
|
||||
@ -2494,11 +2524,28 @@ double CVT_power_of_ten(const int scale)
|
||||
}
|
||||
|
||||
|
||||
SSHORT CVT_decompose(const char* string,
|
||||
USHORT length,
|
||||
SSHORT dtype,
|
||||
SLONG* return_value,
|
||||
ErrorFunction err)
|
||||
class RetPtr
|
||||
{
|
||||
public:
|
||||
virtual ~RetPtr() { }
|
||||
|
||||
enum lb10 {RETVAL_OVERFLOW, RETVAL_POSSIBLE_OVERFLOW, RETVAL_NO_OVERFLOW};
|
||||
|
||||
virtual USHORT maxSize() = 0;
|
||||
virtual void truncate8() = 0;
|
||||
virtual void truncate16() = 0;
|
||||
virtual lb10 compareLimitBy10() = 0;
|
||||
virtual void nextDigit(unsigned digit, unsigned base) = 0;
|
||||
virtual bool isLowerLimit() = 0;
|
||||
virtual void neg() = 0;
|
||||
};
|
||||
|
||||
static void hex_to_value(const char*& string, const char* end, RetPtr* retValue);
|
||||
|
||||
static SSHORT cvt_decompose(const char* string,
|
||||
USHORT length,
|
||||
RetPtr* return_value,
|
||||
ErrorFunction err)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -2512,15 +2559,6 @@ SSHORT CVT_decompose(const char* string,
|
||||
*
|
||||
**************************************/
|
||||
|
||||
// For now, this routine does not handle quadwords unless this is
|
||||
// supported by the platform as a native datatype.
|
||||
|
||||
if (dtype == dtype_quad)
|
||||
{
|
||||
fb_assert(false);
|
||||
err(Arg::Gds(isc_badblk)); // internal error
|
||||
}
|
||||
|
||||
dsc errd;
|
||||
MOVE_CLEAR(&errd, sizeof(errd));
|
||||
errd.dsc_dtype = dtype_text;
|
||||
@ -2528,14 +2566,9 @@ SSHORT CVT_decompose(const char* string,
|
||||
errd.dsc_length = length;
|
||||
errd.dsc_address = reinterpret_cast<UCHAR*>(const_cast<char*>(string));
|
||||
|
||||
SINT64 value = 0;
|
||||
SSHORT scale = 0;
|
||||
int sign = 0;
|
||||
bool digit_seen = false, fraction = false;
|
||||
const SINT64 lower_limit = (dtype == dtype_long) ? MIN_SLONG : MIN_SINT64;
|
||||
const SINT64 upper_limit = (dtype == dtype_long) ? MAX_SLONG : MAX_SINT64;
|
||||
|
||||
const SINT64 limit_by_10 = upper_limit / 10; // used to check for overflow
|
||||
|
||||
const char* p = string;
|
||||
const char* end = p + length;
|
||||
@ -2561,28 +2594,20 @@ SSHORT CVT_decompose(const char* string,
|
||||
while (q < end && *q == ' ')
|
||||
q++;
|
||||
|
||||
if (q != end || end - p == 0 || end - p > 16)
|
||||
if (q != end || end - p == 0 || end - p > return_value->maxSize())
|
||||
CVT_conversion_error(&errd, err);
|
||||
|
||||
q = p;
|
||||
value = hex_to_value(q, digits_end);
|
||||
hex_to_value(q, digits_end, return_value);
|
||||
|
||||
if (q != digits_end)
|
||||
CVT_conversion_error(&errd, err);
|
||||
|
||||
// 0xFFFFFFFF = -1; 0x0FFFFFFFF = 4294967295
|
||||
if (digits_end - p <= 8)
|
||||
value = (SLONG) value;
|
||||
|
||||
if (dtype == dtype_long)
|
||||
{
|
||||
if (value < LONG_MIN_int64 || value > LONG_MAX_int64)
|
||||
err(Arg::Gds(isc_arith_except) << Arg::Gds(isc_numeric_out_of_range));
|
||||
|
||||
*return_value = (SLONG) value;
|
||||
}
|
||||
else
|
||||
*((SINT64*) return_value) = value;
|
||||
return_value->truncate8();
|
||||
else if (digits_end - p <= 16)
|
||||
return_value->truncate16();
|
||||
|
||||
return 0; // 0 scale for hex literals
|
||||
}
|
||||
@ -2598,20 +2623,33 @@ SSHORT CVT_decompose(const char* string,
|
||||
// tricky: the value doesn't always become negative after an
|
||||
// overflow!
|
||||
|
||||
if (value >= limit_by_10)
|
||||
switch(return_value->compareLimitBy10())
|
||||
{
|
||||
// possibility of an overflow
|
||||
if (value > limit_by_10)
|
||||
{
|
||||
err(Arg::Gds(isc_arith_except) << Arg::Gds(isc_numeric_out_of_range));
|
||||
}
|
||||
else if ((*p > '8' && sign == -1) || (*p > '7' && sign != -1))
|
||||
case RetPtr::RETVAL_OVERFLOW:
|
||||
if (fraction)
|
||||
{
|
||||
while (p < end)
|
||||
{
|
||||
if (*p != '0')
|
||||
break;
|
||||
++p;
|
||||
}
|
||||
if (p >= end)
|
||||
continue;
|
||||
}
|
||||
err(Arg::Gds(isc_arith_except) << Arg::Gds(isc_numeric_out_of_range));
|
||||
break;
|
||||
case RetPtr::RETVAL_POSSIBLE_OVERFLOW:
|
||||
if ((*p > '8' && sign == -1) || (*p > '7' && sign != -1))
|
||||
{
|
||||
err(Arg::Gds(isc_arith_except) << Arg::Gds(isc_numeric_out_of_range));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
value = value * 10 + *p - '0';
|
||||
return_value->nextDigit(*p - '0', 10);
|
||||
if (fraction)
|
||||
--scale;
|
||||
}
|
||||
@ -2645,8 +2683,8 @@ SSHORT CVT_decompose(const char* string,
|
||||
if (!digit_seen)
|
||||
CVT_conversion_error(&errd, err);
|
||||
|
||||
if ((sign == -1) && value != lower_limit)
|
||||
value = -value;
|
||||
if ((sign == -1) && !return_value->isLowerLimit())
|
||||
return_value->neg();
|
||||
|
||||
// If there's still something left, there must be an explicit exponent
|
||||
if (p < end)
|
||||
@ -2693,18 +2731,160 @@ SSHORT CVT_decompose(const char* string,
|
||||
|
||||
if (!digit_seen)
|
||||
CVT_conversion_error(&errd, err);
|
||||
|
||||
}
|
||||
|
||||
if (dtype == dtype_long)
|
||||
*return_value = (SLONG) value;
|
||||
else
|
||||
*((SINT64 *) return_value) = value;
|
||||
|
||||
return scale;
|
||||
}
|
||||
|
||||
|
||||
template <class Traits>
|
||||
class RetValue : public RetPtr
|
||||
{
|
||||
public:
|
||||
RetValue(typename Traits::ValueType* ptr)
|
||||
: return_value(ptr)
|
||||
{
|
||||
value = 0;
|
||||
}
|
||||
|
||||
~RetValue()
|
||||
{
|
||||
*return_value = value;
|
||||
}
|
||||
|
||||
USHORT maxSize()
|
||||
{
|
||||
return sizeof(typename Traits::ValueType);
|
||||
}
|
||||
|
||||
void truncate8()
|
||||
{
|
||||
ULONG mask = 0xFFFFFFFF;
|
||||
value &= mask;
|
||||
}
|
||||
|
||||
void truncate16()
|
||||
{
|
||||
FB_UINT64 mask = 0xFFFFFFFFFFFFFFFF;
|
||||
value &= mask;
|
||||
}
|
||||
|
||||
lb10 compareLimitBy10()
|
||||
{
|
||||
if (value > Traits::UPPER_LIMIT / 10)
|
||||
return RETVAL_OVERFLOW;
|
||||
if (value == Traits::UPPER_LIMIT / 10)
|
||||
return RETVAL_POSSIBLE_OVERFLOW;
|
||||
return RETVAL_NO_OVERFLOW;
|
||||
}
|
||||
|
||||
void nextDigit(unsigned digit, unsigned base)
|
||||
{
|
||||
value *= base;
|
||||
value += digit;
|
||||
}
|
||||
|
||||
bool isLowerLimit()
|
||||
{
|
||||
return value == Traits::LOWER_LIMIT;
|
||||
}
|
||||
|
||||
void neg()
|
||||
{
|
||||
value = -value;
|
||||
}
|
||||
|
||||
private:
|
||||
typename Traits::ValueType value;
|
||||
typename Traits::ValueType* return_value;
|
||||
};
|
||||
|
||||
|
||||
class SLONGTraits
|
||||
{
|
||||
public:
|
||||
typedef SLONG ValueType;
|
||||
static const SLONG UPPER_LIMIT = MAX_SLONG;
|
||||
static const SLONG LOWER_LIMIT = MIN_SLONG;
|
||||
};
|
||||
|
||||
SSHORT CVT_decompose(const char* str, USHORT len, SLONG* val, ErrorFunction err)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* d e c o m p o s e
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Decompose a numeric string in mantissa and exponent,
|
||||
* or if it is in hexadecimal notation.
|
||||
*
|
||||
**************************************/
|
||||
|
||||
RetValue<SLONGTraits> value(val);
|
||||
return cvt_decompose(str, len, &value, err);
|
||||
}
|
||||
|
||||
|
||||
class SINT64Traits
|
||||
{
|
||||
public:
|
||||
typedef SINT64 ValueType;
|
||||
static const SINT64 UPPER_LIMIT = MAX_SINT64;
|
||||
static const SINT64 LOWER_LIMIT = MIN_SINT64;
|
||||
};
|
||||
|
||||
SSHORT CVT_decompose(const char* str, USHORT len, SINT64* val, ErrorFunction err)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* d e c o m p o s e
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Decompose a numeric string in mantissa and exponent,
|
||||
* or if it is in hexadecimal notation.
|
||||
*
|
||||
**************************************/
|
||||
|
||||
RetValue<SINT64Traits> value(val);
|
||||
return cvt_decompose(str, len, &value, err);
|
||||
}
|
||||
|
||||
|
||||
class I128Traits
|
||||
{
|
||||
public:
|
||||
typedef Int128 ValueType;
|
||||
static const CInt128 UPPER_LIMIT;
|
||||
static const CInt128 LOWER_LIMIT;
|
||||
};
|
||||
|
||||
const CInt128 I128Traits::UPPER_LIMIT(MAX_Int128);
|
||||
const CInt128 I128Traits::LOWER_LIMIT(MIN_Int128);
|
||||
|
||||
SSHORT CVT_decompose(const char* str, USHORT len, Int128* val, ErrorFunction err)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* d e c o m p o s e
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Decompose a numeric string in mantissa and exponent,
|
||||
* or if it is in hexadecimal notation.
|
||||
*
|
||||
**************************************/
|
||||
|
||||
|
||||
RetValue<I128Traits> value(val);
|
||||
return cvt_decompose(str, len, &value, err);
|
||||
}
|
||||
|
||||
|
||||
USHORT CVT_get_string_ptr_common(const dsc* desc, USHORT* ttype, UCHAR** address,
|
||||
vary* temp, USHORT length, DecimalStatus decSt, Callbacks* cb)
|
||||
{
|
||||
@ -2851,10 +3031,10 @@ Decimal64 CVT_get_dec64(const dsc* desc, DecimalStatus decSt, ErrorFunction err)
|
||||
return *(Decimal64*) p;
|
||||
|
||||
case dtype_dec128:
|
||||
return ((Decimal128Base*) p)->toDecimal64(decSt);
|
||||
return ((Decimal128*) p)->toDecimal64(decSt);
|
||||
|
||||
case dtype_dec_fixed:
|
||||
return d64.set(*((DecimalFixed*) p), decSt, scale);
|
||||
case dtype_int128:
|
||||
return d64.set(*((Int128*) p), decSt, scale);
|
||||
|
||||
default:
|
||||
fb_assert(false);
|
||||
@ -2940,8 +3120,8 @@ Decimal128 CVT_get_dec128(const dsc* desc, DecimalStatus decSt, ErrorFunction er
|
||||
case dtype_dec128:
|
||||
return *(Decimal128*) p;
|
||||
|
||||
case dtype_dec_fixed:
|
||||
return d128.set(*((DecimalFixed*) p), decSt, scale);
|
||||
case dtype_int128:
|
||||
return d128.set(*((Int128*) p), decSt, scale);
|
||||
|
||||
default:
|
||||
fb_assert(false);
|
||||
@ -2961,7 +3141,7 @@ Decimal128 CVT_get_dec128(const dsc* desc, DecimalStatus decSt, ErrorFunction er
|
||||
}
|
||||
|
||||
|
||||
DecimalFixed CVT_get_dec_fixed(const dsc* desc, SSHORT scale, DecimalStatus decSt, ErrorFunction err)
|
||||
Int128 CVT_get_int128(const dsc* desc, SSHORT scale, DecimalStatus decSt, ErrorFunction err)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -2974,8 +3154,15 @@ DecimalFixed CVT_get_dec_fixed(const dsc* desc, SSHORT scale, DecimalStatus decS
|
||||
*
|
||||
**************************************/
|
||||
VaryStr<1024> buffer; // represents unreasonably long decfloat literal in ASCII
|
||||
DecimalFixed dfix;
|
||||
Int128 int128;
|
||||
Decimal128 tmp;
|
||||
double d, eps;
|
||||
|
||||
static const double I128_MIN_dbl = -1.701411834604692e+38;
|
||||
static const double I128_MAX_dbl = 1.701411834604692e+38;
|
||||
static const CDecimal128 I128_MIN_dcft("-1.701411834604692317316873037158841E+38", decSt);
|
||||
static const CDecimal128 I128_MAX_dcft("1.701411834604692317316873037158841E+38", decSt);
|
||||
static const CDecimal128 DecFlt_05("0.5", decSt);
|
||||
|
||||
// adjust exact numeric values to same scaling
|
||||
if (DTYPE_IS_EXACT(desc->dsc_dtype))
|
||||
@ -2988,27 +3175,30 @@ DecimalFixed CVT_get_dec_fixed(const dsc* desc, SSHORT scale, DecimalStatus decS
|
||||
switch (desc->dsc_dtype)
|
||||
{
|
||||
case dtype_short:
|
||||
dfix.set(*(SSHORT*) p);
|
||||
int128.set(SLONG(*(SSHORT*) p), scale);
|
||||
break;
|
||||
|
||||
case dtype_long:
|
||||
dfix.set(*(SLONG*) p);
|
||||
int128.set(*(SLONG*) p, scale);
|
||||
break;
|
||||
|
||||
case dtype_quad:
|
||||
dfix.set(CVT_get_int64(desc, 0, decSt, err));
|
||||
int128.set(CVT_get_int64(desc, 0, decSt, err), scale);
|
||||
break;
|
||||
|
||||
case dtype_int64:
|
||||
dfix.set(*(SINT64*) p);
|
||||
int128.set(*(SINT64*) p, scale);
|
||||
break;
|
||||
|
||||
case dtype_varying:
|
||||
case dtype_cstring:
|
||||
case dtype_text:
|
||||
CVT_make_null_string(desc, ttype_ascii, &p, &buffer, sizeof(buffer) - 1, decSt, err);
|
||||
dfix.set(buffer.vary_string, scale, decSt);
|
||||
return dfix; // scale already corrected
|
||||
{
|
||||
USHORT length =
|
||||
CVT_make_string(desc, ttype_ascii, &p, &buffer, sizeof(buffer), decSt, err);
|
||||
scale -= CVT_decompose(p, length, &int128, err);
|
||||
int128.setScale(scale);
|
||||
}
|
||||
break;
|
||||
|
||||
case dtype_blob:
|
||||
@ -3022,23 +3212,70 @@ DecimalFixed CVT_get_dec_fixed(const dsc* desc, SSHORT scale, DecimalStatus decS
|
||||
break;
|
||||
|
||||
case dtype_real:
|
||||
dfix.set(*((float*) p), scale, decSt);
|
||||
return dfix; // scale already corrected
|
||||
|
||||
case dtype_double:
|
||||
dfix.set(*((double*) p), scale, decSt);
|
||||
return dfix; // scale already corrected
|
||||
if (desc->dsc_dtype == dtype_real)
|
||||
{
|
||||
d = *((float*) p);
|
||||
eps = eps_float;
|
||||
}
|
||||
else // if (desc->dsc_dtype == DEFAULT_DOUBLE)
|
||||
{
|
||||
d = *((double*) p);
|
||||
eps = eps_double;
|
||||
}
|
||||
|
||||
if (scale > 0)
|
||||
d /= CVT_power_of_ten(scale);
|
||||
else if (scale < 0)
|
||||
d *= CVT_power_of_ten(-scale);
|
||||
|
||||
if (d > 0)
|
||||
d += 0.5 + eps;
|
||||
else
|
||||
d -= 0.5 + eps;
|
||||
|
||||
/* make sure the cast will succeed
|
||||
|
||||
Note that adding or subtracting 0.5, as we do in CVT_get_long,
|
||||
will never allow the rounded value to fit into an Int128,
|
||||
because when the double value is too large in magnitude
|
||||
to fit, 0.5 is less than half of the least significant bit
|
||||
of the significant (sometimes miscalled "mantissa") of the
|
||||
double, and thus will have no effect on the sum. */
|
||||
|
||||
if (d < I128_MIN_dbl || I128_MAX_dbl < d)
|
||||
err(Arg::Gds(isc_arith_except) << Arg::Gds(isc_numeric_out_of_range));
|
||||
|
||||
int128.set(d);
|
||||
break;
|
||||
|
||||
case dtype_dec64:
|
||||
dfix = tmp = *((Decimal64*) p);
|
||||
break;
|
||||
|
||||
case dtype_dec128:
|
||||
dfix = *((Decimal128*) p);
|
||||
if (desc->dsc_dtype == dtype_dec64)
|
||||
tmp = *((Decimal64*) p);
|
||||
else
|
||||
tmp = *((Decimal128*) p);
|
||||
|
||||
tmp.setScale(decSt, -scale);
|
||||
|
||||
/* make sure the cast will succeed
|
||||
|
||||
Note that adding or subtracting 0.5, as we do in CVT_get_long,
|
||||
will never allow the rounded value to fit into an Int128,
|
||||
because when the double value is too large in magnitude
|
||||
to fit, 0.5 is less than half of the least significant bit
|
||||
of the significant (sometimes miscalled "mantissa") of the
|
||||
double, and thus will have no effect on the sum. */
|
||||
|
||||
if (tmp.compare(decSt, I128_MIN_dcft) < 0 || I128_MAX_dcft.compare(decSt, tmp) < 0)
|
||||
err(Arg::Gds(isc_arith_except) << Arg::Gds(isc_numeric_out_of_range));
|
||||
|
||||
int128.set(decSt, tmp);
|
||||
break;
|
||||
|
||||
case dtype_dec_fixed:
|
||||
dfix = *((DecimalFixed*) p);
|
||||
case dtype_int128:
|
||||
int128 = *((Int128*) p);
|
||||
int128.setScale(scale);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -3054,8 +3291,7 @@ DecimalFixed CVT_get_dec_fixed(const dsc* desc, SSHORT scale, DecimalStatus decS
|
||||
err(v);
|
||||
}
|
||||
|
||||
dfix.exactInt(decSt, scale);
|
||||
return dfix;
|
||||
return int128;
|
||||
}
|
||||
|
||||
|
||||
@ -3154,7 +3390,9 @@ SQUAD CVT_get_quad(const dsc* desc, SSHORT scale, DecimalStatus decSt, ErrorFunc
|
||||
{
|
||||
USHORT length =
|
||||
CVT_make_string(desc, ttype_ascii, &p, &buffer, sizeof(buffer), decSt, err);
|
||||
scale -= CVT_decompose(p, length, dtype_quad, &value.gds_quad_high, err);
|
||||
SINT64 i64;
|
||||
scale -= CVT_decompose(p, length, &i64, err);
|
||||
SINT64_to_SQUAD(i64, value);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -3170,7 +3408,7 @@ SQUAD CVT_get_quad(const dsc* desc, SSHORT scale, DecimalStatus decSt, ErrorFunc
|
||||
|
||||
case dtype_dec64:
|
||||
case dtype_dec128:
|
||||
case dtype_dec_fixed:
|
||||
case dtype_int128:
|
||||
SINT64_to_SQUAD(CVT_get_int64(desc, scale, decSt, err), value);
|
||||
break;
|
||||
|
||||
@ -3246,9 +3484,8 @@ SINT64 CVT_get_int64(const dsc* desc, SSHORT scale, DecimalStatus decSt, ErrorFu
|
||||
return d128.toInt64(decSt, scale);
|
||||
}
|
||||
|
||||
case dtype_dec_fixed:
|
||||
value = ((DecimalFixed*) p)->toInt64(decSt);
|
||||
break;
|
||||
case dtype_int128:
|
||||
return ((Int128*) p)->toInt64(scale);
|
||||
|
||||
case dtype_real:
|
||||
case dtype_double:
|
||||
@ -3295,7 +3532,7 @@ SINT64 CVT_get_int64(const dsc* desc, SSHORT scale, DecimalStatus decSt, ErrorFu
|
||||
{
|
||||
USHORT length =
|
||||
CVT_make_string(desc, ttype_ascii, &p, &buffer, sizeof(buffer), decSt, err);
|
||||
scale -= CVT_decompose(p, length, dtype_int64, (SLONG *) & value, err);
|
||||
scale -= CVT_decompose(p, length, &value, err);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -3349,7 +3586,7 @@ SINT64 CVT_get_int64(const dsc* desc, SSHORT scale, DecimalStatus decSt, ErrorFu
|
||||
}
|
||||
|
||||
|
||||
static SINT64 hex_to_value(const char*& string, const char* end)
|
||||
static void hex_to_value(const char*& string, const char* end, RetPtr* retValue)
|
||||
/*************************************
|
||||
*
|
||||
* hex_to_value
|
||||
@ -3366,7 +3603,6 @@ static SINT64 hex_to_value(const char*& string, const char* end)
|
||||
// we already know this is a hex string, and there is no prefix.
|
||||
// So, string is something like DEADBEEF.
|
||||
|
||||
SINT64 value = 0;
|
||||
UCHAR byte = 0;
|
||||
int nibble = ((end - string) & 1);
|
||||
char ch;
|
||||
@ -3385,7 +3621,7 @@ static SINT64 hex_to_value(const char*& string, const char* end)
|
||||
{
|
||||
byte = (byte << 4) + (UCHAR) c;
|
||||
nibble = 0;
|
||||
value = (value << 8) + byte;
|
||||
retValue->nextDigit(byte, 256);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -3397,8 +3633,6 @@ static SINT64 hex_to_value(const char*& string, const char* end)
|
||||
}
|
||||
|
||||
fb_assert(string <= end);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
|
@ -80,7 +80,9 @@ enum EXPECT_DATETIME
|
||||
expect_sql_time_tz
|
||||
};
|
||||
|
||||
}
|
||||
class Int128;
|
||||
|
||||
} // namespace Firebird
|
||||
|
||||
|
||||
void CVT_conversion_error(const dsc*, ErrorFunction);
|
||||
@ -90,12 +92,14 @@ bool CVT_get_boolean(const dsc*, ErrorFunction);
|
||||
double CVT_get_double(const dsc*, Firebird::DecimalStatus, ErrorFunction, bool* getNumericOverflow = nullptr);
|
||||
Firebird::Decimal64 CVT_get_dec64(const dsc*, Firebird::DecimalStatus, ErrorFunction);
|
||||
Firebird::Decimal128 CVT_get_dec128(const dsc*, Firebird::DecimalStatus, ErrorFunction);
|
||||
Firebird::DecimalFixed CVT_get_dec_fixed(const dsc*, SSHORT, Firebird::DecimalStatus, ErrorFunction);
|
||||
Firebird::Int128 CVT_get_int128(const dsc*, SSHORT, Firebird::DecimalStatus, ErrorFunction);
|
||||
USHORT CVT_make_string(const dsc*, USHORT, const char**, vary*, USHORT, Firebird::DecimalStatus, ErrorFunction);
|
||||
void CVT_make_null_string(const dsc*, USHORT, const char**, vary*, USHORT, Firebird::DecimalStatus, ErrorFunction);
|
||||
void CVT_move_common(const dsc*, dsc*, Firebird::DecimalStatus, Firebird::Callbacks*);
|
||||
void CVT_move(const dsc*, dsc*, Firebird::DecimalStatus, ErrorFunction);
|
||||
SSHORT CVT_decompose(const char*, USHORT, SSHORT, SLONG*, ErrorFunction);
|
||||
SSHORT CVT_decompose(const char*, USHORT, SLONG*, ErrorFunction);
|
||||
SSHORT CVT_decompose(const char*, USHORT, SINT64*, ErrorFunction);
|
||||
SSHORT CVT_decompose(const char*, USHORT, Firebird::Int128*, ErrorFunction);
|
||||
USHORT CVT_get_string_ptr(const dsc*, USHORT*, UCHAR**, vary*, USHORT, Firebird::DecimalStatus, ErrorFunction);
|
||||
USHORT CVT_get_string_ptr_common(const dsc*, USHORT*, UCHAR**, vary*, USHORT, Firebird::DecimalStatus, Firebird::Callbacks*);
|
||||
SINT64 CVT_get_int64(const dsc*, SSHORT, Firebird::DecimalStatus, ErrorFunction);
|
||||
|
@ -68,7 +68,7 @@ static const USHORT _DSC_convert_to_text_length[DTYPE_TYPE_MAX] =
|
||||
5, // dtype_boolean
|
||||
23, // dtype_dec64 1 + 1 + 1 + 1 + 16(34) + 3(4)
|
||||
42, // dtype_dec128 +- . e +- coeff + exp
|
||||
36, // dtype_dec_fixed coeff(34) + 1(+-) + 1(.)
|
||||
47, // dtype_int128
|
||||
14 + TimeZoneUtil::MAX_LEN, // dtype_sql_time_tz HH:MM:SS.MMMM +NN:NN
|
||||
25 + TimeZoneUtil::MAX_LEN // dtype_timestamp_tz YYYY-MM-DD HH:MM:SS.MMMM +NN:NN
|
||||
};
|
||||
@ -122,7 +122,7 @@ const BYTE DSC_add_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
|
||||
dtype_double dtype_d_float dtype_sql_date dtype_sql_time
|
||||
dtype_timestamp dtype_blob dtype_array dtype_int64
|
||||
dtype_dbkey dtype_boolean dtype_dec64 dtype_dec128
|
||||
dtype_dec_fixed dtype_sql_time_tz dtype_timestamp_tz
|
||||
dtype_int128 dtype_sql_time_tz dtype_timestamp_tz
|
||||
*/
|
||||
|
||||
// dtype_unknown
|
||||
@ -141,7 +141,7 @@ const BYTE DSC_add_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
|
||||
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||
dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||
dtype_dec_fixed, DTYPE_CANNOT, dtype_timestamp_tz},
|
||||
dtype_int128, DTYPE_CANNOT, dtype_timestamp_tz},
|
||||
|
||||
// dtype_cstring
|
||||
{dtype_unknown, dtype_double, dtype_double, dtype_double,
|
||||
@ -150,7 +150,7 @@ const BYTE DSC_add_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
|
||||
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||
dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||
dtype_dec_fixed, DTYPE_CANNOT, dtype_timestamp_tz},
|
||||
dtype_int128, DTYPE_CANNOT, dtype_timestamp_tz},
|
||||
|
||||
// dtype_varying
|
||||
{dtype_unknown, dtype_double, dtype_double, dtype_double,
|
||||
@ -159,7 +159,7 @@ const BYTE DSC_add_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
|
||||
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||
dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||
dtype_dec_fixed, DTYPE_CANNOT, dtype_timestamp_tz},
|
||||
dtype_int128, DTYPE_CANNOT, dtype_timestamp_tz},
|
||||
|
||||
// 4 (unused)
|
||||
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||
@ -204,7 +204,7 @@ const BYTE DSC_add_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
|
||||
dtype_double, dtype_d_float, dtype_sql_date, dtype_sql_time,
|
||||
dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int64,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||
dtype_dec_fixed, dtype_sql_time_tz, dtype_timestamp_tz},
|
||||
dtype_int128, dtype_sql_time_tz, dtype_timestamp_tz},
|
||||
|
||||
// dtype_long
|
||||
{dtype_unknown, dtype_double, dtype_double, dtype_double,
|
||||
@ -213,7 +213,7 @@ const BYTE DSC_add_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
|
||||
dtype_double, dtype_d_float, dtype_sql_date, dtype_sql_time,
|
||||
dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int64,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||
dtype_dec_fixed, dtype_sql_time_tz, dtype_timestamp_tz},
|
||||
dtype_int128, dtype_sql_time_tz, dtype_timestamp_tz},
|
||||
|
||||
// dtype_quad
|
||||
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||
@ -303,7 +303,7 @@ const BYTE DSC_add_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
|
||||
dtype_double, dtype_d_float, dtype_sql_date, dtype_sql_time,
|
||||
dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int64,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||
dtype_dec_fixed, dtype_sql_time_tz, dtype_timestamp_tz},
|
||||
dtype_int128, dtype_sql_time_tz, dtype_timestamp_tz},
|
||||
|
||||
// dtype_dbkey
|
||||
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||
@ -341,14 +341,14 @@ const BYTE DSC_add_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||
dtype_dec128, dtype_sql_time_tz, dtype_timestamp_tz},
|
||||
|
||||
// dtype_dec_fixed
|
||||
{dtype_unknown, dtype_dec_fixed, dtype_dec_fixed, dtype_dec_fixed,
|
||||
// dtype_int128
|
||||
{dtype_unknown, dtype_int128, dtype_int128, dtype_int128,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||
dtype_dec_fixed, dtype_dec_fixed, DTYPE_CANNOT, dtype_double,
|
||||
dtype_int128, dtype_int128, DTYPE_CANNOT, dtype_double,
|
||||
dtype_double, dtype_d_float, dtype_sql_date, dtype_sql_time,
|
||||
dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec_fixed,
|
||||
dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int128,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||
dtype_dec_fixed, dtype_sql_time_tz, dtype_timestamp_tz},
|
||||
dtype_int128, dtype_sql_time_tz, dtype_timestamp_tz},
|
||||
|
||||
// dtype_sql_time_tz
|
||||
{dtype_unknown, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||
@ -384,7 +384,7 @@ const BYTE DSC_sub_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
|
||||
dtype_double dtype_d_float dtype_sql_date dtype_sql_time
|
||||
dtype_timestamp dtype_blob dtype_array dtype_int64
|
||||
dtype_dbkey dtype_boolean dtype_dec64 dtype_dec128
|
||||
dtype_dec_fixed dtype_sql_time_tz dtype_timestamp_tz
|
||||
dtype_int128 dtype_sql_time_tz dtype_timestamp_tz
|
||||
*/
|
||||
|
||||
// dtype_unknown
|
||||
@ -403,7 +403,7 @@ const BYTE DSC_sub_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
|
||||
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||
dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||
dtype_dec_fixed, DTYPE_CANNOT, dtype_timestamp_tz},
|
||||
dtype_int128, DTYPE_CANNOT, dtype_timestamp_tz},
|
||||
|
||||
// dtype_cstring
|
||||
{dtype_unknown, dtype_double, dtype_double, dtype_double,
|
||||
@ -412,7 +412,7 @@ const BYTE DSC_sub_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
|
||||
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||
dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||
dtype_dec_fixed, DTYPE_CANNOT, dtype_timestamp_tz},
|
||||
dtype_int128, DTYPE_CANNOT, dtype_timestamp_tz},
|
||||
|
||||
// dtype_varying
|
||||
{dtype_unknown, dtype_double, dtype_double, dtype_double,
|
||||
@ -421,7 +421,7 @@ const BYTE DSC_sub_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
|
||||
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||
dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||
dtype_dec_fixed, DTYPE_CANNOT, dtype_timestamp_tz},
|
||||
dtype_int128, DTYPE_CANNOT, dtype_timestamp_tz},
|
||||
|
||||
// 4 (unused)
|
||||
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||
@ -466,7 +466,7 @@ const BYTE DSC_sub_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
|
||||
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int64,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||
dtype_dec_fixed, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||
dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||
|
||||
// dtype_long
|
||||
{dtype_unknown, dtype_double, dtype_double, dtype_double,
|
||||
@ -475,7 +475,7 @@ const BYTE DSC_sub_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
|
||||
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int64,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||
dtype_dec_fixed, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||
dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||
|
||||
// dtype_quad
|
||||
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||
@ -565,7 +565,7 @@ const BYTE DSC_sub_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
|
||||
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int64,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||
dtype_dec_fixed, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||
dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||
|
||||
// dtype_dbkey
|
||||
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||
@ -603,14 +603,14 @@ const BYTE DSC_sub_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||
dtype_dec128, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||
|
||||
// dtype_dec_fixed
|
||||
{dtype_unknown, dtype_dec_fixed, dtype_dec_fixed, dtype_dec_fixed,
|
||||
// dtype_int128
|
||||
{dtype_unknown, dtype_int128, dtype_int128, dtype_int128,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||
dtype_dec_fixed, dtype_dec_fixed, DTYPE_CANNOT, dtype_double,
|
||||
dtype_int128, dtype_int128, DTYPE_CANNOT, dtype_double,
|
||||
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec_fixed,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int128,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||
dtype_dec_fixed, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||
dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||
|
||||
// dtype_sql_time_tz
|
||||
{dtype_unknown, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||
@ -647,7 +647,7 @@ const BYTE DSC_multiply_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
|
||||
dtype_double dtype_d_float dtype_sql_date dtype_sql_time
|
||||
dtype_timestamp dtype_blob dtype_array dtype_int64
|
||||
dtype_dbkey dtype_boolean dtype_dec64 dtype_dec128
|
||||
dtype_dec_fixed dtype_sql_time_tz dtype_timestamp_tz
|
||||
dtype_int128 dtype_sql_time_tz dtype_timestamp_tz
|
||||
*/
|
||||
|
||||
// dtype_unknown
|
||||
@ -666,7 +666,7 @@ const BYTE DSC_multiply_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
|
||||
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||
dtype_dec_fixed, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||
dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||
|
||||
// dtype_cstring
|
||||
{dtype_unknown, dtype_double, dtype_double, dtype_double,
|
||||
@ -675,7 +675,7 @@ const BYTE DSC_multiply_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
|
||||
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||
dtype_dec_fixed, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||
dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||
|
||||
// dtype_varying
|
||||
{dtype_unknown, dtype_double, dtype_double, dtype_double,
|
||||
@ -684,7 +684,7 @@ const BYTE DSC_multiply_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
|
||||
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||
dtype_dec_fixed, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||
dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||
|
||||
// 4 (unused)
|
||||
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||
@ -729,7 +729,7 @@ const BYTE DSC_multiply_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
|
||||
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int64,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||
dtype_dec_fixed, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||
dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||
|
||||
// dtype_long
|
||||
{dtype_unknown, dtype_double, dtype_double, dtype_double,
|
||||
@ -738,7 +738,7 @@ const BYTE DSC_multiply_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
|
||||
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int64,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||
dtype_dec_fixed, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||
dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||
|
||||
// dtype_quad
|
||||
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||
@ -826,9 +826,9 @@ const BYTE DSC_multiply_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||
dtype_int64, dtype_int64, DTYPE_CANNOT, dtype_double,
|
||||
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int64,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int128,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||
dtype_dec_fixed, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||
dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||
|
||||
// dtype_dbkey
|
||||
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||
@ -866,14 +866,14 @@ const BYTE DSC_multiply_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||
dtype_dec128, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||
|
||||
// dtype_dec_fixed
|
||||
{dtype_unknown, dtype_dec_fixed, dtype_dec_fixed, dtype_dec_fixed,
|
||||
// dtype_int128
|
||||
{dtype_unknown, dtype_int128, dtype_int128, dtype_int128,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||
dtype_dec_fixed, dtype_dec_fixed, DTYPE_CANNOT, dtype_double,
|
||||
dtype_int128, dtype_int128, DTYPE_CANNOT, dtype_double,
|
||||
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec_fixed,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int128,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||
dtype_dec_fixed, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||
dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||
|
||||
// dtype_sql_time_tz
|
||||
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||
@ -909,7 +909,7 @@ const BYTE DSC_multiply_blr4_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
|
||||
dtype_double dtype_d_float dtype_sql_date dtype_sql_time
|
||||
dtype_timestamp dtype_blob dtype_array dtype_int64
|
||||
dtype_dbkey dtype_boolean dtype_dec64 dtype_dec128
|
||||
dtype_dec_fixed dtype_sql_time_tz dtype_timestamp_tz
|
||||
dtype_int128 dtype_sql_time_tz dtype_timestamp_tz
|
||||
*/
|
||||
|
||||
// dtype_unknown
|
||||
@ -928,7 +928,7 @@ const BYTE DSC_multiply_blr4_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
|
||||
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||
dtype_dec_fixed, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||
dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||
|
||||
// dtype_cstring
|
||||
{dtype_unknown, dtype_double, dtype_double, dtype_double,
|
||||
@ -937,7 +937,7 @@ const BYTE DSC_multiply_blr4_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
|
||||
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||
dtype_dec_fixed, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||
dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||
|
||||
// dtype_varying
|
||||
{dtype_unknown, dtype_double, dtype_double, dtype_double,
|
||||
@ -946,7 +946,7 @@ const BYTE DSC_multiply_blr4_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
|
||||
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||
dtype_dec_fixed, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||
dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||
|
||||
// 4 (unused)
|
||||
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||
@ -991,7 +991,7 @@ const BYTE DSC_multiply_blr4_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
|
||||
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||
dtype_dec_fixed, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||
dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||
|
||||
// dtype_long
|
||||
{dtype_unknown, dtype_double, dtype_double, dtype_double,
|
||||
@ -1000,7 +1000,7 @@ const BYTE DSC_multiply_blr4_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
|
||||
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||
dtype_dec_fixed, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||
dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||
|
||||
// dtype_quad
|
||||
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||
@ -1090,7 +1090,7 @@ const BYTE DSC_multiply_blr4_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
|
||||
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||
dtype_dec_fixed, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||
dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||
|
||||
// dtype_dbkey
|
||||
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||
@ -1128,14 +1128,14 @@ const BYTE DSC_multiply_blr4_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||
dtype_dec128, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||
|
||||
// dtype_dec_fixed
|
||||
{dtype_unknown, dtype_dec_fixed, dtype_dec_fixed, dtype_dec_fixed,
|
||||
// dtype_int128
|
||||
{dtype_unknown, dtype_int128, dtype_int128, dtype_int128,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||
dtype_dec_fixed, dtype_dec_fixed, DTYPE_CANNOT, dtype_double,
|
||||
dtype_int128, dtype_int128, DTYPE_CANNOT, dtype_double,
|
||||
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec_fixed,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int128,
|
||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||
dtype_dec_fixed, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||
dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||
|
||||
// dtype_sql_time_tz
|
||||
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||
@ -1268,9 +1268,9 @@ bool DSC_make_descriptor(DSC* desc,
|
||||
desc->dsc_dtype = dtype_dec128;
|
||||
break;
|
||||
|
||||
case blr_dec_fixed:
|
||||
desc->dsc_length = sizeof(DecimalFixed);
|
||||
desc->dsc_dtype = dtype_dec_fixed;
|
||||
case blr_int128:
|
||||
desc->dsc_length = sizeof(Int128);
|
||||
desc->dsc_dtype = dtype_int128;
|
||||
break;
|
||||
|
||||
case blr_timestamp:
|
||||
@ -1448,7 +1448,7 @@ const char* dsc::typeToText() const
|
||||
return "decfloat(16)";
|
||||
case dtype_dec128:
|
||||
return "decfloat(34)";
|
||||
case dtype_dec_fixed:
|
||||
case dtype_int128:
|
||||
return "decimal";
|
||||
case dtype_sql_time_tz:
|
||||
return "time with timezone";
|
||||
@ -1552,8 +1552,8 @@ void dsc::getSqlInfo(SLONG* sqlLength, SLONG* sqlSubType, SLONG* sqlScale, SLONG
|
||||
*sqlScale = 0;
|
||||
break;
|
||||
|
||||
case dtype_dec_fixed:
|
||||
*sqlType = SQL_DEC_FIXED;
|
||||
case dtype_int128:
|
||||
*sqlType = SQL_INT128;
|
||||
*sqlScale = dsc_scale;
|
||||
if (dsc_sub_type)
|
||||
*sqlSubType = dsc_sub_type;
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "../jrd/ods.h"
|
||||
#include "../intl/charsets.h"
|
||||
#include "../common/DecFloat.h"
|
||||
#include "../common/Int128.h"
|
||||
|
||||
// Data type information
|
||||
|
||||
@ -60,7 +61,7 @@ inline bool DTYPE_IS_BLOB_OR_QUAD(UCHAR d)
|
||||
// Exact numeric?
|
||||
inline bool DTYPE_IS_EXACT(UCHAR d)
|
||||
{
|
||||
return d == dtype_int64 || d == dtype_long || d == dtype_short || d == dtype_dec_fixed;
|
||||
return d == dtype_int64 || d == dtype_long || d == dtype_short || d == dtype_int128;
|
||||
}
|
||||
|
||||
inline bool DTYPE_IS_APPROX(UCHAR d)
|
||||
@ -70,12 +71,13 @@ inline bool DTYPE_IS_APPROX(UCHAR d)
|
||||
|
||||
inline bool DTYPE_IS_DECFLOAT(UCHAR d)
|
||||
{
|
||||
return d == dtype_dec128 || d == dtype_dec64 || d == dtype_dec_fixed;
|
||||
return d == dtype_dec128 || d == dtype_dec64;
|
||||
}
|
||||
|
||||
inline bool DTYPE_IS_NUMERIC(UCHAR d)
|
||||
{
|
||||
return (d >= dtype_byte && d <= dtype_d_float) || d == dtype_int64 || DTYPE_IS_DECFLOAT(d);
|
||||
return (d >= dtype_byte && d <= dtype_d_float) || d == dtype_int64 ||
|
||||
d == dtype_int128 || DTYPE_IS_DECFLOAT(d);
|
||||
}
|
||||
|
||||
// Descriptor format
|
||||
@ -138,7 +140,8 @@ typedef struct dsc
|
||||
|
||||
bool isExact() const
|
||||
{
|
||||
return dsc_dtype == dtype_int64 || dsc_dtype == dtype_long || dsc_dtype == dtype_short;
|
||||
return dsc_dtype == dtype_int128 || dsc_dtype == dtype_int64 ||
|
||||
dsc_dtype == dtype_long || dsc_dtype == dtype_short;
|
||||
}
|
||||
|
||||
bool isNumeric() const
|
||||
@ -187,14 +190,14 @@ typedef struct dsc
|
||||
return dsc_dtype == dtype_dec128 || dsc_dtype == dtype_dec64;
|
||||
}
|
||||
|
||||
bool isDecFixed() const
|
||||
bool isInt128() const
|
||||
{
|
||||
return dsc_dtype == dtype_dec_fixed;
|
||||
return dsc_dtype == dtype_int128;
|
||||
}
|
||||
|
||||
bool isDecOrInt() const
|
||||
{
|
||||
return isDecFloat() || isDecFixed() || isExact();
|
||||
return isDecFloat() || isExact();
|
||||
}
|
||||
|
||||
bool isApprox() const
|
||||
@ -339,6 +342,15 @@ typedef struct dsc
|
||||
dsc_address = (UCHAR*) address;
|
||||
}
|
||||
|
||||
void makeInt128(SCHAR scale, Firebird::Int128* address = NULL)
|
||||
{
|
||||
clear();
|
||||
dsc_dtype = dtype_int128;
|
||||
dsc_length = sizeof(Firebird::Int128);
|
||||
dsc_scale = scale;
|
||||
dsc_address = (UCHAR*) address;
|
||||
}
|
||||
|
||||
void makeLong(SCHAR scale, SLONG* address = NULL)
|
||||
{
|
||||
clear();
|
||||
|
@ -252,6 +252,7 @@ static const TOK tokens[] =
|
||||
{TOK_INSERT, "INSERT", false},
|
||||
{TOK_INSERTING, "INSERTING", false},
|
||||
{TOK_INT, "INT", false},
|
||||
{TOK_INT128, "INT128", true},
|
||||
{TOK_INTEGER, "INTEGER", false},
|
||||
{TOK_INTO, "INTO", false},
|
||||
{TOK_INVOKER, "INVOKER", true},
|
||||
|
@ -855,9 +855,9 @@ static const UCHAR* sdl_desc(const UCHAR* ptr, DSC* desc)
|
||||
desc->dsc_length = sizeof(Decimal128);
|
||||
break;
|
||||
|
||||
case blr_dec_fixed:
|
||||
desc->dsc_dtype = dtype_dec_fixed;
|
||||
desc->dsc_length = sizeof(DecimalFixed);
|
||||
case blr_int128:
|
||||
desc->dsc_dtype = dtype_int128;
|
||||
desc->dsc_length = sizeof(Int128);
|
||||
break;
|
||||
|
||||
case blr_timestamp:
|
||||
|
@ -1522,8 +1522,8 @@ UCHAR sqlTypeToDscType(SSHORT sqlType)
|
||||
return dtype_dec64;
|
||||
case SQL_DEC34:
|
||||
return dtype_dec128;
|
||||
case SQL_DEC_FIXED:
|
||||
return dtype_dec_fixed;
|
||||
case SQL_INT128:
|
||||
return dtype_int128;
|
||||
case SQL_TIME_TZ:
|
||||
return dtype_sql_time_tz;
|
||||
case SQL_TIMESTAMP_TZ:
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "../yvalve/gds_proto.h"
|
||||
#include "../common/gdsassert.h"
|
||||
#include "../common/DecFloat.h"
|
||||
#include "../common/Int128.h"
|
||||
|
||||
inline UCHAR* XDR_ALLOC(ULONG size)
|
||||
{
|
||||
@ -268,12 +269,17 @@ bool_t xdr_datum( XDR* xdrs, const dsc* desc, UCHAR* buffer)
|
||||
break;
|
||||
|
||||
case dtype_dec128:
|
||||
case dtype_dec_fixed:
|
||||
fb_assert(desc->dsc_length >= sizeof(Firebird::Decimal128));
|
||||
if (!xdr_dec128(xdrs, reinterpret_cast<Firebird::Decimal128*>(p)))
|
||||
return FALSE;
|
||||
break;
|
||||
|
||||
case dtype_int128:
|
||||
fb_assert(desc->dsc_length >= sizeof(Firebird::Int128));
|
||||
if (!xdr_int128(xdrs, reinterpret_cast<Firebird::Int128*>(p)))
|
||||
return FALSE;
|
||||
break;
|
||||
|
||||
case dtype_timestamp:
|
||||
fb_assert(desc->dsc_length >= 2 * sizeof(SLONG));
|
||||
if (!xdr_long(xdrs, &((SLONG*) p)[0]))
|
||||
@ -381,6 +387,19 @@ bool_t xdr_dec128(XDR* xdrs, Firebird::Decimal128* ip)
|
||||
}
|
||||
|
||||
|
||||
bool_t xdr_int128(XDR* xdrs, Firebird::Int128* ip)
|
||||
{
|
||||
UCHAR* bytes = ip->getBytes();
|
||||
|
||||
#ifndef WORDS_BIGENDIAN
|
||||
return xdr_hyper(xdrs, &bytes[8]) && xdr_hyper(xdrs, &bytes[0]);
|
||||
#else
|
||||
fb_assert(false); // Dec64/128 XDR not tested on bigendians!
|
||||
return xdr_hyper(xdrs, &bytes[0]) && xdr_hyper(xdrs, &bytes[8]);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool_t xdr_enum(XDR* xdrs, xdr_op* ip)
|
||||
{
|
||||
/**************************************
|
||||
|
@ -29,8 +29,9 @@
|
||||
|
||||
bool_t xdr_datum(XDR*, const dsc*, UCHAR*);
|
||||
bool_t xdr_double(XDR*, double*);
|
||||
bool_t xdr_dec64(XDR*, Firebird::Decimal64*);
|
||||
bool_t xdr_dec128(XDR*, Firebird::Decimal128*);
|
||||
bool_t xdr_dec64(XDR*, Firebird::Decimal64*);
|
||||
bool_t xdr_dec128(XDR*, Firebird::Decimal128*);
|
||||
bool_t xdr_int128(XDR*, Firebird::Int128*);
|
||||
bool_t xdr_enum(XDR*, xdr_op*);
|
||||
bool_t xdr_float(XDR*, float*);
|
||||
bool_t xdr_int(XDR*, int*);
|
||||
|
@ -540,6 +540,11 @@ void AvgAggNode::make(DsqlCompilerScratch* dsqlScratch, dsc* desc)
|
||||
ERRD_post(Arg::Gds(isc_expression_eval_err) <<
|
||||
Arg::Gds(isc_dsql_agg2_wrongarg) << Arg::Str("AVG"));
|
||||
}
|
||||
else if (desc->dsc_dtype == dtype_int64 || desc->dsc_dtype == dtype_int128)
|
||||
{
|
||||
desc->dsc_dtype = dtype_int128;
|
||||
desc->dsc_length = sizeof(Int128);
|
||||
}
|
||||
else if (DTYPE_IS_EXACT(desc->dsc_dtype))
|
||||
{
|
||||
desc->dsc_dtype = dtype_int64;
|
||||
@ -584,13 +589,10 @@ void AvgAggNode::getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc)
|
||||
return;
|
||||
}
|
||||
|
||||
// In V6, the average of an exact type is computed in SINT64, rather than double as in prior
|
||||
// releases.
|
||||
switch (desc->dsc_dtype)
|
||||
{
|
||||
case dtype_short:
|
||||
case dtype_long:
|
||||
case dtype_int64:
|
||||
desc->dsc_dtype = dtype_int64;
|
||||
desc->dsc_length = sizeof(SINT64);
|
||||
desc->dsc_sub_type = 0;
|
||||
@ -598,6 +600,15 @@ void AvgAggNode::getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc)
|
||||
nodScale = desc->dsc_scale;
|
||||
break;
|
||||
|
||||
case dtype_int64:
|
||||
case dtype_int128:
|
||||
desc->dsc_dtype = dtype_int128;
|
||||
desc->dsc_length = sizeof(Int128);
|
||||
desc->dsc_sub_type = 0;
|
||||
desc->dsc_flags = 0;
|
||||
nodScale = desc->dsc_scale;
|
||||
break;
|
||||
|
||||
case dtype_unknown:
|
||||
desc->dsc_dtype = dtype_unknown;
|
||||
desc->dsc_length = 0;
|
||||
@ -697,12 +708,19 @@ dsc* AvgAggNode::aggExecute(thread_db* tdbb, jrd_req* request) const
|
||||
SINT64 i;
|
||||
double d;
|
||||
Decimal128 dec;
|
||||
Int128 i128;
|
||||
|
||||
if (!dialect1 && impure->vlu_desc.dsc_dtype == dtype_int64)
|
||||
{
|
||||
i = *((SINT64*) impure->vlu_desc.dsc_address) / impure->vlux_count;
|
||||
temp.makeInt64(impure->vlu_desc.dsc_scale, &i);
|
||||
}
|
||||
else if (!dialect1 && impure->vlu_desc.dsc_dtype == dtype_int128)
|
||||
{
|
||||
i128.set(impure->vlux_count, 0);
|
||||
i128 = ((Int128*) impure->vlu_desc.dsc_address)->div(i128, 0);
|
||||
temp.makeInt128(impure->vlu_desc.dsc_scale, &i128);
|
||||
}
|
||||
else if (DTYPE_IS_DECFLOAT(impure->vlu_desc.dsc_dtype))
|
||||
{
|
||||
DecimalStatus decSt = tdbb->getAttachment()->att_dec_status;
|
||||
@ -1037,6 +1055,11 @@ void SumAggNode::make(DsqlCompilerScratch* dsqlScratch, dsc* desc)
|
||||
ERRD_post(Arg::Gds(isc_expression_eval_err) <<
|
||||
Arg::Gds(isc_dsql_agg2_wrongarg) << Arg::Str("SUM"));
|
||||
}
|
||||
else if (desc->dsc_dtype == dtype_int64 || desc->dsc_dtype == dtype_int128)
|
||||
{
|
||||
desc->dsc_dtype = dtype_int128;
|
||||
desc->dsc_length = sizeof(Int128);
|
||||
}
|
||||
else if (DTYPE_IS_EXACT(desc->dsc_dtype))
|
||||
{
|
||||
desc->dsc_dtype = dtype_int64;
|
||||
@ -1118,13 +1141,21 @@ void SumAggNode::getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc)
|
||||
{
|
||||
case dtype_short:
|
||||
case dtype_long:
|
||||
case dtype_int64:
|
||||
desc->dsc_dtype = dtype_int64;
|
||||
desc->dsc_length = sizeof(SINT64);
|
||||
nodScale = desc->dsc_scale;
|
||||
desc->dsc_flags = 0;
|
||||
return;
|
||||
|
||||
case dtype_int64:
|
||||
case dtype_int128:
|
||||
desc->dsc_dtype = dtype_int128;
|
||||
desc->dsc_length = sizeof(Int128);
|
||||
desc->dsc_sub_type = 0;
|
||||
desc->dsc_flags = 0;
|
||||
nodScale = desc->dsc_scale;
|
||||
return;
|
||||
|
||||
case dtype_unknown:
|
||||
desc->dsc_dtype = dtype_unknown;
|
||||
desc->dsc_length = 0;
|
||||
|
@ -4491,7 +4491,7 @@ void AlterDomainNode::checkUpdate(const dyn_fld& origFld, const dyn_fld& newFld)
|
||||
case blr_float:
|
||||
case blr_dec64:
|
||||
case blr_dec128:
|
||||
case blr_dec_fixed:
|
||||
case blr_int128:
|
||||
// Cannot convert column %s from character to non-character data.
|
||||
errorCode = isc_dyn_dtype_conv_invalid;
|
||||
break;
|
||||
@ -4613,7 +4613,7 @@ void AlterDomainNode::checkUpdate(const dyn_fld& origFld, const dyn_fld& newFld)
|
||||
case blr_float:
|
||||
case blr_dec64:
|
||||
case blr_dec128:
|
||||
case blr_dec_fixed:
|
||||
case blr_int128:
|
||||
switch (newFld.dyn_dtype)
|
||||
{
|
||||
case blr_blob:
|
||||
@ -4741,7 +4741,7 @@ void AlterDomainNode::checkUpdate(const dyn_fld& origFld, const dyn_fld& newFld)
|
||||
case blr_double:
|
||||
case blr_dec64:
|
||||
case blr_dec128:
|
||||
case blr_dec_fixed:
|
||||
case blr_int128:
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -4751,13 +4751,13 @@ void AlterDomainNode::checkUpdate(const dyn_fld& origFld, const dyn_fld& newFld)
|
||||
}
|
||||
break;
|
||||
|
||||
case blr_dec_fixed:
|
||||
case blr_int128:
|
||||
switch (origFld.dyn_dtype)
|
||||
{
|
||||
case blr_short:
|
||||
case blr_long:
|
||||
case blr_int64:
|
||||
case blr_dec_fixed:
|
||||
case blr_int128:
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -506,17 +506,19 @@ namespace
|
||||
const UCHAR DSC_ZTYPE_FLT64 = 0;
|
||||
const UCHAR DSC_ZTYPE_FLT128 = 1;
|
||||
const UCHAR DSC_ZTYPE_FIXED = 2;
|
||||
const UCHAR DSC_ZTYPE_INT = 3;
|
||||
const UCHAR DSC_ZTYPE_OTHER = 4;
|
||||
const UCHAR DSC_ZTYPE_BAD = 5;
|
||||
const UCHAR DSC_ZTYPE_INT64 = 3;
|
||||
const UCHAR DSC_ZTYPE_INT = 4;
|
||||
const UCHAR DSC_ZTYPE_OTHER = 5;
|
||||
const UCHAR DSC_ZTYPE_BAD = 6;
|
||||
|
||||
const UCHAR decimalDescTable[5][5] = {
|
||||
/* DSC_ZTYPE_FLT64 DSC_ZTYPE_FLT128 DSC_ZTYPE_FIXED DSC_ZTYPE_INT DSC_ZTYPE_OTHER */
|
||||
/* DSC_ZTYPE_FLT64 */ {DSC_ZTYPE_FLT64, DSC_ZTYPE_FLT128, DSC_ZTYPE_FLT128, DSC_ZTYPE_FLT128, DSC_ZTYPE_FLT128},
|
||||
/* DSC_ZTYPE_FLT128 */ {DSC_ZTYPE_FLT128, DSC_ZTYPE_FLT128, DSC_ZTYPE_FLT128, DSC_ZTYPE_FLT128, DSC_ZTYPE_FLT128},
|
||||
/* DSC_ZTYPE_FIXED */ {DSC_ZTYPE_FLT128, DSC_ZTYPE_FLT128, DSC_ZTYPE_FIXED, DSC_ZTYPE_FIXED, DSC_ZTYPE_FLT128},
|
||||
/* DSC_ZTYPE_INT */ {DSC_ZTYPE_FLT128, DSC_ZTYPE_FLT128, DSC_ZTYPE_FIXED, DSC_ZTYPE_BAD, DSC_ZTYPE_BAD},
|
||||
/* DSC_ZTYPE_OTHER */ {DSC_ZTYPE_FLT128, DSC_ZTYPE_FLT128, DSC_ZTYPE_FLT128, DSC_ZTYPE_BAD, DSC_ZTYPE_BAD}
|
||||
const UCHAR decimalDescTable[6][6] = {
|
||||
/* DSC_ZTYPE_FLT64 DSC_ZTYPE_FLT128 DSC_ZTYPE_FIXED DSC_ZTYPE_INT64 DSC_ZTYPE_INT DSC_ZTYPE_OTHER */
|
||||
/* DSC_ZTYPE_FLT64 */ {DSC_ZTYPE_FLT64, DSC_ZTYPE_FLT128, DSC_ZTYPE_FLT128, DSC_ZTYPE_FLT128, DSC_ZTYPE_FLT128, DSC_ZTYPE_FLT128},
|
||||
/* DSC_ZTYPE_FLT128 */ {DSC_ZTYPE_FLT128, DSC_ZTYPE_FLT128, DSC_ZTYPE_FLT128, DSC_ZTYPE_FLT128, DSC_ZTYPE_FLT128, DSC_ZTYPE_FLT128},
|
||||
/* DSC_ZTYPE_FIXED */ {DSC_ZTYPE_FLT128, DSC_ZTYPE_FLT128, DSC_ZTYPE_FIXED, DSC_ZTYPE_FIXED, DSC_ZTYPE_FIXED, DSC_ZTYPE_FLT128},
|
||||
/* DSC_ZTYPE_INT64 */ {DSC_ZTYPE_FLT128, DSC_ZTYPE_FLT128, DSC_ZTYPE_FIXED, DSC_ZTYPE_FIXED, DSC_ZTYPE_BAD, DSC_ZTYPE_BAD},
|
||||
/* DSC_ZTYPE_INT */ {DSC_ZTYPE_FLT128, DSC_ZTYPE_FLT128, DSC_ZTYPE_FIXED, DSC_ZTYPE_BAD, DSC_ZTYPE_BAD, DSC_ZTYPE_BAD},
|
||||
/* DSC_ZTYPE_OTHER */ {DSC_ZTYPE_FLT128, DSC_ZTYPE_FLT128, DSC_ZTYPE_FLT128, DSC_ZTYPE_BAD, DSC_ZTYPE_BAD, DSC_ZTYPE_BAD}
|
||||
};
|
||||
|
||||
UCHAR getFType(const dsc& desc)
|
||||
@ -527,8 +529,10 @@ UCHAR getFType(const dsc& desc)
|
||||
return DSC_ZTYPE_FLT64;
|
||||
case dtype_dec128:
|
||||
return DSC_ZTYPE_FLT128;
|
||||
case dtype_dec_fixed:
|
||||
case dtype_int128:
|
||||
return DSC_ZTYPE_FIXED;
|
||||
case dtype_int64:
|
||||
return DSC_ZTYPE_INT64;
|
||||
}
|
||||
|
||||
if (DTYPE_IS_EXACT(desc.dsc_dtype))
|
||||
@ -547,7 +551,7 @@ unsigned setDecDesc(dsc* desc, const dsc& desc1, const dsc& desc2, Scaling sc, S
|
||||
zipType = DSC_ZTYPE_FLT128; // In production case fallback to Decimal128
|
||||
|
||||
desc->dsc_dtype = zipType == DSC_ZTYPE_FLT64 ? dtype_dec64 :
|
||||
zipType == DSC_ZTYPE_FLT128 ? dtype_dec128 : dtype_dec_fixed;
|
||||
zipType == DSC_ZTYPE_FLT128 ? dtype_dec128 : dtype_int128;
|
||||
desc->dsc_sub_type = 0;
|
||||
desc->dsc_flags = (desc1.dsc_flags | desc2.dsc_flags) & DSC_nullable;
|
||||
desc->dsc_scale = 0;
|
||||
@ -569,9 +573,9 @@ unsigned setDecDesc(dsc* desc, const dsc& desc1, const dsc& desc2, Scaling sc, S
|
||||
*nodScale = desc->dsc_scale;
|
||||
|
||||
desc->dsc_length = zipType == DSC_ZTYPE_FLT64 ? sizeof(Decimal64) :
|
||||
zipType == DSC_ZTYPE_FLT128 ? sizeof(Decimal128) : sizeof(DecimalFixed);
|
||||
zipType == DSC_ZTYPE_FLT128 ? sizeof(Decimal128) : sizeof(Int128);
|
||||
|
||||
return zipType == DSC_ZTYPE_FIXED ? ExprNode::FLAG_DECFIXED : ExprNode::FLAG_DECFLOAT;
|
||||
return zipType == DSC_ZTYPE_FIXED ? ExprNode::FLAG_INT128 : ExprNode::FLAG_DECFLOAT;
|
||||
}
|
||||
|
||||
} // anon namespace
|
||||
@ -764,7 +768,7 @@ void ArithmeticNode::makeDialect1(dsc* desc, dsc& desc1, dsc& desc2)
|
||||
|
||||
case dtype_dec64:
|
||||
case dtype_dec128:
|
||||
case dtype_dec_fixed:
|
||||
case dtype_int128:
|
||||
setDecDesc(desc, desc1, desc2, SCALE_MIN);
|
||||
break;
|
||||
|
||||
@ -792,7 +796,7 @@ void ArithmeticNode::makeDialect1(dsc* desc, dsc& desc1, dsc& desc2)
|
||||
switch (dtype)
|
||||
{
|
||||
case dtype_dec128:
|
||||
case dtype_dec_fixed:
|
||||
case dtype_int128:
|
||||
setDecDesc(desc, desc1, desc2, SCALE_SUM);
|
||||
break;
|
||||
|
||||
@ -887,8 +891,8 @@ void ArithmeticNode::makeDialect3(dsc* desc, dsc& desc1, dsc& desc2)
|
||||
// <timestamp> arithmetic, but returns a <double>
|
||||
if (DTYPE_IS_EXACT(dtype1) && DTYPE_IS_EXACT(dtype2))
|
||||
{
|
||||
if (desc1.isDecFixed() || desc2.isDecFixed())
|
||||
dtype = dtype_dec_fixed;
|
||||
if (desc1.isInt128() || desc2.isInt128())
|
||||
dtype = dtype_int128;
|
||||
else
|
||||
dtype = dtype_int64;
|
||||
}
|
||||
@ -1027,7 +1031,7 @@ void ArithmeticNode::makeDialect3(dsc* desc, dsc& desc1, dsc& desc2)
|
||||
|
||||
case dtype_dec64:
|
||||
case dtype_dec128:
|
||||
case dtype_dec_fixed:
|
||||
case dtype_int128:
|
||||
setDecDesc(desc, desc1, desc2, SCALE_MIN);
|
||||
break;
|
||||
|
||||
@ -1076,7 +1080,7 @@ void ArithmeticNode::makeDialect3(dsc* desc, dsc& desc1, dsc& desc2)
|
||||
|
||||
switch (dtype)
|
||||
{
|
||||
case dtype_dec_fixed:
|
||||
case dtype_int128:
|
||||
case dtype_dec128:
|
||||
setDecDesc(desc, desc1, desc2, SCALE_SUM);
|
||||
break;
|
||||
@ -1135,7 +1139,7 @@ void ArithmeticNode::makeDialect3(dsc* desc, dsc& desc1, dsc& desc2)
|
||||
break;
|
||||
|
||||
case dtype_dec128:
|
||||
case dtype_dec_fixed:
|
||||
case dtype_int128:
|
||||
setDecDesc(desc, desc1, desc2, SCALE_SUM);
|
||||
break;
|
||||
|
||||
@ -1347,7 +1351,7 @@ void ArithmeticNode::getDescDialect1(thread_db* /*tdbb*/, dsc* desc, dsc& desc1,
|
||||
|
||||
case dtype_dec64:
|
||||
case dtype_dec128:
|
||||
case dtype_dec_fixed:
|
||||
case dtype_int128:
|
||||
nodFlags |= setDecDesc(desc, desc1, desc2, SCALE_MIN, &nodScale);
|
||||
break;
|
||||
|
||||
@ -1394,7 +1398,7 @@ void ArithmeticNode::getDescDialect1(thread_db* /*tdbb*/, dsc* desc, dsc& desc1,
|
||||
return;
|
||||
|
||||
case dtype_dec128:
|
||||
case dtype_dec_fixed:
|
||||
case dtype_int128:
|
||||
nodFlags |= setDecDesc(desc, desc1, desc2, SCALE_SUM, &nodScale);
|
||||
break;
|
||||
|
||||
@ -1469,8 +1473,8 @@ void ArithmeticNode::getDescDialect3(thread_db* /*tdbb*/, dsc* desc, dsc& desc1,
|
||||
|
||||
if (DTYPE_IS_EXACT(dtype1) && DTYPE_IS_EXACT(dtype2))
|
||||
{
|
||||
if (desc1.isDecFixed() || desc2.isDecFixed())
|
||||
dtype = dtype_dec_fixed;
|
||||
if (desc1.isInt128() || desc2.isInt128())
|
||||
dtype = dtype_int128;
|
||||
else
|
||||
dtype = dtype_int64;
|
||||
}
|
||||
@ -1620,7 +1624,7 @@ void ArithmeticNode::getDescDialect3(thread_db* /*tdbb*/, dsc* desc, dsc& desc1,
|
||||
|
||||
case dtype_dec64:
|
||||
case dtype_dec128:
|
||||
case dtype_dec_fixed:
|
||||
case dtype_int128:
|
||||
nodFlags |= setDecDesc(desc, desc1, desc2, SCALE_MIN, &nodScale);
|
||||
return;
|
||||
|
||||
@ -1674,7 +1678,7 @@ void ArithmeticNode::getDescDialect3(thread_db* /*tdbb*/, dsc* desc, dsc& desc1,
|
||||
return;
|
||||
|
||||
case dtype_dec128:
|
||||
case dtype_dec_fixed:
|
||||
case dtype_int128:
|
||||
nodFlags |= setDecDesc(desc, desc1, desc2, SCALE_SUM, &nodScale);
|
||||
return;
|
||||
|
||||
@ -1900,23 +1904,6 @@ dsc* ArithmeticNode::add(thread_db* tdbb, const dsc* desc, impure_value* value,
|
||||
return result;
|
||||
}
|
||||
|
||||
if (node->nodFlags & FLAG_DECFIXED)
|
||||
{
|
||||
const DecimalFixed d1 = MOV_get_dec_fixed(tdbb, desc, node->nodScale);
|
||||
const DecimalFixed d2 = MOV_get_dec_fixed(tdbb, &value->vlu_desc, node->nodScale);
|
||||
|
||||
DecimalStatus decSt = tdbb->getAttachment()->att_dec_status;
|
||||
value->vlu_misc.vlu_dec_fixed = (blrOp == blr_subtract) ? d2.sub(decSt, d1) : d1.add(decSt, d2);
|
||||
|
||||
result->dsc_dtype = dtype_dec_fixed;
|
||||
result->dsc_length = sizeof(DecimalFixed);
|
||||
result->dsc_scale = node->nodScale;
|
||||
result->dsc_sub_type = 0;
|
||||
result->dsc_address = (UCHAR*) &value->vlu_misc.vlu_dec_fixed;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Handle floating arithmetic
|
||||
|
||||
if (node->nodFlags & FLAG_DOUBLE)
|
||||
@ -1996,19 +1983,20 @@ dsc* ArithmeticNode::add2(thread_db* tdbb, const dsc* desc, impure_value* value,
|
||||
return result;
|
||||
}
|
||||
|
||||
if (node->nodFlags & FLAG_DECFIXED)
|
||||
// 128-bit arithmetic
|
||||
|
||||
if (node->nodFlags & FLAG_INT128)
|
||||
{
|
||||
const DecimalFixed d1 = MOV_get_dec_fixed(tdbb, desc, node->nodScale);
|
||||
const DecimalFixed d2 = MOV_get_dec_fixed(tdbb, &value->vlu_desc, node->nodScale);
|
||||
const Int128 d1 = MOV_get_int128(tdbb, desc, node->nodScale);
|
||||
const Int128 d2 = MOV_get_int128(tdbb, &value->vlu_desc, node->nodScale);
|
||||
|
||||
DecimalStatus decSt = tdbb->getAttachment()->att_dec_status;
|
||||
value->vlu_misc.vlu_dec_fixed = (blrOp == blr_subtract) ? d2.sub(decSt, d1) : d1.add(decSt, d2);
|
||||
value->vlu_misc.vlu_int128 = (blrOp == blr_subtract) ? d2.sub(d1) : d1.add(d2);
|
||||
|
||||
result->dsc_dtype = dtype_dec_fixed;
|
||||
result->dsc_length = sizeof(DecimalFixed);
|
||||
result->dsc_dtype = dtype_int128;
|
||||
result->dsc_length = sizeof(Int128);
|
||||
result->dsc_scale = node->nodScale;
|
||||
result->dsc_sub_type = 0;
|
||||
result->dsc_address = (UCHAR*) &value->vlu_misc.vlu_dec_fixed;
|
||||
result->dsc_address = (UCHAR*) &value->vlu_misc.vlu_int128;
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -2099,19 +2087,20 @@ dsc* ArithmeticNode::multiply(const dsc* desc, impure_value* value) const
|
||||
return &value->vlu_desc;
|
||||
}
|
||||
|
||||
if (nodFlags & FLAG_DECFIXED)
|
||||
// 128-bit arithmetic
|
||||
|
||||
if (nodFlags & FLAG_INT128)
|
||||
{
|
||||
const DecimalFixed d1 = MOV_get_dec_fixed(tdbb, desc, nodScale);
|
||||
const DecimalFixed d2 = MOV_get_dec_fixed(tdbb, &value->vlu_desc, nodScale);
|
||||
const Int128 d1 = MOV_get_int128(tdbb, desc, nodScale);
|
||||
const Int128 d2 = MOV_get_int128(tdbb, &value->vlu_desc, nodScale);
|
||||
|
||||
DecimalStatus decSt = tdbb->getAttachment()->att_dec_status;
|
||||
value->vlu_misc.vlu_dec_fixed = d1.mul(decSt, d2);
|
||||
value->vlu_misc.vlu_int128 = d1.mul(d2);
|
||||
|
||||
value->vlu_desc.dsc_dtype = dtype_dec_fixed;
|
||||
value->vlu_desc.dsc_length = sizeof(DecimalFixed);
|
||||
value->vlu_desc.dsc_dtype = dtype_int128;
|
||||
value->vlu_desc.dsc_length = sizeof(Int128);
|
||||
value->vlu_desc.dsc_scale = nodScale;
|
||||
value->vlu_desc.dsc_sub_type = 0;
|
||||
value->vlu_desc.dsc_address = (UCHAR*) &value->vlu_misc.vlu_dec_fixed;
|
||||
value->vlu_desc.dsc_address = (UCHAR*) &value->vlu_misc.vlu_int128;
|
||||
|
||||
return &value->vlu_desc;
|
||||
}
|
||||
@ -2210,20 +2199,21 @@ dsc* ArithmeticNode::multiply2(const dsc* desc, impure_value* value) const
|
||||
return &value->vlu_desc;
|
||||
}
|
||||
|
||||
if (nodFlags & FLAG_DECFIXED)
|
||||
// 128-bit arithmetic
|
||||
|
||||
if (nodFlags & FLAG_INT128)
|
||||
{
|
||||
const SSHORT scale = NUMERIC_SCALE(*desc);
|
||||
const DecimalFixed d1 = MOV_get_dec_fixed(tdbb, desc, scale);
|
||||
const DecimalFixed d2 = MOV_get_dec_fixed(tdbb, &value->vlu_desc, nodScale - scale);
|
||||
const Int128 d1 = MOV_get_int128(tdbb, desc, scale);
|
||||
const Int128 d2 = MOV_get_int128(tdbb, &value->vlu_desc, nodScale - scale);
|
||||
|
||||
DecimalStatus decSt = tdbb->getAttachment()->att_dec_status;
|
||||
value->vlu_misc.vlu_dec_fixed = d1.mul(decSt, d2);
|
||||
value->vlu_misc.vlu_int128 = d1.mul(d2);
|
||||
|
||||
value->vlu_desc.dsc_dtype = dtype_dec_fixed;
|
||||
value->vlu_desc.dsc_length = sizeof(DecimalFixed);
|
||||
value->vlu_desc.dsc_dtype = dtype_int128;
|
||||
value->vlu_desc.dsc_length = sizeof(Int128);
|
||||
value->vlu_desc.dsc_scale = nodScale;
|
||||
value->vlu_desc.dsc_sub_type = 0;
|
||||
value->vlu_desc.dsc_address = (UCHAR*) &value->vlu_misc.vlu_dec_fixed;
|
||||
value->vlu_desc.dsc_address = (UCHAR*) &value->vlu_misc.vlu_int128;
|
||||
|
||||
return &value->vlu_desc;
|
||||
}
|
||||
@ -2324,20 +2314,21 @@ dsc* ArithmeticNode::divide2(const dsc* desc, impure_value* value) const
|
||||
return &value->vlu_desc;
|
||||
}
|
||||
|
||||
if (nodFlags & FLAG_DECFIXED)
|
||||
// 128-bit arithmetic
|
||||
|
||||
if (nodFlags & FLAG_INT128)
|
||||
{
|
||||
const SSHORT scale = NUMERIC_SCALE(*desc);
|
||||
const DecimalFixed d2 = MOV_get_dec_fixed(tdbb, desc, scale);
|
||||
const DecimalFixed d1 = MOV_get_dec_fixed(tdbb, &value->vlu_desc, nodScale - scale);
|
||||
const Int128 d2 = MOV_get_int128(tdbb, desc, scale);
|
||||
const Int128 d1 = MOV_get_int128(tdbb, &value->vlu_desc, nodScale - scale);
|
||||
|
||||
DecimalStatus decSt = tdbb->getAttachment()->att_dec_status;
|
||||
value->vlu_misc.vlu_dec_fixed = d1.div(decSt, d2, scale * 2);
|
||||
value->vlu_misc.vlu_int128 = d1.div(d2, scale * 2);
|
||||
|
||||
value->vlu_desc.dsc_dtype = dtype_dec_fixed;
|
||||
value->vlu_desc.dsc_length = sizeof(DecimalFixed);
|
||||
value->vlu_desc.dsc_dtype = dtype_int128;
|
||||
value->vlu_desc.dsc_length = sizeof(Int128);
|
||||
value->vlu_desc.dsc_scale = nodScale;
|
||||
value->vlu_desc.dsc_sub_type = 0;
|
||||
value->vlu_desc.dsc_address = (UCHAR*) &value->vlu_misc.vlu_dec_fixed;
|
||||
value->vlu_desc.dsc_address = (UCHAR*) &value->vlu_misc.vlu_int128;
|
||||
|
||||
return &value->vlu_desc;
|
||||
}
|
||||
@ -7383,18 +7374,17 @@ DmlNode* LiteralNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch*
|
||||
case dtype_double:
|
||||
case dtype_dec128:
|
||||
{
|
||||
SSHORT scale;
|
||||
UCHAR dtype;
|
||||
|
||||
// The double literal could potentially be used for any numeric literal - the value is
|
||||
// passed as if it were a text string. Convert the numeric string to its binary value
|
||||
// (int64, long or double as appropriate).
|
||||
|
||||
l = csb->csb_blr_reader.getWord();
|
||||
q = csb->csb_blr_reader.getPos();
|
||||
dtype = CVT_get_numeric(q, l, &scale, p);
|
||||
SSHORT scale = 0;
|
||||
UCHAR dtype = CVT_get_numeric(q, l, &scale, p);
|
||||
node->litDesc.dsc_dtype = dtype;
|
||||
node->dsqlStr = FB_NEW_POOL(pool) IntlString(pool, string(q, l));
|
||||
node->litDesc.dsc_scale = (SCHAR) scale;
|
||||
|
||||
switch (dtype)
|
||||
{
|
||||
@ -7406,11 +7396,9 @@ DmlNode* LiteralNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch*
|
||||
break;
|
||||
case dtype_long:
|
||||
node->litDesc.dsc_length = sizeof(SLONG);
|
||||
node->litDesc.dsc_scale = (SCHAR) scale;
|
||||
break;
|
||||
default:
|
||||
node->litDesc.dsc_length = sizeof(SINT64);
|
||||
node->litDesc.dsc_scale = (SCHAR) scale;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -7846,25 +7834,34 @@ bool LiteralNode::sameAs(CompilerScratch* csb, const ExprNode* other, bool ignor
|
||||
|
||||
ValueExprNode* LiteralNode::pass2(thread_db* tdbb, CompilerScratch* csb)
|
||||
{
|
||||
if (DTYPE_IS_DECFLOAT(csb->csb_preferredDataType) && dsqlStr)
|
||||
if (csb->csb_preferredDesc && ((DTYPE_IS_DECFLOAT(csb->csb_preferredDesc->dsc_dtype) ||
|
||||
csb->csb_preferredDesc->dsc_dtype == dtype_int128) && dsqlStr))
|
||||
{
|
||||
const string& s(dsqlStr->getString());
|
||||
dsc desc;
|
||||
desc.makeText(s.length(), CS_ASCII, (UCHAR*) s.c_str());
|
||||
|
||||
switch (csb->csb_preferredDataType)
|
||||
switch (csb->csb_preferredDesc->dsc_dtype)
|
||||
{
|
||||
case dtype_dec64:
|
||||
*((Decimal64*) litDesc.dsc_address) = CVT_get_dec64(&desc,
|
||||
tdbb->getAttachment()->att_dec_status, ERR_post);
|
||||
litDesc.dsc_dtype = dtype_dec64;
|
||||
litDesc.dsc_scale = 0;
|
||||
break;
|
||||
|
||||
case dtype_dec128:
|
||||
case dtype_dec_fixed:
|
||||
*((Decimal128*) litDesc.dsc_address) = CVT_get_dec128(&desc,
|
||||
tdbb->getAttachment()->att_dec_status, ERR_post);
|
||||
litDesc.dsc_dtype = dtype_dec128;
|
||||
litDesc.dsc_scale = 0;
|
||||
break;
|
||||
|
||||
case dtype_int128:
|
||||
*((Int128*) litDesc.dsc_address) = CVT_get_int128(&desc,
|
||||
csb->csb_preferredDesc->dsc_scale, tdbb->getAttachment()->att_dec_status, ERR_post);
|
||||
litDesc.dsc_dtype = dtype_int128;
|
||||
litDesc.dsc_scale = csb->csb_preferredDesc->dsc_scale;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -8744,8 +8741,8 @@ dsc* NegateNode::execute(thread_db* tdbb, jrd_req* request) const
|
||||
impure->vlu_misc.vlu_dec128 = impure->vlu_misc.vlu_dec128.neg();
|
||||
break;
|
||||
|
||||
case dtype_dec_fixed:
|
||||
impure->vlu_misc.vlu_dec_fixed = impure->vlu_misc.vlu_dec_fixed.neg();
|
||||
case dtype_int128:
|
||||
impure->vlu_misc.vlu_int128 = impure->vlu_misc.vlu_int128.neg();
|
||||
break;
|
||||
|
||||
case dtype_int64:
|
||||
@ -11091,7 +11088,7 @@ void SubQueryNode::getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc)
|
||||
|
||||
case dtype_dec64:
|
||||
case dtype_dec128:
|
||||
case dtype_dec_fixed:
|
||||
case dtype_int128:
|
||||
desc->dsc_dtype = dtype_dec128;
|
||||
desc->dsc_length = sizeof(Decimal128);
|
||||
desc->dsc_scale = 0;
|
||||
|
@ -532,7 +532,7 @@ public:
|
||||
static const unsigned FLAG_DATE = 0x20;
|
||||
static const unsigned FLAG_DECFLOAT = 0x40;
|
||||
static const unsigned FLAG_VALUE = 0x80; // Full value area required in impure space.
|
||||
static const unsigned FLAG_DECFIXED = 0x100;
|
||||
static const unsigned FLAG_INT128 = 0x100;
|
||||
|
||||
explicit ExprNode(Type aType, MemoryPool& pool)
|
||||
: DmlNode(pool),
|
||||
|
@ -501,7 +501,7 @@ AssignmentNode* AssignmentNode::pass2(thread_db* tdbb, CompilerScratch* csb)
|
||||
{ // scope
|
||||
dsc desc;
|
||||
asgnTo->getDesc(tdbb, csb, &desc);
|
||||
AutoSetRestore<UCHAR> dataType(&csb->csb_preferredDataType, desc.dsc_dtype);
|
||||
AutoSetRestore<dsc*> dataType(&csb->csb_preferredDesc, &desc);
|
||||
ExprNode::doPass2(tdbb, csb, asgnFrom.getAddress());
|
||||
}
|
||||
ExprNode::doPass2(tdbb, csb, asgnTo.getAddress());
|
||||
@ -8360,11 +8360,14 @@ void SetDecFloatTrapsNode::execute(thread_db* tdbb, dsql_req* /*request*/, jrd_t
|
||||
//--------------------
|
||||
|
||||
|
||||
void SetDecFloatBindNode::execute(thread_db* tdbb, dsql_req* /*request*/, jrd_tra** /*traHandle*/) const
|
||||
void SetHighPrecBindNode::execute(thread_db* tdbb, dsql_req* /*request*/, jrd_tra** /*traHandle*/) const
|
||||
{
|
||||
SET_TDBB(tdbb);
|
||||
Attachment* const attachment = tdbb->getAttachment();
|
||||
attachment->att_dec_binding = bind;
|
||||
if (bindInt128)
|
||||
attachment->att_i128_binding = bind;
|
||||
else
|
||||
attachment->att_dec_binding = bind;
|
||||
}
|
||||
|
||||
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "../dsql/Nodes.h"
|
||||
#include "../dsql/DdlNodes.h"
|
||||
#include "../dsql/NodePrinter.h"
|
||||
#include "../common/DecFloat.h"
|
||||
|
||||
namespace Jrd {
|
||||
|
||||
@ -1748,11 +1749,13 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class SetDecFloatBindNode : public SessionManagementNode
|
||||
class SetHighPrecBindNode : public SessionManagementNode
|
||||
{
|
||||
public:
|
||||
SetDecFloatBindNode(MemoryPool& pool)
|
||||
: SessionManagementNode(pool)
|
||||
SetHighPrecBindNode(MemoryPool& pool, bool isInt128)
|
||||
: SessionManagementNode(pool),
|
||||
bind(Firebird::NumericBinding::NUM_NATIVE),
|
||||
bindInt128(isInt128)
|
||||
{
|
||||
}
|
||||
|
||||
@ -1764,13 +1767,14 @@ public:
|
||||
NODE_PRINT(printer, bind.bind);
|
||||
NODE_PRINT(printer, bind.numScale);
|
||||
|
||||
return "SetDecFloatBindNode";
|
||||
return "SetHighPrecBindNode";
|
||||
}
|
||||
|
||||
virtual void execute(thread_db* tdbb, dsql_req* request, jrd_tra** traHandle) const;
|
||||
|
||||
public:
|
||||
Firebird::DecimalBinding bind;
|
||||
Firebird::NumericBinding bind;
|
||||
bool bindInt128;
|
||||
};
|
||||
|
||||
|
||||
|
@ -60,7 +60,7 @@ const USHORT blr_dtypes[] = {
|
||||
blr_bool, // dtype_boolean
|
||||
blr_dec64, // dtype_dec64
|
||||
blr_dec128, // dtype_dec128
|
||||
blr_dec_fixed, // dtype_dec_fixed
|
||||
blr_int128, // dtype_int128
|
||||
blr_sql_time_tz, // dtype_sql_time_tz
|
||||
blr_timestamp_tz // dtype_timestamp_tz
|
||||
};
|
||||
|
@ -1148,7 +1148,7 @@ void dsql_req::mapInOut(thread_db* tdbb, bool toExternal, const dsql_msg* messag
|
||||
desc.dsc_address = dsql_msg_buf + (IPTR) desc.dsc_address;
|
||||
|
||||
if (notNull)
|
||||
MOVD_move(tdbb, &parDesc, &desc, toExternal);
|
||||
MOVD_move(tdbb, &parDesc, &desc);
|
||||
else
|
||||
memset(desc.dsc_address, 0, desc.dsc_length);
|
||||
}
|
||||
@ -1156,7 +1156,7 @@ void dsql_req::mapInOut(thread_db* tdbb, bool toExternal, const dsql_msg* messag
|
||||
{
|
||||
// Safe cast because desc is used as source only.
|
||||
desc.dsc_address = const_cast<UCHAR*>(in_dsql_msg_buf) + (IPTR) desc.dsc_address;
|
||||
MOVD_move(tdbb, &desc, &parDesc, toExternal);
|
||||
MOVD_move(tdbb, &desc, &parDesc);
|
||||
}
|
||||
else
|
||||
memset(parDesc.dsc_address, 0, parDesc.dsc_length);
|
||||
@ -1191,7 +1191,7 @@ void dsql_req::mapInOut(thread_db* tdbb, bool toExternal, const dsql_msg* messag
|
||||
dsc desc = parameter->par_desc;
|
||||
desc.dsc_address = msgBuffer + (IPTR) desc.dsc_address;
|
||||
|
||||
MOVD_move(tdbb, &parentDesc, &desc, false);
|
||||
MOVD_move(tdbb, &parentDesc, &desc);
|
||||
|
||||
dsql_par* null_ind = parameter->par_null;
|
||||
if (null_ind != NULL)
|
||||
@ -1221,7 +1221,7 @@ void dsql_req::mapInOut(thread_db* tdbb, bool toExternal, const dsql_msg* messag
|
||||
dsc desc = parameter->par_desc;
|
||||
desc.dsc_address = msgBuffer + (IPTR) desc.dsc_address;
|
||||
|
||||
MOVD_move(tdbb, &parentDesc, &desc, false);
|
||||
MOVD_move(tdbb, &parentDesc, &desc);
|
||||
|
||||
dsql_par* null_ind = parameter->par_null;
|
||||
if (null_ind != NULL)
|
||||
|
@ -256,8 +256,8 @@ public:
|
||||
precision = 18;
|
||||
break;
|
||||
|
||||
case dtype_dec_fixed:
|
||||
precision = 34;
|
||||
case dtype_int128:
|
||||
precision = 38;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -203,21 +203,24 @@ void GEN_port(DsqlCompilerScratch* dsqlScratch, dsql_msg* message)
|
||||
if (fromCharSet != toCharSet)
|
||||
parameter->par_desc.setTextType(toCharSet);
|
||||
}
|
||||
else if (parameter->par_desc.isDecFloat())
|
||||
else if (parameter->par_desc.isDecFloat() ||
|
||||
parameter->par_desc.dsc_dtype == dtype_int128)
|
||||
{
|
||||
const DecimalBinding& b = tdbb->getAttachment()->att_dec_binding;
|
||||
const NumericBinding& b(parameter->par_desc.dsc_dtype == dtype_int128 ?
|
||||
tdbb->getAttachment()->att_i128_binding : tdbb->getAttachment()->att_dec_binding);
|
||||
switch (b.bind)
|
||||
{
|
||||
case DecimalBinding::DEC_NATIVE:
|
||||
case NumericBinding::NUM_NATIVE:
|
||||
break;
|
||||
case DecimalBinding::DEC_TEXT:
|
||||
case NumericBinding::NUM_TEXT:
|
||||
parameter->par_desc.makeText((parameter->par_desc.dsc_dtype == dtype_dec64 ?
|
||||
IDecFloat16::STRING_SIZE : IDecFloat34::STRING_SIZE) - 1, ttype_ascii);
|
||||
IDecFloat16::STRING_SIZE : parameter->par_desc.dsc_dtype == dtype_dec128 ?
|
||||
IDecFloat34::STRING_SIZE : IInt128::STRING_SIZE) - 1, ttype_ascii);
|
||||
break;
|
||||
case DecimalBinding::DEC_DOUBLE:
|
||||
case NumericBinding::NUM_DOUBLE:
|
||||
parameter->par_desc.makeDouble();
|
||||
break;
|
||||
case DecimalBinding::DEC_NUMERIC:
|
||||
case NumericBinding::NUM_INT64:
|
||||
parameter->par_desc.makeInt64(b.numScale);
|
||||
break;
|
||||
}
|
||||
@ -415,8 +418,8 @@ void GEN_descriptor( DsqlCompilerScratch* dsqlScratch, const dsc* desc, bool tex
|
||||
dsqlScratch->appendUChar(blr_dec128);
|
||||
break;
|
||||
|
||||
case dtype_dec_fixed:
|
||||
dsqlScratch->appendUChar(blr_dec_fixed);
|
||||
case dtype_int128:
|
||||
dsqlScratch->appendUChar(blr_int128);
|
||||
dsqlScratch->appendUChar(desc->dsc_scale);
|
||||
break;
|
||||
|
||||
|
@ -33,11 +33,11 @@ using namespace Firebird;
|
||||
|
||||
|
||||
// Move (and possible convert) something to something else.
|
||||
void MOVD_move(thread_db* tdbb, dsc* from, dsc* to, bool toExternal)
|
||||
void MOVD_move(thread_db* tdbb, dsc* from, dsc* to)
|
||||
{
|
||||
try
|
||||
{
|
||||
MOV_move_ext(tdbb, from, to, toExternal);
|
||||
MOV_move(tdbb, from, to);
|
||||
}
|
||||
catch (const status_exception& ex)
|
||||
{
|
||||
|
@ -24,6 +24,6 @@
|
||||
#ifndef DSQL_MOVD_PROTO_H
|
||||
#define DSQL_MOVD_PROTO_H
|
||||
|
||||
void MOVD_move(Jrd::thread_db* tdbb, dsc*, dsc*, bool toExternal);
|
||||
void MOVD_move(Jrd::thread_db* tdbb, dsc*, dsc*);
|
||||
|
||||
#endif // DSQL_MOVD_PROTO_H
|
||||
|
@ -613,6 +613,7 @@ using namespace Firebird;
|
||||
%token <metaNamePtr> HEX_ENCODE
|
||||
%token <metaNamePtr> IDLE
|
||||
%token <metaNamePtr> INVOKER
|
||||
%token <metaNamePtr> INT128
|
||||
%token <metaNamePtr> IV
|
||||
%token <metaNamePtr> LAST_DAY
|
||||
%token <metaNamePtr> LEGACY
|
||||
@ -816,7 +817,7 @@ using namespace Firebird;
|
||||
Jrd::CreateAlterRoleNode* createAlterRoleNode;
|
||||
Jrd::SetDecFloatRoundNode* setDecFloatRoundNode;
|
||||
Jrd::SetDecFloatTrapsNode* setDecFloatTrapsNode;
|
||||
Jrd::SetDecFloatBindNode* setDecFloatBindNode;
|
||||
Jrd::SetHighPrecBindNode* setHighPrecBindNode;
|
||||
Jrd::SessionResetNode* sessionResetNode;
|
||||
}
|
||||
|
||||
@ -4224,6 +4225,7 @@ keyword_or_column
|
||||
| VAR_SAMP
|
||||
| VAR_POP
|
||||
| DECFLOAT // added in FB 4.0
|
||||
| INT128
|
||||
| LOCAL
|
||||
| LOCALTIME
|
||||
| LOCALTIMESTAMP
|
||||
@ -4971,14 +4973,14 @@ prec_scale
|
||||
{
|
||||
$$ = newNode<dsql_fld>();
|
||||
|
||||
if ($2 < 1 || $2 > 34)
|
||||
yyabandon(YYPOSNARG(2), -842, Arg::Gds(isc_precision_err2) << Arg::Num(1) << Arg::Num(34));
|
||||
// Precision must be between 1 and 34
|
||||
if ($2 < 1 || $2 > 38)
|
||||
yyabandon(YYPOSNARG(2), -842, Arg::Gds(isc_precision_err2) << Arg::Num(1) << Arg::Num(38));
|
||||
// Precision must be between 1 and 38
|
||||
|
||||
if ($2 > 18)
|
||||
{
|
||||
$$->dtype = dtype_dec_fixed;
|
||||
$$->length = sizeof(DecimalFixed);
|
||||
$$->dtype = dtype_int128;
|
||||
$$->length = sizeof(Int128);
|
||||
}
|
||||
else if ($2 > 9)
|
||||
{
|
||||
@ -5027,17 +5029,17 @@ prec_scale
|
||||
{
|
||||
$$ = newNode<dsql_fld>();
|
||||
|
||||
if ($2 < 1 || $2 > 34)
|
||||
yyabandon(YYPOSNARG(2), -842, Arg::Gds(isc_precision_err2) << Arg::Num(1) << Arg::Num(34));
|
||||
// Precision must be between 1 and 34
|
||||
if ($2 < 1 || $2 > 38)
|
||||
yyabandon(YYPOSNARG(2), -842, Arg::Gds(isc_precision_err2) << Arg::Num(1) << Arg::Num(38));
|
||||
// Precision must be between 1 and 38
|
||||
|
||||
if ($4 > $2 || $4 < 0)
|
||||
yyabandon(YYPOSNARG(4), -842, isc_scale_nogt); // Scale must be between 0 and precision
|
||||
|
||||
if ($2 > 18)
|
||||
{
|
||||
$$->dtype = dtype_dec_fixed;
|
||||
$$->length = sizeof(DecimalFixed);
|
||||
$$->dtype = dtype_int128;
|
||||
$$->length = sizeof(Int128);
|
||||
}
|
||||
else if ($2 > 9)
|
||||
{
|
||||
@ -5270,14 +5272,20 @@ set_decfloat_traps
|
||||
{ $$ = $5; }
|
||||
;
|
||||
|
||||
%type <setDecFloatBindNode> set_decfloat_bind
|
||||
%type <setHighPrecBindNode> set_decfloat_bind
|
||||
set_decfloat_bind
|
||||
: SET DECFLOAT BIND
|
||||
{ $$ = newNode<SetDecFloatBindNode>(); }
|
||||
: SET bind_to_type BIND
|
||||
{ $$ = newNode<SetHighPrecBindNode>($2); }
|
||||
decfloat_bind_clause($4)
|
||||
{ $$ = $4; }
|
||||
;
|
||||
|
||||
%type <boolVal> bind_to_type
|
||||
bind_to_type
|
||||
: DECFLOAT { $$ = false; }
|
||||
| INT128 { $$ = true; }
|
||||
;
|
||||
|
||||
%type decfloat_traps_list_opt(<setDecFloatTrapsNode>)
|
||||
decfloat_traps_list_opt($setDecFloatTrapsNode)
|
||||
: // nothing
|
||||
@ -5296,26 +5304,26 @@ decfloat_trap($setDecFloatTrapsNode)
|
||||
{ $setDecFloatTrapsNode->trap($1); }
|
||||
;
|
||||
|
||||
%type decfloat_bind_clause(<setDecFloatBindNode>)
|
||||
decfloat_bind_clause($setDecFloatBindNode)
|
||||
%type decfloat_bind_clause(<setHighPrecBindNode>)
|
||||
decfloat_bind_clause($setHighPrecBindNode)
|
||||
: NATIVE
|
||||
// do nothing
|
||||
| character_keyword
|
||||
{ $setDecFloatBindNode->bind.bind = DecimalBinding::DEC_TEXT; }
|
||||
{ $setHighPrecBindNode->bind.bind = NumericBinding::NUM_TEXT; }
|
||||
| DOUBLE PRECISION
|
||||
{ $setDecFloatBindNode->bind.bind = DecimalBinding::DEC_DOUBLE; }
|
||||
| BIGINT decfloat_scale_clause($setDecFloatBindNode)
|
||||
{ $setDecFloatBindNode->bind.bind = DecimalBinding::DEC_NUMERIC; }
|
||||
{ $setHighPrecBindNode->bind.bind = NumericBinding::NUM_DOUBLE; }
|
||||
| BIGINT decfloat_scale_clause($setHighPrecBindNode)
|
||||
{ $setHighPrecBindNode->bind.bind = NumericBinding::NUM_INT64; }
|
||||
;
|
||||
|
||||
%type decfloat_scale_clause(<setDecFloatBindNode>)
|
||||
decfloat_scale_clause($setDecFloatBindNode)
|
||||
%type decfloat_scale_clause(<setHighPrecBindNode>)
|
||||
decfloat_scale_clause($setHighPrecBindNode)
|
||||
: // nothing
|
||||
| ',' signed_long_integer
|
||||
{
|
||||
if ($2 > DecimalBinding::MAX_SCALE || $2 < 0)
|
||||
if ($2 > NumericBinding::MAX_SCALE || $2 < 0)
|
||||
yyabandon(YYPOSNARG(2), -842, isc_scale_nogt); // Scale must be between 0 and precision
|
||||
$setDecFloatBindNode->bind.numScale = -$2;
|
||||
$setHighPrecBindNode->bind.numScale = -$2;
|
||||
}
|
||||
|
||||
%type <setSessionNode> session_statement
|
||||
|
@ -34,6 +34,7 @@ typedef ISC_TIME_TZ;
|
||||
typedef ISC_TIMESTAMP_TZ;
|
||||
typedef FB_DEC16;
|
||||
typedef FB_DEC34;
|
||||
typedef FB_I128;
|
||||
typedef isc_tr_handle;
|
||||
typedef isc_stmt_handle;
|
||||
|
||||
@ -1093,7 +1094,7 @@ interface Util : Versioned
|
||||
XpbBuilder getXpbBuilder(Status status, uint kind, const uchar* buf, uint len);
|
||||
uint setOffsets(Status status, MessageMetadata metadata, OffsetsCallback callback);
|
||||
|
||||
version: // 3.0 => 4.0
|
||||
version: // 3.0 => 4.0 Alpha1
|
||||
DecFloat16 getDecFloat16(Status status);
|
||||
DecFloat34 getDecFloat34(Status status);
|
||||
Transaction getTransactionByHandle(Status status, isc_tr_handle* hndlPtr);
|
||||
@ -1106,6 +1107,9 @@ version: // 3.0 => 4.0
|
||||
uint fractions, const string timeZone);
|
||||
void encodeTimeStampTz(Status status, ISC_TIMESTAMP_TZ* timeStampTz, uint year, uint month, uint day,
|
||||
uint hours, uint minutes, uint seconds, uint fractions, const string timeZone);
|
||||
|
||||
version: // 4.0 Beta1 => 4.0 Beta2
|
||||
Int128 getInt128(Status status);
|
||||
}
|
||||
|
||||
interface OffsetsCallback : Versioned
|
||||
@ -1515,6 +1519,15 @@ interface DecFloat34 : Versioned
|
||||
void fromString(Status status, const string from, FB_DEC34* to);
|
||||
}
|
||||
|
||||
interface Int128 : Versioned
|
||||
{
|
||||
// - 170141183460469231731687303715884105728 e - 128 \0
|
||||
// 1 + 39 + 1 + 1 + 3 + 1 = 46
|
||||
const uint STRING_SIZE = 46; // includes terminating \0
|
||||
void toString(Status status, const FB_I128* from, int scale, uint bufferLength, string buffer);
|
||||
void fromString(Status status, int scale, const string from, FB_I128* to);
|
||||
}
|
||||
|
||||
// Replication interfaces
|
||||
|
||||
interface ReplicatedRecord : Versioned
|
||||
|
@ -116,6 +116,7 @@ namespace Firebird
|
||||
class IUdrPlugin;
|
||||
class IDecFloat16;
|
||||
class IDecFloat34;
|
||||
class IInt128;
|
||||
class IReplicatedRecord;
|
||||
class IReplicatedBlob;
|
||||
class IReplicatedTransaction;
|
||||
@ -4051,6 +4052,7 @@ namespace Firebird
|
||||
void (CLOOP_CARG *decodeTimeStampTz)(IUtil* self, IStatus* status, const ISC_TIMESTAMP_TZ* timeStampTz, unsigned* year, unsigned* month, unsigned* day, unsigned* hours, unsigned* minutes, unsigned* seconds, unsigned* fractions, unsigned timeZoneBufferLength, char* timeZoneBuffer) throw();
|
||||
void (CLOOP_CARG *encodeTimeTz)(IUtil* self, IStatus* status, ISC_TIME_TZ* timeTz, unsigned hours, unsigned minutes, unsigned seconds, unsigned fractions, const char* timeZone) throw();
|
||||
void (CLOOP_CARG *encodeTimeStampTz)(IUtil* self, IStatus* status, ISC_TIMESTAMP_TZ* timeStampTz, unsigned year, unsigned month, unsigned day, unsigned hours, unsigned minutes, unsigned seconds, unsigned fractions, const char* timeZone) throw();
|
||||
IInt128* (CLOOP_CARG *getInt128)(IUtil* self, IStatus* status) throw();
|
||||
};
|
||||
|
||||
protected:
|
||||
@ -4064,7 +4066,7 @@ namespace Firebird
|
||||
}
|
||||
|
||||
public:
|
||||
static const unsigned VERSION = 3;
|
||||
static const unsigned VERSION = 4;
|
||||
|
||||
template <typename StatusType> void getFbVersion(StatusType* status, IAttachment* att, IVersionCallback* callback)
|
||||
{
|
||||
@ -4259,6 +4261,20 @@ namespace Firebird
|
||||
static_cast<VTable*>(this->cloopVTable)->encodeTimeStampTz(this, status, timeStampTz, year, month, day, hours, minutes, seconds, fractions, timeZone);
|
||||
StatusType::checkException(status);
|
||||
}
|
||||
|
||||
template <typename StatusType> IInt128* getInt128(StatusType* status)
|
||||
{
|
||||
if (cloopVTable->version < 4)
|
||||
{
|
||||
StatusType::setVersionError(status, "IUtil", cloopVTable->version, 4);
|
||||
StatusType::checkException(status);
|
||||
return 0;
|
||||
}
|
||||
StatusType::clearException(status);
|
||||
IInt128* ret = static_cast<VTable*>(this->cloopVTable)->getInt128(this, status);
|
||||
StatusType::checkException(status);
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
class IOffsetsCallback : public IVersioned
|
||||
@ -5856,6 +5872,45 @@ namespace Firebird
|
||||
}
|
||||
};
|
||||
|
||||
class IInt128 : public IVersioned
|
||||
{
|
||||
public:
|
||||
struct VTable : public IVersioned::VTable
|
||||
{
|
||||
void (CLOOP_CARG *toString)(IInt128* self, IStatus* status, const FB_I128* from, int scale, unsigned bufferLength, char* buffer) throw();
|
||||
void (CLOOP_CARG *fromString)(IInt128* self, IStatus* status, int scale, const char* from, FB_I128* to) throw();
|
||||
};
|
||||
|
||||
protected:
|
||||
IInt128(DoNotInherit)
|
||||
: IVersioned(DoNotInherit())
|
||||
{
|
||||
}
|
||||
|
||||
~IInt128()
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
static const unsigned VERSION = 2;
|
||||
|
||||
static const unsigned STRING_SIZE = 46;
|
||||
|
||||
template <typename StatusType> void toString(StatusType* status, const FB_I128* from, int scale, unsigned bufferLength, char* buffer)
|
||||
{
|
||||
StatusType::clearException(status);
|
||||
static_cast<VTable*>(this->cloopVTable)->toString(this, status, from, scale, bufferLength, buffer);
|
||||
StatusType::checkException(status);
|
||||
}
|
||||
|
||||
template <typename StatusType> void fromString(StatusType* status, int scale, const char* from, FB_I128* to)
|
||||
{
|
||||
StatusType::clearException(status);
|
||||
static_cast<VTable*>(this->cloopVTable)->fromString(this, status, scale, from, to);
|
||||
StatusType::checkException(status);
|
||||
}
|
||||
};
|
||||
|
||||
class IReplicatedRecord : public IVersioned
|
||||
{
|
||||
public:
|
||||
@ -14332,6 +14387,7 @@ namespace Firebird
|
||||
this->decodeTimeStampTz = &Name::cloopdecodeTimeStampTzDispatcher;
|
||||
this->encodeTimeTz = &Name::cloopencodeTimeTzDispatcher;
|
||||
this->encodeTimeStampTz = &Name::cloopencodeTimeStampTzDispatcher;
|
||||
this->getInt128 = &Name::cloopgetInt128Dispatcher;
|
||||
}
|
||||
} vTable;
|
||||
|
||||
@ -14630,6 +14686,21 @@ namespace Firebird
|
||||
StatusType::catchException(&status2);
|
||||
}
|
||||
}
|
||||
|
||||
static IInt128* CLOOP_CARG cloopgetInt128Dispatcher(IUtil* self, IStatus* status) throw()
|
||||
{
|
||||
StatusType status2(status);
|
||||
|
||||
try
|
||||
{
|
||||
return static_cast<Name*>(self)->Name::getInt128(&status2);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
StatusType::catchException(&status2);
|
||||
return static_cast<IInt128*>(0);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Name, typename StatusType, typename Base = IVersionedImpl<Name, StatusType, Inherit<IUtil> > >
|
||||
@ -14666,6 +14737,7 @@ namespace Firebird
|
||||
virtual void decodeTimeStampTz(StatusType* status, const ISC_TIMESTAMP_TZ* timeStampTz, unsigned* year, unsigned* month, unsigned* day, unsigned* hours, unsigned* minutes, unsigned* seconds, unsigned* fractions, unsigned timeZoneBufferLength, char* timeZoneBuffer) = 0;
|
||||
virtual void encodeTimeTz(StatusType* status, ISC_TIME_TZ* timeTz, unsigned hours, unsigned minutes, unsigned seconds, unsigned fractions, const char* timeZone) = 0;
|
||||
virtual void encodeTimeStampTz(StatusType* status, ISC_TIMESTAMP_TZ* timeStampTz, unsigned year, unsigned month, unsigned day, unsigned hours, unsigned minutes, unsigned seconds, unsigned fractions, const char* timeZone) = 0;
|
||||
virtual IInt128* getInt128(StatusType* status) = 0;
|
||||
};
|
||||
|
||||
template <typename Name, typename StatusType, typename Base>
|
||||
@ -18081,6 +18153,73 @@ namespace Firebird
|
||||
virtual void fromString(StatusType* status, const char* from, FB_DEC34* to) = 0;
|
||||
};
|
||||
|
||||
template <typename Name, typename StatusType, typename Base>
|
||||
class IInt128BaseImpl : public Base
|
||||
{
|
||||
public:
|
||||
typedef IInt128 Declaration;
|
||||
|
||||
IInt128BaseImpl(DoNotInherit = DoNotInherit())
|
||||
{
|
||||
static struct VTableImpl : Base::VTable
|
||||
{
|
||||
VTableImpl()
|
||||
{
|
||||
this->version = Base::VERSION;
|
||||
this->toString = &Name::clooptoStringDispatcher;
|
||||
this->fromString = &Name::cloopfromStringDispatcher;
|
||||
}
|
||||
} vTable;
|
||||
|
||||
this->cloopVTable = &vTable;
|
||||
}
|
||||
|
||||
static void CLOOP_CARG clooptoStringDispatcher(IInt128* self, IStatus* status, const FB_I128* from, int scale, unsigned bufferLength, char* buffer) throw()
|
||||
{
|
||||
StatusType status2(status);
|
||||
|
||||
try
|
||||
{
|
||||
static_cast<Name*>(self)->Name::toString(&status2, from, scale, bufferLength, buffer);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
StatusType::catchException(&status2);
|
||||
}
|
||||
}
|
||||
|
||||
static void CLOOP_CARG cloopfromStringDispatcher(IInt128* self, IStatus* status, int scale, const char* from, FB_I128* to) throw()
|
||||
{
|
||||
StatusType status2(status);
|
||||
|
||||
try
|
||||
{
|
||||
static_cast<Name*>(self)->Name::fromString(&status2, scale, from, to);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
StatusType::catchException(&status2);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Name, typename StatusType, typename Base = IVersionedImpl<Name, StatusType, Inherit<IInt128> > >
|
||||
class IInt128Impl : public IInt128BaseImpl<Name, StatusType, Base>
|
||||
{
|
||||
protected:
|
||||
IInt128Impl(DoNotInherit = DoNotInherit())
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
virtual ~IInt128Impl()
|
||||
{
|
||||
}
|
||||
|
||||
virtual void toString(StatusType* status, const FB_I128* from, int scale, unsigned bufferLength, char* buffer) = 0;
|
||||
virtual void fromString(StatusType* status, int scale, const char* from, FB_I128* to) = 0;
|
||||
};
|
||||
|
||||
template <typename Name, typename StatusType, typename Base>
|
||||
class IReplicatedRecordBaseImpl : public Base
|
||||
{
|
||||
|
@ -69,7 +69,7 @@
|
||||
#define blr_bool (unsigned char)23
|
||||
#define blr_dec64 (unsigned char)24
|
||||
#define blr_dec128 (unsigned char)25
|
||||
#define blr_dec_fixed (unsigned char)26
|
||||
#define blr_int128 (unsigned char)26
|
||||
#define blr_sql_time_tz (unsigned char)28
|
||||
#define blr_timestamp_tz (unsigned char)29
|
||||
|
||||
|
@ -129,6 +129,7 @@
|
||||
#define isc_dpb_decfloat_bind 94
|
||||
#define isc_dpb_decfloat_round 95
|
||||
#define isc_dpb_decfloat_traps 96
|
||||
#define isc_dpb_int128_bind 97
|
||||
|
||||
|
||||
/**************************************************/
|
||||
|
@ -63,7 +63,7 @@
|
||||
#define dtype_boolean 21
|
||||
#define dtype_dec64 22
|
||||
#define dtype_dec128 23
|
||||
#define dtype_dec_fixed 24
|
||||
#define dtype_int128 24
|
||||
#define dtype_sql_time_tz 25
|
||||
#define dtype_timestamp_tz 26
|
||||
#define DTYPE_TYPE_MAX 27
|
||||
|
@ -78,9 +78,9 @@ typedef struct
|
||||
#define SQL_TYPE_TIME 560
|
||||
#define SQL_TYPE_DATE 570
|
||||
#define SQL_INT64 580
|
||||
#define SQL_INT128 32752
|
||||
#define SQL_TIMESTAMP_TZ 32754
|
||||
#define SQL_TIME_TZ 32756
|
||||
#define SQL_DEC_FIXED 32758
|
||||
#define SQL_DEC16 32760
|
||||
#define SQL_DEC34 32762
|
||||
#define SQL_BOOLEAN 32764
|
||||
|
@ -197,7 +197,12 @@ struct FB_DEC34_t {
|
||||
ISC_UINT64 fb_data[2];
|
||||
};
|
||||
|
||||
struct FB_I128_t {
|
||||
ISC_UINT64 fb_data[2];
|
||||
};
|
||||
|
||||
typedef struct FB_DEC16_t FB_DEC16;
|
||||
typedef struct FB_DEC34_t FB_DEC34;
|
||||
typedef struct FB_I128_t FB_I128;
|
||||
|
||||
#endif /* FIREBIRD_IMPL_TYPES_PUB_H */
|
||||
|
@ -320,6 +320,7 @@ IsqlGlobals::IsqlGlobals()
|
||||
|
||||
df16 = Firebird::UtilInterfacePtr()->getDecFloat16(&statusWrapper);
|
||||
df34 = Firebird::UtilInterfacePtr()->getDecFloat34(&statusWrapper);
|
||||
i128 = Firebird::UtilInterfacePtr()->getInt128(&statusWrapper);
|
||||
}
|
||||
|
||||
// I s q l G l o b a l s : : p r i n t f
|
||||
@ -1838,7 +1839,7 @@ bool ISQL_printNumericType(const char* fieldName, const int fieldType, const int
|
||||
case INTEGER:
|
||||
case BIGINT:
|
||||
case DOUBLE_PRECISION:
|
||||
case DEC_FIXED_TYPE:
|
||||
case blr_int128:
|
||||
// Handle Integral subtypes NUMERIC and DECIMAL
|
||||
// We are ODS >= 10 and could be any Dialect
|
||||
|
||||
@ -1872,8 +1873,8 @@ bool ISQL_printNumericType(const char* fieldName, const int fieldType, const int
|
||||
case DOUBLE_PRECISION:
|
||||
isqlGlob.printf("NUMERIC(15, %d)", -fieldScale);
|
||||
break;
|
||||
case DEC_FIXED_TYPE:
|
||||
isqlGlob.printf("NUMERIC(34, %d)", -fieldScale);
|
||||
case blr_int128:
|
||||
isqlGlob.printf("NUMERIC(38, %d)", -fieldScale);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -2288,6 +2289,7 @@ static processing_state add_row(TEXT* tabname)
|
||||
double* dvalue;
|
||||
FB_DEC16* d64value;
|
||||
FB_DEC34* d128value;
|
||||
FB_I128* i128value;
|
||||
UCHAR* boolean;
|
||||
ISC_QUAD* blobid;
|
||||
vary* avary;
|
||||
@ -2361,11 +2363,27 @@ static processing_state add_row(TEXT* tabname)
|
||||
if ((!isqlGlob.df16) || (fbStatus->getState() & Firebird::IStatus::STATE_ERRORS))
|
||||
{
|
||||
STDERROUT("Input parsing problem");
|
||||
ISQL_errmsg(fbStatus);
|
||||
done = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case SQL_INT128:
|
||||
scale = msg->getScale(fbStatus, i);
|
||||
if (ISQL_errmsg(fbStatus))
|
||||
return (SKIP);
|
||||
|
||||
i128value = (FB_I128*) datap;
|
||||
if (isqlGlob.i128)
|
||||
isqlGlob.i128->fromString(fbStatus, scale, lastInputLine, i128value);
|
||||
if ((!isqlGlob.i128) || (fbStatus->getState() & Firebird::IStatus::STATE_ERRORS))
|
||||
{
|
||||
STDERROUT("Input parsing problem");
|
||||
ISQL_errmsg(fbStatus);
|
||||
done = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case SQL_DEC_FIXED:
|
||||
case SQL_DEC34:
|
||||
d128value = (FB_DEC34*) datap;
|
||||
if (isqlGlob.df34)
|
||||
@ -2373,6 +2391,7 @@ static processing_state add_row(TEXT* tabname)
|
||||
if ((!isqlGlob.df34) || (fbStatus->getState() & Firebird::IStatus::STATE_ERRORS))
|
||||
{
|
||||
STDERROUT("Input parsing problem");
|
||||
ISQL_errmsg(fbStatus);
|
||||
done = true;
|
||||
}
|
||||
break;
|
||||
@ -3068,6 +3087,7 @@ static processing_state bulk_insert_hack(const char* command)
|
||||
tm times;
|
||||
FB_DEC16* d64value;
|
||||
FB_DEC34* d128value;
|
||||
FB_I128* i128value;
|
||||
// Initialize the time structure.
|
||||
memset(×, 0, sizeof(times));
|
||||
char msec_str[5] = "";
|
||||
@ -3134,18 +3154,38 @@ static processing_state bulk_insert_hack(const char* command)
|
||||
if ((!isqlGlob.df16) || (fbStatus->getState() & Firebird::IStatus::STATE_ERRORS))
|
||||
{
|
||||
STDERROUT("Input parsing problem");
|
||||
ISQL_errmsg(fbStatus);
|
||||
done = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case SQL_DEC34:
|
||||
case SQL_DEC_FIXED:
|
||||
d128value = (FB_DEC34*) datap;
|
||||
if (isqlGlob.df34)
|
||||
isqlGlob.df34->fromString(fbStatus, get_numeric_value(lastPos).c_str(), d128value);
|
||||
if ((!isqlGlob.df34) || (fbStatus->getState() & Firebird::IStatus::STATE_ERRORS))
|
||||
{
|
||||
STDERROUT("Input parsing problem");
|
||||
ISQL_errmsg(fbStatus);
|
||||
done = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case SQL_INT128:
|
||||
scale = message->getScale(fbStatus, i);
|
||||
if (ISQL_errmsg(fbStatus))
|
||||
return (SKIP);
|
||||
|
||||
i128value = (FB_I128*) datap;
|
||||
if (isqlGlob.i128)
|
||||
{
|
||||
isqlGlob.i128->fromString(fbStatus, scale,
|
||||
get_numeric_value(lastPos).c_str(), i128value);
|
||||
}
|
||||
if ((!isqlGlob.i128) || (fbStatus->getState() & Firebird::IStatus::STATE_ERRORS))
|
||||
{
|
||||
STDERROUT("Input parsing problem");
|
||||
ISQL_errmsg(fbStatus);
|
||||
done = true;
|
||||
}
|
||||
break;
|
||||
@ -7312,7 +7352,6 @@ static unsigned print_item(TEXT** s, const IsqlVar* var, const unsigned length)
|
||||
break;
|
||||
|
||||
case SQL_DEC34:
|
||||
case SQL_DEC_FIXED:
|
||||
{
|
||||
char decStr[Firebird::IDecFloat34::STRING_SIZE];
|
||||
if (isqlGlob.df34)
|
||||
@ -7325,9 +7364,34 @@ static unsigned print_item(TEXT** s, const IsqlVar* var, const unsigned length)
|
||||
strcpy(decStr, convErr);
|
||||
|
||||
if (setValues.List)
|
||||
isqlGlob.printf("%*.*s%s", sizeof(decStr) - 1, sizeof(decStr) - 1, decStr, NEWLINE);
|
||||
{
|
||||
isqlGlob.printf("%*.*s%s", int(sizeof(decStr) - 1), int(sizeof(decStr) - 1),
|
||||
decStr, NEWLINE);
|
||||
}
|
||||
else
|
||||
sprintf(p, "%*.*s ", sizeof(decStr) - 1, sizeof(decStr) - 1, decStr);
|
||||
sprintf(p, "%*.*s ", int(sizeof(decStr) - 1), int(sizeof(decStr) - 1), decStr);
|
||||
}
|
||||
break;
|
||||
|
||||
case SQL_INT128:
|
||||
{
|
||||
char intStr[Firebird::IInt128::STRING_SIZE];
|
||||
if (isqlGlob.i128)
|
||||
{
|
||||
isqlGlob.i128->toString(fbStatus, var->value.asInt128, dscale, sizeof(intStr), intStr);
|
||||
if (ISQL_errmsg(fbStatus))
|
||||
strcpy(intStr, convErr);
|
||||
}
|
||||
else
|
||||
strcpy(intStr, convErr);
|
||||
|
||||
if (setValues.List)
|
||||
{
|
||||
isqlGlob.printf("%*.*s%s", int(sizeof(intStr) - 1), int(sizeof(intStr) - 1),
|
||||
intStr, NEWLINE);
|
||||
}
|
||||
else
|
||||
sprintf(p, "%*.*s ", int(sizeof(intStr) - 1), int(sizeof(intStr) - 1), intStr);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -8169,7 +8233,9 @@ static unsigned process_message_display(Firebird::IMessageMetadata* message, uns
|
||||
case SQL_DEC16:
|
||||
disp_length = Firebird::IDecFloat16::STRING_SIZE - 1;
|
||||
break;
|
||||
case SQL_DEC_FIXED:
|
||||
case SQL_INT128:
|
||||
disp_length = Firebird::IInt128::STRING_SIZE - 1;
|
||||
break;
|
||||
case SQL_DEC34:
|
||||
disp_length = Firebird::IDecFloat34::STRING_SIZE - 1;
|
||||
break;
|
||||
@ -8847,8 +8913,8 @@ static const char* sqltype_to_string(unsigned sqltype)
|
||||
return "DECFLOAT(16)";
|
||||
case SQL_DEC34:
|
||||
return "DECFLOAT(34)";
|
||||
case SQL_DEC_FIXED:
|
||||
return "DECIMAL FIXED";
|
||||
case SQL_INT128:
|
||||
return "NUMERIC(38)";
|
||||
case SQL_D_FLOAT:
|
||||
return "D_FLOAT";
|
||||
case SQL_TIMESTAMP:
|
||||
|
@ -306,7 +306,6 @@ const int BIGINT = 16;
|
||||
const int BOOLEAN_TYPE = 23;
|
||||
const int DEC64_TYPE = 24;
|
||||
const int DEC128_TYPE = 25;
|
||||
const int DEC_FIXED_TYPE = 26;
|
||||
|
||||
static const sqltypes Column_types[] = {
|
||||
{SMALLINT, "SMALLINT"}, // keyword
|
||||
@ -326,7 +325,7 @@ static const sqltypes Column_types[] = {
|
||||
{BOOLEAN_TYPE, "BOOLEAN"}, // keyword
|
||||
{DEC64_TYPE, "DECFLOAT(16)"},
|
||||
{DEC128_TYPE, "DECFLOAT(34)"},
|
||||
{DEC_FIXED_TYPE, "<Should not be shown>"},
|
||||
{blr_int128, "INT64"},
|
||||
{blr_sql_time_tz, "TIME WITH TIME ZONE"}, // keyword
|
||||
{blr_timestamp_tz, "TIMESTAMP WITH TIME ZONE"}, // keyword
|
||||
{0, ""}
|
||||
@ -417,6 +416,7 @@ public:
|
||||
USHORT att_charset;
|
||||
Firebird::IDecFloat16* df16;
|
||||
Firebird::IDecFloat34* df34;
|
||||
Firebird::IInt128* i128;
|
||||
void printf(const char* buffer, ...);
|
||||
void prints(const char* buffer);
|
||||
|
||||
@ -478,6 +478,7 @@ struct IsqlVar
|
||||
char* asChar;
|
||||
FB_DEC16* asDec16;
|
||||
FB_DEC34* asDec34;
|
||||
FB_I128* asInt128;
|
||||
void* setPtr;
|
||||
};
|
||||
TypeMix value;
|
||||
|
@ -243,7 +243,7 @@ Jrd::Attachment::Attachment(MemoryPool* pool, Database* dbb, const InitialOption
|
||||
att_internal(*pool),
|
||||
att_dyn_req(*pool),
|
||||
att_dec_status(DecimalStatus::DEFAULT),
|
||||
att_dec_binding(DecimalBinding::DEFAULT),
|
||||
att_dec_binding(NumericBinding::DEFAULT),
|
||||
att_charsets(*pool),
|
||||
att_charset_ids(*pool),
|
||||
att_pools(*pool),
|
||||
|
@ -363,8 +363,11 @@ public:
|
||||
void resetAttachment(Attachment* attachment) const;
|
||||
|
||||
private:
|
||||
void setBinding(Firebird::string option, Firebird::NumericBinding& bind);
|
||||
|
||||
Firebird::DecimalStatus decFloatStatus = Firebird::DecimalStatus::DEFAULT;
|
||||
Firebird::DecimalBinding decFloatBinding = Firebird::DecimalBinding::DEFAULT;
|
||||
Firebird::NumericBinding decFloatBinding = Firebird::NumericBinding::DEFAULT;
|
||||
Firebird::NumericBinding int128Binding = Firebird::NumericBinding::DEFAULT;
|
||||
|
||||
Firebird::TimeZoneUtil::Bind timeZoneBind = Firebird::TimeZoneUtil::BIND_NATIVE;
|
||||
USHORT originalTimeZone = Firebird::TimeZoneUtil::GMT_ZONE;
|
||||
@ -466,7 +469,8 @@ public:
|
||||
Firebird::Array<JrdStatement*> att_dyn_req; // internal dyn statements
|
||||
Firebird::ICryptKeyCallback* att_crypt_callback; // callback for DB crypt
|
||||
Firebird::DecimalStatus att_dec_status; // error handling and rounding
|
||||
Firebird::DecimalBinding att_dec_binding; // use legacy datatype for DecFloat in outer world
|
||||
Firebird::NumericBinding att_dec_binding; // use legacy datatype for DecFloat in outer world
|
||||
Firebird::NumericBinding att_i128_binding; // use legacy datatype for INT128 in outer world
|
||||
|
||||
jrd_req* findSystemRequest(thread_db* tdbb, USHORT id, USHORT which);
|
||||
|
||||
|
@ -1570,9 +1570,6 @@ void ExtEngineManager::makeTrigger(thread_db* tdbb, CompilerScratch* csb, Jrd::T
|
||||
if (field)
|
||||
{
|
||||
dsc d(relFormat->fmt_desc[i]);
|
||||
if (d.dsc_dtype == dtype_dec_fixed)
|
||||
d.dsc_dtype = dtype_dec128;
|
||||
|
||||
fieldsMsg->addItem(field->fld_name, !field->fld_not_null, d);
|
||||
}
|
||||
}
|
||||
|
@ -109,10 +109,10 @@ namespace
|
||||
item.length = sizeof(Decimal128);
|
||||
break;
|
||||
|
||||
case dtype_dec_fixed:
|
||||
item.type = SQL_DEC_FIXED;
|
||||
case dtype_int128:
|
||||
item.type = SQL_INT128;
|
||||
item.scale = desc->dsc_scale;
|
||||
item.length = sizeof(DecimalFixed);
|
||||
item.length = sizeof(Int128);
|
||||
break;
|
||||
|
||||
case dtype_sql_date:
|
||||
|
@ -44,7 +44,7 @@ MsgMetadata* Routine::createMetadata(const Array<NestConst<Parameter> >& paramet
|
||||
++i)
|
||||
{
|
||||
dsc d((*i)->prm_desc);
|
||||
if (isExtern && d.dsc_dtype == dtype_dec_fixed)
|
||||
if (isExtern && d.dsc_dtype == dtype_int128)
|
||||
d.dsc_dtype = dtype_dec128;
|
||||
metadata->addItem((*i)->prm_name, (*i)->prm_nullable, d);
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ Maximum alignments for corresponding data types are defined in dsc.h
|
||||
*/
|
||||
|
||||
#include "../common/DecFloat.h"
|
||||
#include "../common/Int128.h"
|
||||
#include "firebird/impl/blr.h"
|
||||
|
||||
/* The following macro must be defined as the highest-numericly-valued
|
||||
@ -70,7 +71,7 @@ static const USHORT gds_cvt_blr_dtype[DTYPE_BLR_MAX + 1] =
|
||||
dtype_boolean, // blr_bool == 23
|
||||
dtype_dec64, /* blr_dec64 == 24 */
|
||||
dtype_dec128, /* blr_dec128 == 25 */
|
||||
dtype_dec_fixed, /* blr_dec_fixed == 26 */
|
||||
dtype_int128, /* blr_int128 == 26 */
|
||||
dtype_double, /* blr_double == 27 */
|
||||
dtype_sql_time_tz, /* blr_sql_time_tz == 28 */
|
||||
dtype_timestamp_tz, /* blr_timestamp_tz == 29 */
|
||||
@ -111,7 +112,7 @@ static const USHORT type_alignments[DTYPE_TYPE_MAX] =
|
||||
sizeof(UCHAR), /* dtype_boolean */
|
||||
sizeof(Firebird::Decimal64),/* dtype_dec64 */
|
||||
sizeof(Firebird::Decimal64),/* dtype_dec128 */
|
||||
sizeof(Firebird::Decimal64),/* dtype_dec_fixed */
|
||||
sizeof(Firebird::Decimal64),/* dtype_int128 */
|
||||
sizeof(GDS_TIME), /* dtype_sql_time_tz */
|
||||
sizeof(GDS_DATE) /* dtype_timestamp_tz */
|
||||
};
|
||||
@ -142,7 +143,7 @@ static const USHORT type_lengths[DTYPE_TYPE_MAX] =
|
||||
sizeof(UCHAR), /* dtype_boolean */
|
||||
sizeof(Firebird::Decimal64),/* dtype_dec64 */
|
||||
sizeof(Firebird::Decimal128),/*dtype_dec128 */
|
||||
sizeof(Firebird::DecimalFixed), /* dtype_dec_fixed */
|
||||
sizeof(Firebird::Int128), /* dtype_int128 */
|
||||
sizeof(ISC_TIME_TZ), /* dtype_sql_time_tz */
|
||||
sizeof(ISC_TIMESTAMP_TZ) /* dtype_timestamp_tz */
|
||||
};
|
||||
@ -176,7 +177,7 @@ static const USHORT type_significant_bits[DTYPE_TYPE_MAX] =
|
||||
0, // dtype_boolean
|
||||
0, // dtype_dec64
|
||||
0, // dtype_dec128
|
||||
0, // dtype_dec_fixed
|
||||
0, // dtype_int128
|
||||
0, // dtype_sql_time_tz
|
||||
0 // dtype_timestamp_tz
|
||||
};
|
||||
|
@ -223,19 +223,20 @@ UCHAR CVT_get_numeric(const UCHAR* string, const USHORT length, SSHORT* scale, v
|
||||
// tricky: the value doesn't always become negative after an
|
||||
// overflow!
|
||||
|
||||
if (value >= NUMERIC_LIMIT)
|
||||
if (!over)
|
||||
{
|
||||
// possibility of an overflow
|
||||
if ((value > NUMERIC_LIMIT) || (*p > '8' && sign == -1) || (*p > '7' && sign != -1))
|
||||
if (value >= NUMERIC_LIMIT)
|
||||
{
|
||||
over = true;
|
||||
break;
|
||||
// possibility of an overflow
|
||||
if ((value > NUMERIC_LIMIT) || (*p > '8' && sign == -1) || (*p > '7' && sign != -1))
|
||||
over = true;
|
||||
}
|
||||
|
||||
// Force the subtraction to be performed before the addition,
|
||||
// thus preventing a possible signed arithmetic overflow.
|
||||
value = value * 10 + (*p - '0');
|
||||
}
|
||||
|
||||
// Force the subtraction to be performed before the addition,
|
||||
// thus preventing a possible signed arithmetic overflow.
|
||||
value = value * 10 + (*p - '0');
|
||||
if (fraction)
|
||||
--local_scale;
|
||||
}
|
||||
@ -262,6 +263,8 @@ UCHAR CVT_get_numeric(const UCHAR* string, const USHORT length, SSHORT* scale, v
|
||||
if ((local_scale > MAX_SCHAR) || (local_scale < MIN_SCHAR))
|
||||
over = true;
|
||||
|
||||
*scale = local_scale;
|
||||
|
||||
if ((!over) && ((p < end) || // there is an exponent
|
||||
((value < 0) && (sign != -1)))) // MAX_SINT64+1 wrapped around
|
||||
{
|
||||
@ -278,8 +281,6 @@ UCHAR CVT_get_numeric(const UCHAR* string, const USHORT length, SSHORT* scale, v
|
||||
return dtype_dec128;
|
||||
}
|
||||
|
||||
*scale = local_scale;
|
||||
|
||||
// The literal has already been converted to a 64-bit integer: return
|
||||
// a long if the value fits into a long, else return an int64.
|
||||
|
||||
|
@ -85,7 +85,7 @@ const BYTE CVT2_compare_priority[] =
|
||||
9, // dtype_long
|
||||
// Move quad up by one to make room for int64 at its proper place in the table.
|
||||
11, // dtype_quad
|
||||
// Also leave space for dec_fixed, dec64 and dec 128.
|
||||
// Also leave space for int128, dec64 and dec 128.
|
||||
15, // dtype_real
|
||||
16, // dtype_double
|
||||
17, // dtype_d_float
|
||||
@ -99,8 +99,8 @@ const BYTE CVT2_compare_priority[] =
|
||||
10, // dtype_int64 - goes right after long
|
||||
25, // dtype_dbkey - compares with nothing except itself
|
||||
26, // dtype_boolean - compares with nothing except itself
|
||||
12, // dtype_dec_fixed - go after quad
|
||||
13, // dec64 - go after dtype_dec_fixed
|
||||
12, // dtype_int128 - go after quad
|
||||
13, // dec64 - go after dtype_int128
|
||||
14, // dec128 - go after dec64 and before real
|
||||
20, // dtype_sql_time_tz - go after dtype_sql_time
|
||||
22 // dtype_timestamp_tz - go after dtype_timestamp
|
||||
@ -305,8 +305,8 @@ int CVT2_compare(const dsc* arg1, const dsc* arg2, Firebird::DecimalStatus decSt
|
||||
case dtype_dec128:
|
||||
return ((Decimal128*) p1)->compare(decSt, *(Decimal128*) p2);
|
||||
|
||||
case dtype_dec_fixed:
|
||||
return ((DecimalFixed*) p1)->compare(decSt, *(DecimalFixed*) p2);
|
||||
case dtype_int128:
|
||||
return ((Int128*) p1)->compare(*(Int128*) p2);
|
||||
|
||||
case dtype_boolean:
|
||||
return *p1 == *p2 ? 0 : *p1 < *p2 ? -1 : 1;
|
||||
@ -564,7 +564,7 @@ int CVT2_compare(const dsc* arg1, const dsc* arg2, Firebird::DecimalStatus decSt
|
||||
return temp1.compare(decSt, temp2);
|
||||
}
|
||||
|
||||
case dtype_dec_fixed:
|
||||
case dtype_int128:
|
||||
{
|
||||
SSHORT scale;
|
||||
if (arg2->dsc_dtype > dtype_varying)
|
||||
@ -572,9 +572,9 @@ int CVT2_compare(const dsc* arg1, const dsc* arg2, Firebird::DecimalStatus decSt
|
||||
else
|
||||
scale = arg1->dsc_scale;
|
||||
|
||||
const DecimalFixed temp1 = CVT_get_dec_fixed(arg1, scale, decSt, ERR_post);
|
||||
const DecimalFixed temp2 = CVT_get_dec_fixed(arg2, scale, decSt, ERR_post);
|
||||
return temp1.compare(decSt, temp2);
|
||||
const Int128 temp1 = CVT_get_int128(arg1, scale, decSt, ERR_post);
|
||||
const Int128 temp2 = CVT_get_int128(arg2, scale, decSt, ERR_post);
|
||||
return temp1.compare(temp2);
|
||||
}
|
||||
|
||||
case dtype_blob:
|
||||
|
@ -1302,7 +1302,7 @@ USHORT DFW_assign_index_type(thread_db* tdbb, const Firebird::MetaName& name, SS
|
||||
return idx_boolean;
|
||||
case dtype_dec64:
|
||||
case dtype_dec128:
|
||||
case dtype_dec_fixed:
|
||||
case dtype_int128:
|
||||
return idx_decimal;
|
||||
default:
|
||||
return idx_numeric;
|
||||
|
@ -432,8 +432,8 @@ void EVL_make_value(thread_db* tdbb, const dsc* desc, impure_value* value, Memor
|
||||
value->vlu_misc.vlu_dec128 = *((Decimal128*) from.dsc_address);
|
||||
return;
|
||||
|
||||
case dtype_dec_fixed:
|
||||
value->vlu_misc.vlu_dec_fixed = *((DecimalFixed*) from.dsc_address);
|
||||
case dtype_int128:
|
||||
value->vlu_misc.vlu_int128 = *((Int128*) from.dsc_address);
|
||||
return;
|
||||
|
||||
case dtype_sql_time:
|
||||
|
@ -64,7 +64,6 @@ DEFINE_TRACE_ROUTINE(cmp_trace);
|
||||
#endif
|
||||
|
||||
class VaryingString;
|
||||
struct dsc;
|
||||
|
||||
namespace Jrd {
|
||||
|
||||
@ -463,7 +462,7 @@ public:
|
||||
csb_currentForNode(NULL),
|
||||
csb_currentDMLNode(NULL),
|
||||
csb_currentAssignTarget(NULL),
|
||||
csb_preferredDataType(0),
|
||||
csb_preferredDesc(NULL),
|
||||
csb_rpt(p)
|
||||
{
|
||||
csb_dbg_info = FB_NEW_POOL(p) Firebird::DbgInfo(p);
|
||||
@ -546,7 +545,7 @@ public:
|
||||
ForNode* csb_currentForNode;
|
||||
StmtNode* csb_currentDMLNode; // could be StoreNode or ModifyNode
|
||||
ExprNode* csb_currentAssignTarget;
|
||||
UCHAR csb_preferredDataType; // expected by receiving side datatype
|
||||
dsc* csb_preferredDesc; // expected by receiving side data format
|
||||
|
||||
struct csb_repeat
|
||||
{
|
||||
|
@ -606,7 +606,7 @@ void FUN_evaluate(thread_db* tdbb, const Function* function, const NestValueArra
|
||||
break;
|
||||
|
||||
case dtype_dec128:
|
||||
case dtype_dec_fixed:
|
||||
case dtype_int128:
|
||||
{
|
||||
const Decimal128 d = MOV_get_dec128(tdbb, input);
|
||||
if (parameter->prm_fun_mechanism == FUN_value)
|
||||
@ -820,21 +820,6 @@ void FUN_evaluate(thread_db* tdbb, const Function* function, const NestValueArra
|
||||
Arg::Str(function->getName().toString()));
|
||||
}
|
||||
break;
|
||||
|
||||
case dtype_dec_fixed:
|
||||
if (value->vlu_misc.vlu_dec_fixed.isInf())
|
||||
{
|
||||
status_exception::raise(Arg::Gds(isc_expression_eval_err) <<
|
||||
Arg::Gds(isc_udf_fp_overflow) <<
|
||||
Arg::Str(function->getName().toString()));
|
||||
}
|
||||
else if (value->vlu_misc.vlu_dec_fixed.isNan())
|
||||
{
|
||||
status_exception::raise(Arg::Gds(isc_expression_eval_err) <<
|
||||
Arg::Gds(isc_udf_fp_nan) <<
|
||||
Arg::Str(function->getName().toString()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
request->req_flags &= ~req_null;
|
||||
@ -1148,8 +1133,8 @@ static void invoke(thread_db* tdbb,
|
||||
value->vlu_misc.vlu_dec128 = CALL_UDF<Decimal128>(tdbb, function->fun_entrypoint, args);
|
||||
break;
|
||||
|
||||
case dtype_dec_fixed:
|
||||
value->vlu_misc.vlu_dec_fixed = CALL_UDF<DecimalFixed>(tdbb, function->fun_entrypoint, args);
|
||||
case dtype_int128:
|
||||
value->vlu_misc.vlu_int128 = CALL_UDF<Int128>(tdbb, function->fun_entrypoint, args);
|
||||
break;
|
||||
|
||||
case dtype_timestamp:
|
||||
|
@ -1020,6 +1020,7 @@ namespace Jrd
|
||||
string dpb_decfloat_bind;
|
||||
string dpb_decfloat_round;
|
||||
string dpb_decfloat_traps;
|
||||
string dpb_int128_bind;
|
||||
|
||||
public:
|
||||
static const ULONG DPB_FLAGS_MASK = DBB_damaged;
|
||||
@ -1062,6 +1063,43 @@ namespace Jrd
|
||||
}
|
||||
};
|
||||
|
||||
void Attachment::InitialOptions::setBinding(string option, NumericBinding& bind)
|
||||
{
|
||||
option.lower();
|
||||
|
||||
if (option == "native")
|
||||
bind = NumericBinding::DEFAULT;
|
||||
else if (option == "char" || option == "character")
|
||||
bind = NumericBinding(NumericBinding::NUM_TEXT);
|
||||
else if (option == "double" || option == "double precision")
|
||||
bind = NumericBinding(NumericBinding::NUM_DOUBLE);
|
||||
else if (option == "bigint")
|
||||
bind = NumericBinding(NumericBinding::NUM_INT64);
|
||||
else if (option.substr(0, 7) == "bigint,")
|
||||
{
|
||||
const char* p = option.c_str() + 7;
|
||||
|
||||
while (*p == ' ')
|
||||
++p;
|
||||
|
||||
const char* start = p;
|
||||
int scale = 0;
|
||||
|
||||
while (*p >= '0' && *p <= '9')
|
||||
{
|
||||
scale = scale * 10 + (*p - '0');
|
||||
++p;
|
||||
}
|
||||
|
||||
if (*p != '\0' || p - start == 0 || p - start > 2 || scale > NumericBinding::MAX_SCALE)
|
||||
(Arg::Gds(isc_invalid_decfloat_bind) << option).raise();
|
||||
|
||||
bind = NumericBinding(NumericBinding::NUM_INT64, static_cast<SCHAR>(-scale));
|
||||
}
|
||||
else
|
||||
(Arg::Gds(isc_invalid_decfloat_bind) << option).raise();
|
||||
}
|
||||
|
||||
Attachment::InitialOptions::InitialOptions(const DatabaseOptions& options)
|
||||
{
|
||||
if (options.dpb_time_zone_bind.hasData())
|
||||
@ -1078,42 +1116,10 @@ namespace Jrd
|
||||
}
|
||||
|
||||
if (options.dpb_decfloat_bind.hasData())
|
||||
{
|
||||
auto option = options.dpb_decfloat_bind;
|
||||
option.lower();
|
||||
setBinding(options.dpb_decfloat_bind, decFloatBinding);
|
||||
|
||||
if (option == "native")
|
||||
decFloatBinding = DecimalBinding::DEFAULT;
|
||||
else if (option == "char" || option == "character")
|
||||
decFloatBinding = DecimalBinding(DecimalBinding::DEC_TEXT);
|
||||
else if (option == "double" || option == "double precision")
|
||||
decFloatBinding = DecimalBinding(DecimalBinding::DEC_DOUBLE);
|
||||
else if (option == "bigint")
|
||||
decFloatBinding = DecimalBinding(DecimalBinding::DEC_NUMERIC);
|
||||
else if (option.substr(0, 7) == "bigint,")
|
||||
{
|
||||
const char* p = option.c_str() + 7;
|
||||
|
||||
while (*p == ' ')
|
||||
++p;
|
||||
|
||||
const char* start = p;
|
||||
int scale = 0;
|
||||
|
||||
while (*p >= '0' && *p <= '9')
|
||||
{
|
||||
scale = scale * 10 + (*p - '0');
|
||||
++p;
|
||||
}
|
||||
|
||||
if (*p != '\0' || p - start == 0 || p - start > 2 || scale > DecimalBinding::MAX_SCALE)
|
||||
(Arg::Gds(isc_invalid_decfloat_bind) << option).raise();
|
||||
|
||||
decFloatBinding = DecimalBinding(DecimalBinding::DEC_NUMERIC, static_cast<SCHAR>(-scale));
|
||||
}
|
||||
else
|
||||
(Arg::Gds(isc_invalid_decfloat_bind) << option).raise();
|
||||
}
|
||||
if (options.dpb_int128_bind.hasData())
|
||||
setBinding(options.dpb_int128_bind, int128Binding);
|
||||
|
||||
if (options.dpb_decfloat_round.hasData())
|
||||
{
|
||||
@ -1172,6 +1178,7 @@ namespace Jrd
|
||||
// reset DecFloat options
|
||||
attachment->att_dec_status = decFloatStatus;
|
||||
attachment->att_dec_binding = decFloatBinding;
|
||||
attachment->att_i128_binding = int128Binding;
|
||||
|
||||
// reset time zone options
|
||||
attachment->att_timezone_bind = timeZoneBind;
|
||||
@ -6969,6 +6976,10 @@ void DatabaseOptions::get(const UCHAR* dpb, USHORT dpb_length, bool& invalid_cli
|
||||
rdr.getString(dpb_decfloat_bind);
|
||||
break;
|
||||
|
||||
case isc_dpb_int128_bind:
|
||||
rdr.getString(dpb_int128_bind);
|
||||
break;
|
||||
|
||||
case isc_dpb_decfloat_round:
|
||||
rdr.getString(dpb_decfloat_round);
|
||||
break;
|
||||
|
@ -450,42 +450,6 @@ void MOV_move(Jrd::thread_db* tdbb, /*const*/ dsc* from, dsc* to)
|
||||
}
|
||||
|
||||
|
||||
void MOV_move_ext(Jrd::thread_db* tdbb, /*const*/ dsc* from, dsc* to, bool toExtern)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* M O V _ m o v e _ e x t
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Move data to/from outer world.
|
||||
*
|
||||
**************************************/
|
||||
|
||||
MOV_move(tdbb, from, to);
|
||||
|
||||
switch (to->dsc_dtype)
|
||||
{
|
||||
case dtype_dec_fixed:
|
||||
if (toExtern)
|
||||
{
|
||||
((Decimal128*) to->dsc_address)->setScale(tdbb->getAttachment()->att_dec_status,
|
||||
to->dsc_scale);
|
||||
}
|
||||
else
|
||||
{
|
||||
((DecimalFixed*) to->dsc_address)->exactInt(tdbb->getAttachment()->att_dec_status,
|
||||
to->dsc_scale);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Decimal64 MOV_get_dec64(Jrd::thread_db* tdbb, const dsc* desc)
|
||||
{
|
||||
/**************************************
|
||||
@ -510,7 +474,7 @@ Decimal128 MOV_get_dec128(Jrd::thread_db* tdbb, const dsc* desc)
|
||||
}
|
||||
|
||||
|
||||
DecimalFixed MOV_get_dec_fixed(Jrd::thread_db* tdbb, const dsc* desc, SSHORT scale)
|
||||
Int128 MOV_get_int128(Jrd::thread_db* tdbb, const dsc* desc, SSHORT scale)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -518,7 +482,7 @@ DecimalFixed MOV_get_dec_fixed(Jrd::thread_db* tdbb, const dsc* desc, SSHORT sca
|
||||
*
|
||||
**************************************/
|
||||
|
||||
return CVT_get_dec_fixed(desc, scale, tdbb->getAttachment()->att_dec_status, ERR_post);
|
||||
return CVT_get_int128(desc, scale, tdbb->getAttachment()->att_dec_status, ERR_post);
|
||||
}
|
||||
|
||||
|
||||
|
@ -52,10 +52,9 @@ int MOV_make_string2(Jrd::thread_db*, const dsc*, USHORT, UCHAR**, Jrd::MoveBuf
|
||||
Firebird::string MOV_make_string2(Jrd::thread_db* tdbb, const dsc* desc, USHORT ttype,
|
||||
bool limit = true);
|
||||
void MOV_move(Jrd::thread_db*, /*const*/ dsc*, dsc*);
|
||||
void MOV_move_ext(Jrd::thread_db* tdbb, /*const*/ dsc* from, dsc* to, bool toExtern);
|
||||
Firebird::Decimal64 MOV_get_dec64(Jrd::thread_db*, const dsc*);
|
||||
Firebird::Decimal128 MOV_get_dec128(Jrd::thread_db*, const dsc*);
|
||||
Firebird::DecimalFixed MOV_get_dec_fixed(Jrd::thread_db*, const dsc*, SSHORT);
|
||||
Firebird::Int128 MOV_get_int128(Jrd::thread_db*, const dsc*, SSHORT);
|
||||
|
||||
namespace Jrd
|
||||
{
|
||||
|
@ -419,7 +419,7 @@ static const UCHAR sort_dtypes[] =
|
||||
SKD_bytes, // dtype_boolean
|
||||
SKD_dec64, // dtype_dec64
|
||||
SKD_dec128, // dtype_dec128
|
||||
SKD_dec128, // dtype_dec_fixed
|
||||
SKD_int128, // dtype_int128
|
||||
SKD_sql_time_tz, // dtype_sql_time_tz
|
||||
SKD_timestamp_tz // dtype_timestamp_tz
|
||||
};
|
||||
|
@ -405,9 +405,9 @@ USHORT PAR_datatype(BlrReader& blrReader, dsc* desc)
|
||||
desc->dsc_length = sizeof(Decimal128);
|
||||
break;
|
||||
|
||||
case blr_dec_fixed:
|
||||
desc->dsc_dtype = dtype_dec_fixed;
|
||||
desc->dsc_length = sizeof(DecimalFixed);
|
||||
case blr_int128:
|
||||
desc->dsc_dtype = dtype_int128;
|
||||
desc->dsc_length = sizeof(Int128);
|
||||
desc->dsc_scale = (int) blrReader.getByte();
|
||||
break;
|
||||
|
||||
|
@ -804,6 +804,7 @@ void Sort::diddleKey(UCHAR* record, bool direction, bool duplicateHandling)
|
||||
case SKD_timestamp:
|
||||
case SKD_sql_date:
|
||||
case SKD_int64:
|
||||
case SKD_int128:
|
||||
*p ^= 1 << 7;
|
||||
break;
|
||||
|
||||
@ -1047,6 +1048,24 @@ void Sort::diddleKey(UCHAR* record, bool direction, bool duplicateHandling)
|
||||
SWAP_LONGS(lwp[0], lwp[1], lw);
|
||||
break;
|
||||
|
||||
case SKD_int128:
|
||||
// INT128 fits in four long, and hence two swaps should happen
|
||||
// here for the right order comparison using DO_32_COMPARE
|
||||
if (!direction)
|
||||
{
|
||||
SWAP_LONGS(lwp[0], lwp[3], lw);
|
||||
SWAP_LONGS(lwp[1], lwp[2], lw);
|
||||
}
|
||||
|
||||
p[15] ^= 1 << 7;
|
||||
|
||||
if (direction)
|
||||
{
|
||||
SWAP_LONGS(lwp[0], lwp[3], lw);
|
||||
SWAP_LONGS(lwp[1], lwp[2], lw);
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef IEEE
|
||||
case SKD_double:
|
||||
if (!direction)
|
||||
|
@ -145,6 +145,7 @@ const int SKD_dec64 = 16;
|
||||
const int SKD_dec128 = 17;
|
||||
const int SKD_sql_time_tz = 18;
|
||||
const int SKD_timestamp_tz = 19;
|
||||
const int SKD_int128 = 20;
|
||||
|
||||
// skd_flags
|
||||
const UCHAR SKD_ascending = 0; // default initializer
|
||||
|
@ -85,7 +85,7 @@ struct impure_value
|
||||
double vlu_double;
|
||||
Firebird::Decimal64 vlu_dec64;
|
||||
Firebird::Decimal128 vlu_dec128;
|
||||
Firebird::DecimalFixed vlu_dec_fixed;
|
||||
Firebird::Int128 vlu_int128;
|
||||
GDS_TIMESTAMP vlu_timestamp;
|
||||
ISC_TIMESTAMP_TZ vlu_timestamp_tz;
|
||||
GDS_TIME vlu_sql_time;
|
||||
@ -101,7 +101,7 @@ struct impure_value
|
||||
void make_int64(const SINT64 val, const signed char scale = 0);
|
||||
void make_double(const double val);
|
||||
void make_decimal128(const Firebird::Decimal128 val);
|
||||
void make_decimal_fixed(const Firebird::DecimalFixed val, const signed char scale);
|
||||
void make_decimal_fixed(const Firebird::Int128 val, const signed char scale);
|
||||
};
|
||||
|
||||
// Do not use these methods where dsc_sub_type is not explicitly set to zero.
|
||||
@ -145,14 +145,14 @@ inline void impure_value::make_decimal128(const Firebird::Decimal128 val)
|
||||
this->vlu_desc.dsc_address = reinterpret_cast<UCHAR*>(&this->vlu_misc.vlu_dec128);
|
||||
}
|
||||
|
||||
inline void impure_value::make_decimal_fixed(const Firebird::DecimalFixed val, const signed char scale)
|
||||
inline void impure_value::make_decimal_fixed(const Firebird::Int128 val, const signed char scale)
|
||||
{
|
||||
this->vlu_misc.vlu_dec_fixed = val;
|
||||
this->vlu_desc.dsc_dtype = dtype_dec_fixed;
|
||||
this->vlu_desc.dsc_length = sizeof(Firebird::DecimalFixed);
|
||||
this->vlu_misc.vlu_int128 = val;
|
||||
this->vlu_desc.dsc_dtype = dtype_int128;
|
||||
this->vlu_desc.dsc_length = sizeof(Firebird::Int128);
|
||||
this->vlu_desc.dsc_scale = scale;
|
||||
this->vlu_desc.dsc_sub_type = 0;
|
||||
this->vlu_desc.dsc_address = reinterpret_cast<UCHAR*>(&this->vlu_misc.vlu_dec_fixed);
|
||||
this->vlu_desc.dsc_address = reinterpret_cast<UCHAR*>(&this->vlu_misc.vlu_int128);
|
||||
}
|
||||
|
||||
struct impure_value_ex : public impure_value
|
||||
|
@ -17,7 +17,7 @@
|
||||
ISC_QUAD = array [1..2] of Integer;
|
||||
FB_DEC16 = array [1..1] of Int64;
|
||||
FB_DEC34 = array [1..2] of Int64;
|
||||
FB_DEC_FIXED = array [1..2] of Int64;
|
||||
FB_INT128 = array [1..2] of Int64;
|
||||
|
||||
isc_tr_handle = ^integer32;
|
||||
isc_stmt_handle = ^integer32;
|
||||
|
@ -127,10 +127,10 @@ void BlrFromMessage::buildBlr(IMessageMetadata* metadata)
|
||||
dtype = dtype_dec128;
|
||||
break;
|
||||
|
||||
case SQL_DEC_FIXED:
|
||||
appendUChar(blr_dec_fixed);
|
||||
case SQL_INT128:
|
||||
appendUChar(blr_int128);
|
||||
appendUChar(scale);
|
||||
dtype = dtype_dec_fixed;
|
||||
dtype = dtype_int128;
|
||||
break;
|
||||
|
||||
case SQL_DOUBLE:
|
||||
|
@ -300,11 +300,11 @@ static rem_fmt* parse_format(const UCHAR*& blr, size_t& blr_length)
|
||||
align = type_alignments[dtype_dec128];
|
||||
break;
|
||||
|
||||
case blr_dec_fixed:
|
||||
desc->dsc_dtype = dtype_dec_fixed;
|
||||
desc->dsc_length = sizeof(DecimalFixed);
|
||||
case blr_int128:
|
||||
desc->dsc_dtype = dtype_int128;
|
||||
desc->dsc_length = sizeof(Int128);
|
||||
desc->dsc_scale = *blr++;
|
||||
align = type_alignments[dtype_dec_fixed];
|
||||
align = type_alignments[dtype_int128];
|
||||
break;
|
||||
|
||||
// this case cannot occur as switch paramater is char and blr_blob
|
||||
|
@ -762,7 +762,7 @@ void TracePluginImpl::appendParams(ITraceParams* params)
|
||||
case dtype_dec128:
|
||||
paramtype = "decfloat(34)";
|
||||
break;
|
||||
case dtype_dec_fixed:
|
||||
case dtype_int128:
|
||||
paramtype = "decimal";
|
||||
break;
|
||||
|
||||
@ -887,11 +887,10 @@ void TracePluginImpl::appendParams(ITraceParams* params)
|
||||
((Decimal128*) parameters->dsc_address)->toString(paramvalue);
|
||||
break;
|
||||
|
||||
case dtype_dec_fixed:
|
||||
case dtype_int128:
|
||||
try
|
||||
{
|
||||
DecimalStatus decSt(FB_DEC_Errors);
|
||||
((DecimalFixed*) parameters->dsc_address)->toString(decSt, parameters->dsc_scale, paramvalue);
|
||||
((Int128*) parameters->dsc_address)->toString(parameters->dsc_scale, paramvalue);
|
||||
}
|
||||
catch (const Exception& ex)
|
||||
{
|
||||
|
@ -686,6 +686,7 @@ public:
|
||||
void encodeTimeStampTz(Firebird::CheckStatusWrapper* status, ISC_TIMESTAMP_TZ* timeStampTz,
|
||||
unsigned year, unsigned month, unsigned day,
|
||||
unsigned hours, unsigned minutes, unsigned seconds, unsigned fractions, const char* timeZone);
|
||||
Firebird::IInt128* getInt128(Firebird::CheckStatusWrapper* status);
|
||||
};
|
||||
|
||||
} // namespace Why
|
||||
|
@ -60,6 +60,7 @@
|
||||
#include "../common/classes/TempFile.h"
|
||||
#include "../common/utils_proto.h"
|
||||
#include "../common/ThreadStart.h"
|
||||
#include "../common/Int128.h"
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
@ -3034,9 +3035,9 @@ static int blr_print_dtype(gds_ctl* control)
|
||||
length = sizeof(Firebird::Decimal64);
|
||||
break;
|
||||
|
||||
case blr_dec_fixed:
|
||||
string = "dec_fixed";
|
||||
length = sizeof(Firebird::DecimalFixed);
|
||||
case blr_int128:
|
||||
string = "int128";
|
||||
length = sizeof(Firebird::Int128);
|
||||
break;
|
||||
|
||||
case blr_domain_name:
|
||||
@ -3100,7 +3101,7 @@ static int blr_print_dtype(gds_ctl* control)
|
||||
case blr_long:
|
||||
case blr_quad:
|
||||
case blr_int64:
|
||||
case blr_dec_fixed:
|
||||
case blr_int128:
|
||||
blr_print_byte(control);
|
||||
break;
|
||||
|
||||
|
@ -1303,6 +1303,49 @@ IDecFloat34* UtilInterface::getDecFloat34(CheckStatusWrapper* status)
|
||||
return &decFloat34;
|
||||
}
|
||||
|
||||
class IfaceInt128 FB_FINAL : public AutoIface<IInt128Impl<IfaceInt128, CheckStatusWrapper> >
|
||||
{
|
||||
public:
|
||||
// IInt128 implementation
|
||||
void toString(CheckStatusWrapper* status, const FB_I128* from, int scale, unsigned bufSize, char* buffer)
|
||||
{
|
||||
try
|
||||
{
|
||||
const Int128* i128 = (Int128*)from;
|
||||
i128->toString(scale, bufSize, buffer);
|
||||
}
|
||||
catch (const Exception& ex)
|
||||
{
|
||||
ex.stuffException(status);
|
||||
}
|
||||
}
|
||||
|
||||
void fromString(CheckStatusWrapper* status, int scale, const char* from, FB_I128* to)
|
||||
{
|
||||
try
|
||||
{
|
||||
Int128* i128 = (Int128*)to;
|
||||
scale -= CVT_decompose(from, static_cast<USHORT>(strlen(from)), i128, errorFunction);
|
||||
i128->setScale(scale);
|
||||
}
|
||||
catch (const Exception& ex)
|
||||
{
|
||||
ex.stuffException(status);
|
||||
}
|
||||
}
|
||||
|
||||
static void errorFunction(const Arg::StatusVector& v)
|
||||
{
|
||||
v.raise();
|
||||
}
|
||||
};
|
||||
|
||||
IInt128* UtilInterface::getInt128(CheckStatusWrapper* status)
|
||||
{
|
||||
static IfaceInt128 ifaceInt128;
|
||||
return &ifaceInt128;
|
||||
}
|
||||
|
||||
unsigned UtilInterface::setOffsets(CheckStatusWrapper* status, IMessageMetadata* metadata,
|
||||
IOffsetsCallback* callback)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user