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: for /r %%i in (*.bat) do unix2dos "%%i"
|
||||||
- cmd: if "%PLATFORM%" == "x64" set FB_PROCESSOR_ARCHITECTURE=AMD64
|
- cmd: if "%PLATFORM%" == "x64" set FB_PROCESSOR_ARCHITECTURE=AMD64
|
||||||
- cmd: if "%PLATFORM%" == "x64" set FB_OUTPUT_SUFFIX=x64
|
- 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_PROCESSOR_ARCHITECTURE=x86
|
||||||
- cmd: if "%PLATFORM%" == "x86" set FB_OUTPUT_SUFFIX=win32
|
- 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: cd builds\win32
|
||||||
- cmd: run_all.bat JUSTBUILD
|
- cmd: run_all.bat JUSTBUILD
|
||||||
- cmd: set ARTIFACTS_PATH=output_%FB_OUTPUT_SUFFIX%
|
- cmd: set ARTIFACTS_PATH=output_%FB_OUTPUT_SUFFIX%
|
||||||
|
@ -41,6 +41,9 @@ if "%ERRLEV%"=="1" goto :END
|
|||||||
call :decNumber
|
call :decNumber
|
||||||
if "%ERRLEV%"=="1" goto :END
|
if "%ERRLEV%"=="1" goto :END
|
||||||
|
|
||||||
|
if "%FB_TARGET_PLATFORM%"=="x64" call :ttmath
|
||||||
|
if "%ERRLEV%"=="1" goto :END
|
||||||
|
|
||||||
call :re2
|
call :re2
|
||||||
if "%ERRLEV%"=="1" goto :END
|
if "%ERRLEV%"=="1" goto :END
|
||||||
|
|
||||||
@ -162,6 +165,23 @@ if errorlevel 1 call :boot2 decNumber_%FB_OBJ_DIR%
|
|||||||
@call set_build_target.bat %*
|
@call set_build_target.bat %*
|
||||||
goto :EOF
|
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
|
:: BUILD re2
|
||||||
:re2
|
:re2
|
||||||
|
@ -72,6 +72,7 @@
|
|||||||
<ClCompile Include="..\..\..\src\common\DynamicStrings.cpp" />
|
<ClCompile Include="..\..\..\src\common\DynamicStrings.cpp" />
|
||||||
<ClCompile Include="..\..\..\src\common\enc.cpp" />
|
<ClCompile Include="..\..\..\src\common\enc.cpp" />
|
||||||
<ClCompile Include="..\..\..\src\common\fb_exception.cpp" />
|
<ClCompile Include="..\..\..\src\common\fb_exception.cpp" />
|
||||||
|
<ClCompile Include="..\..\..\src\common\Int128.cpp" />
|
||||||
<ClCompile Include="..\..\..\src\common\IntlParametersBlock.cpp" />
|
<ClCompile Include="..\..\..\src\common\IntlParametersBlock.cpp" />
|
||||||
<ClCompile Include="..\..\..\src\common\IntlUtil.cpp" />
|
<ClCompile Include="..\..\..\src\common\IntlUtil.cpp" />
|
||||||
<ClCompile Include="..\..\..\src\common\isc.cpp" />
|
<ClCompile Include="..\..\..\src\common\isc.cpp" />
|
||||||
@ -180,6 +181,7 @@
|
|||||||
<ClInclude Include="..\..\..\src\common\enc_proto.h" />
|
<ClInclude Include="..\..\..\src\common\enc_proto.h" />
|
||||||
<ClInclude Include="..\..\..\src\common\file_params.h" />
|
<ClInclude Include="..\..\..\src\common\file_params.h" />
|
||||||
<ClInclude Include="..\..\..\src\common\gdsassert.h" />
|
<ClInclude Include="..\..\..\src\common\gdsassert.h" />
|
||||||
|
<ClInclude Include="..\..\..\src\common\Int128.h" />
|
||||||
<ClInclude Include="..\..\..\src\common\intlobj_new.h" />
|
<ClInclude Include="..\..\..\src\common\intlobj_new.h" />
|
||||||
<ClInclude Include="..\..\..\src\common\IntlParametersBlock.h" />
|
<ClInclude Include="..\..\..\src\common\IntlParametersBlock.h" />
|
||||||
<ClInclude Include="..\..\..\src\common\IntlUtil.h" />
|
<ClInclude Include="..\..\..\src\common\IntlUtil.h" />
|
||||||
@ -335,7 +337,7 @@
|
|||||||
<Culture>0x041d</Culture>
|
<Culture>0x041d</Culture>
|
||||||
</ResourceCompile>
|
</ResourceCompile>
|
||||||
<Lib>
|
<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>
|
</Lib>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
@ -353,7 +355,7 @@
|
|||||||
<Culture>0x041d</Culture>
|
<Culture>0x041d</Culture>
|
||||||
</ResourceCompile>
|
</ResourceCompile>
|
||||||
<Lib>
|
<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>
|
</Lib>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
@ -240,6 +240,9 @@
|
|||||||
<ClCompile Include="..\..\..\src\common\keywords.cpp">
|
<ClCompile Include="..\..\..\src\common\keywords.cpp">
|
||||||
<Filter>common</Filter>
|
<Filter>common</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\src\common\Int128.cpp">
|
||||||
|
<Filter>common</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\..\..\src\common\xdr_proto.h">
|
<ClInclude Include="..\..\..\src\common\xdr_proto.h">
|
||||||
@ -581,5 +584,8 @@
|
|||||||
<ClInclude Include="..\..\..\src\common\keywords.h">
|
<ClInclude Include="..\..\..\src\common\keywords.h">
|
||||||
<Filter>headers</Filter>
|
<Filter>headers</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\src\common\Int128.h">
|
||||||
|
<Filter>headers</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
@ -68,6 +68,7 @@
|
|||||||
<ClCompile Include="..\..\..\src\common\DynamicStrings.cpp" />
|
<ClCompile Include="..\..\..\src\common\DynamicStrings.cpp" />
|
||||||
<ClCompile Include="..\..\..\src\common\enc.cpp" />
|
<ClCompile Include="..\..\..\src\common\enc.cpp" />
|
||||||
<ClCompile Include="..\..\..\src\common\fb_exception.cpp" />
|
<ClCompile Include="..\..\..\src\common\fb_exception.cpp" />
|
||||||
|
<ClCompile Include="..\..\..\src\common\Int128.cpp" />
|
||||||
<ClCompile Include="..\..\..\src\common\IntlParametersBlock.cpp" />
|
<ClCompile Include="..\..\..\src\common\IntlParametersBlock.cpp" />
|
||||||
<ClCompile Include="..\..\..\src\common\IntlUtil.cpp" />
|
<ClCompile Include="..\..\..\src\common\IntlUtil.cpp" />
|
||||||
<ClCompile Include="..\..\..\src\common\isc.cpp" />
|
<ClCompile Include="..\..\..\src\common\isc.cpp" />
|
||||||
@ -176,6 +177,7 @@
|
|||||||
<ClInclude Include="..\..\..\src\common\enc_proto.h" />
|
<ClInclude Include="..\..\..\src\common\enc_proto.h" />
|
||||||
<ClInclude Include="..\..\..\src\common\file_params.h" />
|
<ClInclude Include="..\..\..\src\common\file_params.h" />
|
||||||
<ClInclude Include="..\..\..\src\common\gdsassert.h" />
|
<ClInclude Include="..\..\..\src\common\gdsassert.h" />
|
||||||
|
<ClInclude Include="..\..\..\src\common\Int128.h" />
|
||||||
<ClInclude Include="..\..\..\src\common\intlobj_new.h" />
|
<ClInclude Include="..\..\..\src\common\intlobj_new.h" />
|
||||||
<ClInclude Include="..\..\..\src\common\IntlParametersBlock.h" />
|
<ClInclude Include="..\..\..\src\common\IntlParametersBlock.h" />
|
||||||
<ClInclude Include="..\..\..\src\common\IntlUtil.h" />
|
<ClInclude Include="..\..\..\src\common\IntlUtil.h" />
|
||||||
@ -335,7 +337,7 @@
|
|||||||
<Culture>0x041d</Culture>
|
<Culture>0x041d</Culture>
|
||||||
</ResourceCompile>
|
</ResourceCompile>
|
||||||
<Lib>
|
<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>
|
</Lib>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
@ -353,7 +355,7 @@
|
|||||||
<Culture>0x041d</Culture>
|
<Culture>0x041d</Culture>
|
||||||
</ResourceCompile>
|
</ResourceCompile>
|
||||||
<Lib>
|
<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>
|
</Lib>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
@ -240,6 +240,9 @@
|
|||||||
<ClCompile Include="..\..\..\src\common\keywords.cpp">
|
<ClCompile Include="..\..\..\src\common\keywords.cpp">
|
||||||
<Filter>common</Filter>
|
<Filter>common</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\src\common\Int128.cpp">
|
||||||
|
<Filter>common</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\..\..\src\common\xdr_proto.h">
|
<ClInclude Include="..\..\..\src\common\xdr_proto.h">
|
||||||
@ -581,5 +584,8 @@
|
|||||||
<ClInclude Include="..\..\..\src\common\classes\ParsedList.h">
|
<ClInclude Include="..\..\..\src\common\classes\ParsedList.h">
|
||||||
<Filter>headers</Filter>
|
<Filter>headers</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\src\common\Int128.h">
|
||||||
|
<Filter>headers</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
@ -68,6 +68,7 @@
|
|||||||
<ClCompile Include="..\..\..\src\common\DynamicStrings.cpp" />
|
<ClCompile Include="..\..\..\src\common\DynamicStrings.cpp" />
|
||||||
<ClCompile Include="..\..\..\src\common\enc.cpp" />
|
<ClCompile Include="..\..\..\src\common\enc.cpp" />
|
||||||
<ClCompile Include="..\..\..\src\common\fb_exception.cpp" />
|
<ClCompile Include="..\..\..\src\common\fb_exception.cpp" />
|
||||||
|
<ClCompile Include="..\..\..\src\common\Int128.cpp" />
|
||||||
<ClCompile Include="..\..\..\src\common\IntlParametersBlock.cpp" />
|
<ClCompile Include="..\..\..\src\common\IntlParametersBlock.cpp" />
|
||||||
<ClCompile Include="..\..\..\src\common\IntlUtil.cpp" />
|
<ClCompile Include="..\..\..\src\common\IntlUtil.cpp" />
|
||||||
<ClCompile Include="..\..\..\src\common\isc.cpp" />
|
<ClCompile Include="..\..\..\src\common\isc.cpp" />
|
||||||
@ -177,6 +178,7 @@
|
|||||||
<ClInclude Include="..\..\..\src\common\enc_proto.h" />
|
<ClInclude Include="..\..\..\src\common\enc_proto.h" />
|
||||||
<ClInclude Include="..\..\..\src\common\file_params.h" />
|
<ClInclude Include="..\..\..\src\common\file_params.h" />
|
||||||
<ClInclude Include="..\..\..\src\common\gdsassert.h" />
|
<ClInclude Include="..\..\..\src\common\gdsassert.h" />
|
||||||
|
<ClInclude Include="..\..\..\src\common\Int128.h" />
|
||||||
<ClInclude Include="..\..\..\src\common\intlobj_new.h" />
|
<ClInclude Include="..\..\..\src\common\intlobj_new.h" />
|
||||||
<ClInclude Include="..\..\..\src\common\IntlParametersBlock.h" />
|
<ClInclude Include="..\..\..\src\common\IntlParametersBlock.h" />
|
||||||
<ClInclude Include="..\..\..\src\common\IntlUtil.h" />
|
<ClInclude Include="..\..\..\src\common\IntlUtil.h" />
|
||||||
@ -337,7 +339,7 @@
|
|||||||
<Culture>0x041d</Culture>
|
<Culture>0x041d</Culture>
|
||||||
</ResourceCompile>
|
</ResourceCompile>
|
||||||
<Lib>
|
<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>
|
</Lib>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
@ -355,7 +357,7 @@
|
|||||||
<Culture>0x041d</Culture>
|
<Culture>0x041d</Culture>
|
||||||
</ResourceCompile>
|
</ResourceCompile>
|
||||||
<Lib>
|
<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>
|
</Lib>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
@ -243,6 +243,9 @@
|
|||||||
<ClCompile Include="..\..\..\src\common\keywords.cpp">
|
<ClCompile Include="..\..\..\src\common\keywords.cpp">
|
||||||
<Filter>common</Filter>
|
<Filter>common</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\src\common\Int128.cpp">
|
||||||
|
<Filter>common</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\..\..\src\common\xdr_proto.h">
|
<ClInclude Include="..\..\..\src\common\xdr_proto.h">
|
||||||
@ -587,5 +590,8 @@
|
|||||||
<ClInclude Include="..\..\..\src\common\keywords.h">
|
<ClInclude Include="..\..\..\src\common\keywords.h">
|
||||||
<Filter>headers</Filter>
|
<Filter>headers</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\src\common\Int128.h">
|
||||||
|
<Filter>headers</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -68,6 +68,7 @@
|
|||||||
<ClCompile Include="..\..\..\src\common\DynamicStrings.cpp" />
|
<ClCompile Include="..\..\..\src\common\DynamicStrings.cpp" />
|
||||||
<ClCompile Include="..\..\..\src\common\enc.cpp" />
|
<ClCompile Include="..\..\..\src\common\enc.cpp" />
|
||||||
<ClCompile Include="..\..\..\src\common\fb_exception.cpp" />
|
<ClCompile Include="..\..\..\src\common\fb_exception.cpp" />
|
||||||
|
<ClCompile Include="..\..\..\src\common\Int128.cpp" />
|
||||||
<ClCompile Include="..\..\..\src\common\IntlParametersBlock.cpp" />
|
<ClCompile Include="..\..\..\src\common\IntlParametersBlock.cpp" />
|
||||||
<ClCompile Include="..\..\..\src\common\IntlUtil.cpp" />
|
<ClCompile Include="..\..\..\src\common\IntlUtil.cpp" />
|
||||||
<ClCompile Include="..\..\..\src\common\isc.cpp" />
|
<ClCompile Include="..\..\..\src\common\isc.cpp" />
|
||||||
@ -177,6 +178,7 @@
|
|||||||
<ClInclude Include="..\..\..\src\common\enc_proto.h" />
|
<ClInclude Include="..\..\..\src\common\enc_proto.h" />
|
||||||
<ClInclude Include="..\..\..\src\common\file_params.h" />
|
<ClInclude Include="..\..\..\src\common\file_params.h" />
|
||||||
<ClInclude Include="..\..\..\src\common\gdsassert.h" />
|
<ClInclude Include="..\..\..\src\common\gdsassert.h" />
|
||||||
|
<ClInclude Include="..\..\..\src\common\Int128.h" />
|
||||||
<ClInclude Include="..\..\..\src\common\intlobj_new.h" />
|
<ClInclude Include="..\..\..\src\common\intlobj_new.h" />
|
||||||
<ClInclude Include="..\..\..\src\common\IntlParametersBlock.h" />
|
<ClInclude Include="..\..\..\src\common\IntlParametersBlock.h" />
|
||||||
<ClInclude Include="..\..\..\src\common\IntlUtil.h" />
|
<ClInclude Include="..\..\..\src\common\IntlUtil.h" />
|
||||||
@ -338,7 +340,7 @@
|
|||||||
<Culture>0x041d</Culture>
|
<Culture>0x041d</Culture>
|
||||||
</ResourceCompile>
|
</ResourceCompile>
|
||||||
<Lib>
|
<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>
|
</Lib>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
@ -356,7 +358,7 @@
|
|||||||
<Culture>0x041d</Culture>
|
<Culture>0x041d</Culture>
|
||||||
</ResourceCompile>
|
</ResourceCompile>
|
||||||
<Lib>
|
<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>
|
</Lib>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
@ -243,6 +243,9 @@
|
|||||||
<ClCompile Include="..\..\..\src\common\keywords.cpp">
|
<ClCompile Include="..\..\..\src\common\keywords.cpp">
|
||||||
<Filter>common</Filter>
|
<Filter>common</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\src\common\Int128.cpp">
|
||||||
|
<Filter>common</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\..\..\src\common\xdr_proto.h">
|
<ClInclude Include="..\..\..\src\common\xdr_proto.h">
|
||||||
@ -587,5 +590,8 @@
|
|||||||
<ClInclude Include="..\..\..\src\common\keywords.h">
|
<ClInclude Include="..\..\..\src\common\keywords.h">
|
||||||
<Filter>headers</Filter>
|
<Filter>headers</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\src\common\Int128.h">
|
||||||
|
<Filter>headers</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
@ -200,7 +200,7 @@ Enhancement in precision of calculations with NUMERIC/DECIMAL (FB 4.0)
|
|||||||
--------------
|
--------------
|
||||||
|
|
||||||
Function:
|
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:
|
Author:
|
||||||
Alex Peshkoff <peshkoff@mail.ru>
|
Alex Peshkoff <peshkoff@mail.ru>
|
||||||
@ -208,20 +208,35 @@ Enhancement in precision of calculations with NUMERIC/DECIMAL (FB 4.0)
|
|||||||
Syntax rules:
|
Syntax rules:
|
||||||
NUMERIC ( P {, N} )
|
NUMERIC ( P {, N} )
|
||||||
DECIMAL ( 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).
|
of digits after decimal separator (as before).
|
||||||
|
|
||||||
Storage:
|
Storage:
|
||||||
128-bit, format according to IEEE 754.
|
128-bit signed integer.
|
||||||
|
|
||||||
Example(s):
|
Example(s):
|
||||||
1. DECLARE VARIABLE VAR1 DECIMAL(25);
|
1. DECLARE VARIABLE VAR1 DECIMAL(25);
|
||||||
2. CREATE TABLE TABLE1 (FIELD1 NUMERIC(34, 17));
|
2. CREATE TABLE TABLE1 (FIELD1 NUMERIC(38, 19));
|
||||||
|
|
||||||
Note(s):
|
Note(s):
|
||||||
Numerics with precision less than 19 digits use SMALLINT, INTEGER, BIGINT or DOUBLE PRECISION
|
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
|
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
|
38 digits 128-bit integer is used for it. Actual precision is always increased to 38 digits.
|
||||||
complex calculations such digits are casted (internally, in trivial way) to DECFLOAT(34) and
|
For complex calculations such digits are casted (internally) to DECFLOAT(34) and the result of
|
||||||
the result of various math (log, exp, etc.) and aggregate functions using high precision
|
various math (log, exp, etc.) and aggregate functions using high precision numeric argument is
|
||||||
numeric argument is DECFLOAT(34).
|
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);
|
add_byte(blr, field->fld_scale);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case blr_dec_fixed:
|
case blr_int128:
|
||||||
alignment = type_alignments[dtype_dec_fixed];
|
alignment = type_alignments[dtype_int128];
|
||||||
add_byte(blr, field->fld_type);
|
add_byte(blr, field->fld_type);
|
||||||
add_byte(blr, field->fld_scale);
|
add_byte(blr, field->fld_scale);
|
||||||
break;
|
break;
|
||||||
|
@ -170,11 +170,15 @@ ULONG CAN_encode_decode(burp_rel* relation, lstring* buffer, UCHAR* data, bool d
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case dtype_dec128:
|
case dtype_dec128:
|
||||||
case dtype_dec_fixed:
|
|
||||||
if (!xdr_dec128(xdrs, (Firebird::Decimal128*) p))
|
if (!xdr_dec128(xdrs, (Firebird::Decimal128*) p))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case dtype_int128:
|
||||||
|
if (!xdr_int128(xdrs, (Firebird::Int128*) p))
|
||||||
|
return FALSE;
|
||||||
|
break;
|
||||||
|
|
||||||
case dtype_timestamp:
|
case dtype_timestamp:
|
||||||
if (!xdr_long(xdrs, &((SLONG*) p)[0]))
|
if (!xdr_long(xdrs, &((SLONG*) p)[0]))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -3579,7 +3579,7 @@ rec_type get_data_old(BurpGlobals* tdgbl, burp_rel* relation)
|
|||||||
case blr_long:
|
case blr_long:
|
||||||
case blr_quad:
|
case blr_quad:
|
||||||
case blr_int64:
|
case blr_int64:
|
||||||
case blr_dec_fixed:
|
case blr_int128:
|
||||||
add_byte(blr, field->fld_type);
|
add_byte(blr, field->fld_type);
|
||||||
add_byte(blr, field->fld_scale);
|
add_byte(blr, field->fld_scale);
|
||||||
break;
|
break;
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
|
|
||||||
#include "firebird.h"
|
#include "firebird.h"
|
||||||
#include "DecFloat.h"
|
#include "DecFloat.h"
|
||||||
|
#include "Int128.h"
|
||||||
|
|
||||||
#include "StatusArg.h"
|
#include "StatusArg.h"
|
||||||
#include "gen/iberror.h"
|
#include "gen/iberror.h"
|
||||||
@ -49,7 +50,7 @@ extern "C"
|
|||||||
using namespace Firebird;
|
using namespace Firebird;
|
||||||
|
|
||||||
const DecimalStatus DecimalStatus::DEFAULT(FB_DEC_Errors);
|
const DecimalStatus DecimalStatus::DEFAULT(FB_DEC_Errors);
|
||||||
const DecimalBinding DecimalBinding::DEFAULT;
|
const NumericBinding NumericBinding::DEFAULT;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@ -77,7 +78,7 @@ public:
|
|||||||
init(DEC_INIT_DECIMAL64);
|
init(DEC_INIT_DECIMAL64);
|
||||||
}
|
}
|
||||||
|
|
||||||
DecimalContext(const Decimal128Base*, DecimalStatus ds)
|
DecimalContext(const Decimal128*, DecimalStatus ds)
|
||||||
: decSt(ds)
|
: decSt(ds)
|
||||||
{
|
{
|
||||||
init(DEC_INIT_DECIMAL128);
|
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 dzup(DBL_MIN, DecimalStatus(0)), dzlw(-DBL_MIN, DecimalStatus(0));
|
||||||
const CDecimal128 i64max(MAX_SINT64, DecimalStatus(0)), i64min(MIN_SINT64, DecimalStatus(0));
|
const CDecimal128 i64max(MAX_SINT64, DecimalStatus(0)), i64min(MIN_SINT64, DecimalStatus(0));
|
||||||
const CDecimal128 c1(1);
|
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)
|
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;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Decimal64 Decimal64::set(DecimalFixed value, DecimalStatus decSt, int scale)
|
Decimal64 Decimal64::set(Int128 value, DecimalStatus decSt, int scale)
|
||||||
{
|
{
|
||||||
Decimal128 tmp;
|
Decimal128 tmp;
|
||||||
tmp.set(value, decSt, scale);
|
tmp.set(value, decSt, scale);
|
||||||
@ -518,11 +521,21 @@ Decimal128 Decimal128::set(SLONG value, DecimalStatus decSt, int scale)
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Decimal128 Decimal128::set(DecimalFixed value, DecimalStatus decSt, int scale)
|
Decimal128 Decimal128::set(Int128 value, DecimalStatus decSt, int scale)
|
||||||
{
|
{
|
||||||
*this = value;
|
unsigned dwords[4];
|
||||||
setScale(decSt, -scale);
|
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;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -533,13 +546,10 @@ Decimal128 Decimal128::set(SINT64 value, DecimalStatus decSt, int scale)
|
|||||||
unsigned low = value & 0xFFFFFFFF;
|
unsigned low = value & 0xFFFFFFFF;
|
||||||
|
|
||||||
DecimalContext context(this, decSt);
|
DecimalContext context(this, decSt);
|
||||||
decQuad pow2_32;
|
|
||||||
decQuadFromString(&pow2_32, "4294967296", &context);
|
|
||||||
|
|
||||||
decQuad up, down;
|
decQuad up, down;
|
||||||
decQuadFromInt32(&up, high);
|
decQuadFromInt32(&up, high);
|
||||||
decQuadFromUInt32(&down, low);
|
decQuadFromUInt32(&down, low);
|
||||||
decQuadFMA(&dec, &up, &pow2_32, &down, &context);
|
decQuadFMA(&dec, &up, &pow2_32.dec, &down, &context);
|
||||||
}
|
}
|
||||||
|
|
||||||
setScale(decSt, -scale);
|
setScale(decSt, -scale);
|
||||||
@ -565,80 +575,6 @@ Decimal128 Decimal128::set(double value, DecimalStatus decSt)
|
|||||||
return *this;
|
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)
|
Decimal128 Decimal128::operator=(Decimal64 d64)
|
||||||
{
|
{
|
||||||
decDoubleToWider(&d64.dec, &dec);
|
decDoubleToWider(&d64.dec, &dec);
|
||||||
@ -654,13 +590,6 @@ int Decimal128::toInteger(DecimalStatus decSt, int scale) const
|
|||||||
return decQuadToInt32(&tmp.dec, &context, rMode);
|
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
|
void Decimal128::toString(DecimalStatus decSt, unsigned length, char* to) const
|
||||||
{
|
{
|
||||||
DecimalContext context(this, decSt);
|
DecimalContext context(this, decSt);
|
||||||
@ -690,24 +619,7 @@ void Decimal128::toString(string& to) const
|
|||||||
to.recalculate_length();
|
to.recalculate_length();
|
||||||
}
|
}
|
||||||
|
|
||||||
Decimal128 DecimalFixed::scaled128(DecimalStatus decSt, int scale) const
|
double Decimal128::toDouble(DecimalStatus decSt) 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
|
|
||||||
{
|
{
|
||||||
DecimalContext context(this, decSt);
|
DecimalContext context(this, decSt);
|
||||||
|
|
||||||
@ -764,37 +676,12 @@ SINT64 Decimal128::toInt64(DecimalStatus decSt, int scale) const
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
SINT64 DecimalFixed::toInt64(DecimalStatus decSt) const
|
UCHAR* Decimal128::getBytes()
|
||||||
{
|
|
||||||
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()
|
|
||||||
{
|
{
|
||||||
return dec.bytes;
|
return dec.bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
Decimal64 Decimal128Base::toDecimal64(DecimalStatus decSt) const
|
Decimal64 Decimal128::toDecimal64(DecimalStatus decSt) const
|
||||||
{
|
{
|
||||||
Decimal64 rc;
|
Decimal64 rc;
|
||||||
DecimalContext context(this, decSt);
|
DecimalContext context(this, decSt);
|
||||||
@ -802,7 +689,7 @@ Decimal64 Decimal128Base::toDecimal64(DecimalStatus decSt) const
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Decimal128Base::setScale(DecimalStatus decSt, int scale)
|
void Decimal128::setScale(DecimalStatus decSt, int scale)
|
||||||
{
|
{
|
||||||
if (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);
|
DecimalContext context(this, decSt);
|
||||||
decQuad r;
|
decQuad r;
|
||||||
@ -820,7 +707,7 @@ int Decimal128Base::compare(DecimalStatus decSt, Decimal128Base tgt) const
|
|||||||
return decQuadToInt32(&r, &context, DEC_ROUND_HALF_UP);
|
return decQuadToInt32(&r, &context, DEC_ROUND_HALF_UP);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Decimal128Base::isInf() const
|
bool Decimal128::isInf() const
|
||||||
{
|
{
|
||||||
switch(decQuadClass(&dec))
|
switch(decQuadClass(&dec))
|
||||||
{
|
{
|
||||||
@ -832,7 +719,7 @@ bool Decimal128Base::isInf() const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Decimal128Base::isNan() const
|
bool Decimal128::isNan() const
|
||||||
{
|
{
|
||||||
switch(decQuadClass(&dec))
|
switch(decQuadClass(&dec))
|
||||||
{
|
{
|
||||||
@ -844,7 +731,7 @@ bool Decimal128Base::isNan() const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Decimal128Base::sign() const
|
int Decimal128::sign() const
|
||||||
{
|
{
|
||||||
if (decQuadIsZero(&dec))
|
if (decQuadIsZero(&dec))
|
||||||
return 0;
|
return 0;
|
||||||
@ -870,7 +757,7 @@ Decimal128 Decimal128::floor(DecimalStatus decSt) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEV_BUILD
|
#ifdef DEV_BUILD
|
||||||
int Decimal128Base::show()
|
int Decimal128::show()
|
||||||
{
|
{
|
||||||
decQuadShow(&dec, "");
|
decQuadShow(&dec, "");
|
||||||
return 0;
|
return 0;
|
||||||
@ -915,50 +802,6 @@ Decimal128 Decimal128::mul(DecimalStatus decSt, Decimal128 op2) const
|
|||||||
return rc;
|
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
|
Decimal128 Decimal128::div(DecimalStatus decSt, Decimal128 op2) const
|
||||||
{
|
{
|
||||||
DecimalContext context(this, decSt);
|
DecimalContext context(this, decSt);
|
||||||
@ -967,27 +810,6 @@ Decimal128 Decimal128::div(DecimalStatus decSt, Decimal128 op2) const
|
|||||||
return rc;
|
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
|
Decimal128 Decimal128::fma(DecimalStatus decSt, Decimal128 op2, Decimal128 op3) const
|
||||||
{
|
{
|
||||||
DecimalContext context(this, decSt);
|
DecimalContext context(this, decSt);
|
||||||
@ -1049,7 +871,7 @@ Decimal128 Decimal128::log10(DecimalStatus decSt) const
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Decimal128Base::makeKey(ULONG* key) const
|
void Decimal128::makeKey(ULONG* key) const
|
||||||
{
|
{
|
||||||
unsigned char coeff[DECQUAD_Pmax];
|
unsigned char coeff[DECQUAD_Pmax];
|
||||||
int sign = decQuadGetCoefficient(&dec, coeff);
|
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);
|
make(key, DECQUAD_Pmax, DECQUAD_Bias, sizeof(dec), coeff, sign, exp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Decimal128Base::grabKey(ULONG* key)
|
void Decimal128::grabKey(ULONG* key)
|
||||||
{
|
{
|
||||||
int exp, sign;
|
int exp, sign;
|
||||||
unsigned char bcd[DECQUAD_Pmax];
|
unsigned char bcd[DECQUAD_Pmax];
|
||||||
@ -1068,12 +890,12 @@ void Decimal128Base::grabKey(ULONG* key)
|
|||||||
decQuadFromBCD(&dec, exp, bcd, sign);
|
decQuadFromBCD(&dec, exp, bcd, sign);
|
||||||
}
|
}
|
||||||
|
|
||||||
ULONG Decimal128Base::getIndexKeyLength()
|
ULONG Decimal128::getIndexKeyLength()
|
||||||
{
|
{
|
||||||
return 17;
|
return 17;
|
||||||
}
|
}
|
||||||
|
|
||||||
ULONG Decimal128Base::makeIndexKey(vary* buf)
|
ULONG Decimal128::makeIndexKey(vary* buf)
|
||||||
{
|
{
|
||||||
unsigned char coeff[DECQUAD_Pmax + 2];
|
unsigned char coeff[DECQUAD_Pmax + 2];
|
||||||
int sign = decQuadGetCoefficient(&dec, coeff);
|
int sign = decQuadGetCoefficient(&dec, coeff);
|
||||||
@ -1207,4 +1029,9 @@ short Decimal128::decCompare(Decimal128 op2) const
|
|||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Decimal128::getBcd(BCD* bcd) const
|
||||||
|
{
|
||||||
|
bcd->sign = decQuadToBCD(&dec, &bcd->exp, bcd->bcd);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Firebird
|
} // namespace Firebird
|
||||||
|
@ -115,27 +115,27 @@ struct DecimalStatus
|
|||||||
USHORT decExtFlag, roundingMode;
|
USHORT decExtFlag, roundingMode;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DecimalBinding
|
struct NumericBinding
|
||||||
{
|
{
|
||||||
enum Bind
|
enum Bind
|
||||||
{
|
{
|
||||||
DEC_NATIVE,
|
NUM_NATIVE,
|
||||||
DEC_TEXT,
|
NUM_TEXT,
|
||||||
DEC_DOUBLE,
|
NUM_DOUBLE,
|
||||||
DEC_NUMERIC
|
NUM_INT64
|
||||||
};
|
};
|
||||||
|
|
||||||
DecimalBinding()
|
NumericBinding()
|
||||||
: bind(DEC_NATIVE),
|
: bind(NUM_NATIVE),
|
||||||
numScale(0)
|
numScale(0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
DecimalBinding(Bind aBind, SCHAR aNumScale = 0)
|
NumericBinding(Bind aBind, SCHAR aNumScale = 0)
|
||||||
: bind(aBind),
|
: bind(aBind),
|
||||||
numScale(aNumScale)
|
numScale(aNumScale)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
static const DecimalBinding DEFAULT;
|
static const NumericBinding DEFAULT;
|
||||||
static const SCHAR MAX_SCALE = 18;
|
static const SCHAR MAX_SCALE = 18;
|
||||||
|
|
||||||
Bind bind;
|
Bind bind;
|
||||||
@ -143,13 +143,11 @@ struct DecimalBinding
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class DecimalFixed;
|
class Int128;
|
||||||
|
|
||||||
class Decimal64
|
class Decimal64
|
||||||
{
|
{
|
||||||
friend class Decimal128;
|
friend class Decimal128;
|
||||||
friend class DecimalFixed;
|
|
||||||
friend class Decimal128Base;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
#if SIZEOF_LONG < 8
|
#if SIZEOF_LONG < 8
|
||||||
@ -159,7 +157,7 @@ public:
|
|||||||
Decimal64 set(SINT64 value, DecimalStatus decSt, int scale);
|
Decimal64 set(SINT64 value, DecimalStatus decSt, int scale);
|
||||||
Decimal64 set(const char* value, DecimalStatus decSt);
|
Decimal64 set(const char* value, DecimalStatus decSt);
|
||||||
Decimal64 set(double 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();
|
UCHAR* getBytes();
|
||||||
Decimal64 abs() const;
|
Decimal64 abs() const;
|
||||||
@ -193,38 +191,7 @@ private:
|
|||||||
decDouble dec;
|
decDouble dec;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Decimal128Base
|
class Decimal128
|
||||||
{
|
|
||||||
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
|
|
||||||
{
|
{
|
||||||
friend class Decimal64;
|
friend class Decimal64;
|
||||||
|
|
||||||
@ -237,7 +204,7 @@ public:
|
|||||||
Decimal128 set(SINT64 value, DecimalStatus decSt, int scale);
|
Decimal128 set(SINT64 value, DecimalStatus decSt, int scale);
|
||||||
Decimal128 set(const char* value, DecimalStatus decSt);
|
Decimal128 set(const char* value, DecimalStatus decSt);
|
||||||
Decimal128 set(double 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);
|
Decimal128 operator=(Decimal64 d64);
|
||||||
|
|
||||||
@ -265,12 +232,37 @@ public:
|
|||||||
short totalOrder(Decimal128 op2) const;
|
short totalOrder(Decimal128 op2) const;
|
||||||
short decCompare(Decimal128 op2) const;
|
short decCompare(Decimal128 op2) const;
|
||||||
|
|
||||||
private:
|
double toDouble(DecimalStatus decSt) const;
|
||||||
Decimal128 operator=(Decimal128Base d128b)
|
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));
|
int sign, exp;
|
||||||
return *this;
|
unsigned char bcd[DECQUAD_Pmax];
|
||||||
}
|
};
|
||||||
|
|
||||||
|
void getBcd(BCD* bcd) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
decQuad dec;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CDecimal128 : public Decimal128
|
class CDecimal128 : public Decimal128
|
||||||
@ -290,45 +282,11 @@ public:
|
|||||||
{
|
{
|
||||||
set(value, DecimalStatus(0), 0);
|
set(value, DecimalStatus(0), 0);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
class DecimalFixed : public Decimal128Base
|
CDecimal128(const char* value, DecimalStatus decSt)
|
||||||
{
|
|
||||||
public:
|
|
||||||
#if SIZEOF_LONG < 8
|
|
||||||
DecimalFixed set(int value)
|
|
||||||
{
|
{
|
||||||
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
|
} // 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);
|
item->length = sizeof(Decimal128);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case blr_dec_fixed:
|
case blr_int128:
|
||||||
item->type = SQL_DEC_FIXED;
|
item->type = SQL_INT128;
|
||||||
item->length = sizeof(DecimalFixed);
|
item->length = sizeof(Int128);
|
||||||
item->scale = rdr.getByte();
|
item->scale = rdr.getByte();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -504,7 +504,10 @@ namespace Firebird
|
|||||||
memset(baseInsert(p0, n), c, n);
|
memset(baseInsert(p0, n), c, n);
|
||||||
return *this;
|
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)
|
void insert(iterator it, size_type n, char_type c)
|
||||||
{
|
{
|
||||||
insert(it - c_str(), n, c);
|
insert(it - c_str(), n, c);
|
||||||
@ -519,6 +522,11 @@ namespace Firebird
|
|||||||
baseErase(p0, n);
|
baseErase(p0, n);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
AbstractString& clear() throw()
|
||||||
|
{
|
||||||
|
erase();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
iterator erase(iterator it) throw()
|
iterator erase(iterator it) throw()
|
||||||
{
|
{
|
||||||
erase(it - c_str(), 1);
|
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 float_to_text(const dsc*, dsc*, Callbacks*);
|
||||||
static void decimal_float_to_text(const dsc*, dsc*, DecimalStatus, Callbacks*);
|
static void decimal_float_to_text(const dsc*, dsc*, DecimalStatus, Callbacks*);
|
||||||
static void integer_to_text(const dsc*, dsc*, 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&);
|
static void localError(const Firebird::Arg::StatusVector&);
|
||||||
|
|
||||||
class DummyException {};
|
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)
|
else if (from->dsc_dtype == dtype_dec128)
|
||||||
((Decimal128*) from->dsc_address)->toString(decSt, sizeof(temp), temp);
|
((Decimal128*) from->dsc_address)->toString(decSt, sizeof(temp), temp);
|
||||||
else
|
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)
|
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);
|
return d128.toInteger(decSt, scale);
|
||||||
|
|
||||||
case dtype_dec_fixed:
|
case dtype_int128:
|
||||||
value = ((DecimalFixed*) p)->toInteger(decSt);
|
return ((Int128*) p)->toInteger(scale);
|
||||||
break;
|
|
||||||
|
|
||||||
case dtype_real:
|
case dtype_real:
|
||||||
case dtype_double:
|
case dtype_double:
|
||||||
@ -1121,7 +1148,7 @@ SLONG CVT_get_long(const dsc* desc, SSHORT scale, DecimalStatus decSt, ErrorFunc
|
|||||||
{
|
{
|
||||||
USHORT length =
|
USHORT length =
|
||||||
CVT_make_string(desc, ttype_ascii, &p, &buffer, sizeof(buffer), decSt, err);
|
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;
|
break;
|
||||||
|
|
||||||
@ -1274,8 +1301,8 @@ double CVT_get_double(const dsc* desc, DecimalStatus decSt, ErrorFunction err, b
|
|||||||
return d128.toDouble(decSt);
|
return d128.toDouble(decSt);
|
||||||
}
|
}
|
||||||
|
|
||||||
case dtype_dec_fixed:
|
case dtype_int128:
|
||||||
value = ((DecimalFixed*) desc->dsc_address)->toDouble(decSt);
|
value = ((Int128*) desc->dsc_address)->toDouble();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case dtype_varying:
|
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_boolean:
|
||||||
case dtype_dec64:
|
case dtype_dec64:
|
||||||
case dtype_dec128:
|
case dtype_dec128:
|
||||||
case dtype_dec_fixed:
|
case dtype_int128:
|
||||||
CVT_conversion_error(from, cb->err);
|
CVT_conversion_error(from, cb->err);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1629,7 +1656,7 @@ void CVT_move_common(const dsc* from, dsc* to, DecimalStatus decSt, Callbacks* c
|
|||||||
case dtype_boolean:
|
case dtype_boolean:
|
||||||
case dtype_dec64:
|
case dtype_dec64:
|
||||||
case dtype_dec128:
|
case dtype_dec128:
|
||||||
case dtype_dec_fixed:
|
case dtype_int128:
|
||||||
CVT_conversion_error(from, cb->err);
|
CVT_conversion_error(from, cb->err);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1671,7 +1698,7 @@ void CVT_move_common(const dsc* from, dsc* to, DecimalStatus decSt, Callbacks* c
|
|||||||
case dtype_boolean:
|
case dtype_boolean:
|
||||||
case dtype_dec64:
|
case dtype_dec64:
|
||||||
case dtype_dec128:
|
case dtype_dec128:
|
||||||
case dtype_dec_fixed:
|
case dtype_int128:
|
||||||
CVT_conversion_error(from, cb->err);
|
CVT_conversion_error(from, cb->err);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1716,7 +1743,7 @@ void CVT_move_common(const dsc* from, dsc* to, DecimalStatus decSt, Callbacks* c
|
|||||||
case dtype_boolean:
|
case dtype_boolean:
|
||||||
case dtype_dec64:
|
case dtype_dec64:
|
||||||
case dtype_dec128:
|
case dtype_dec128:
|
||||||
case dtype_dec_fixed:
|
case dtype_int128:
|
||||||
CVT_conversion_error(from, cb->err);
|
CVT_conversion_error(from, cb->err);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1763,7 +1790,7 @@ void CVT_move_common(const dsc* from, dsc* to, DecimalStatus decSt, Callbacks* c
|
|||||||
case dtype_boolean:
|
case dtype_boolean:
|
||||||
case dtype_dec64:
|
case dtype_dec64:
|
||||||
case dtype_dec128:
|
case dtype_dec128:
|
||||||
case dtype_dec_fixed:
|
case dtype_int128:
|
||||||
CVT_conversion_error(from, cb->err);
|
CVT_conversion_error(from, cb->err);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1946,6 +1973,10 @@ void CVT_move_common(const dsc* from, dsc* to, DecimalStatus decSt, Callbacks* c
|
|||||||
integer_to_text(from, to, cb);
|
integer_to_text(from, to, cb);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
case dtype_int128:
|
||||||
|
int128_to_text(from, to, cb);
|
||||||
|
return;
|
||||||
|
|
||||||
case dtype_real:
|
case dtype_real:
|
||||||
case dtype_double:
|
case dtype_double:
|
||||||
float_to_text(from, to, cb);
|
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_dec64:
|
||||||
case dtype_dec128:
|
case dtype_dec128:
|
||||||
case dtype_dec_fixed:
|
|
||||||
decimal_float_to_text(from, to, decSt, cb);
|
decimal_float_to_text(from, to, decSt, cb);
|
||||||
return;
|
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);
|
*((Decimal128*) p) = CVT_get_dec128(from, decSt, cb->err);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case dtype_dec_fixed:
|
case dtype_int128:
|
||||||
*((DecimalFixed*) p) = CVT_get_dec_fixed(from, (SSHORT) to->dsc_scale, decSt, cb->err);
|
*((Int128*) p) = CVT_get_int128(from, (SSHORT) to->dsc_scale, decSt, cb->err);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case dtype_boolean:
|
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_double:
|
||||||
case dtype_dec64:
|
case dtype_dec64:
|
||||||
case dtype_dec128:
|
case dtype_dec128:
|
||||||
case dtype_dec_fixed:
|
case dtype_int128:
|
||||||
CVT_conversion_error(from, cb->err);
|
CVT_conversion_error(from, cb->err);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2494,11 +2524,28 @@ double CVT_power_of_ten(const int scale)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SSHORT CVT_decompose(const char* string,
|
class RetPtr
|
||||||
USHORT length,
|
{
|
||||||
SSHORT dtype,
|
public:
|
||||||
SLONG* return_value,
|
virtual ~RetPtr() { }
|
||||||
ErrorFunction err)
|
|
||||||
|
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;
|
dsc errd;
|
||||||
MOVE_CLEAR(&errd, sizeof(errd));
|
MOVE_CLEAR(&errd, sizeof(errd));
|
||||||
errd.dsc_dtype = dtype_text;
|
errd.dsc_dtype = dtype_text;
|
||||||
@ -2528,14 +2566,9 @@ SSHORT CVT_decompose(const char* string,
|
|||||||
errd.dsc_length = length;
|
errd.dsc_length = length;
|
||||||
errd.dsc_address = reinterpret_cast<UCHAR*>(const_cast<char*>(string));
|
errd.dsc_address = reinterpret_cast<UCHAR*>(const_cast<char*>(string));
|
||||||
|
|
||||||
SINT64 value = 0;
|
|
||||||
SSHORT scale = 0;
|
SSHORT scale = 0;
|
||||||
int sign = 0;
|
int sign = 0;
|
||||||
bool digit_seen = false, fraction = false;
|
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* p = string;
|
||||||
const char* end = p + length;
|
const char* end = p + length;
|
||||||
@ -2561,28 +2594,20 @@ SSHORT CVT_decompose(const char* string,
|
|||||||
while (q < end && *q == ' ')
|
while (q < end && *q == ' ')
|
||||||
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);
|
CVT_conversion_error(&errd, err);
|
||||||
|
|
||||||
q = p;
|
q = p;
|
||||||
value = hex_to_value(q, digits_end);
|
hex_to_value(q, digits_end, return_value);
|
||||||
|
|
||||||
if (q != digits_end)
|
if (q != digits_end)
|
||||||
CVT_conversion_error(&errd, err);
|
CVT_conversion_error(&errd, err);
|
||||||
|
|
||||||
// 0xFFFFFFFF = -1; 0x0FFFFFFFF = 4294967295
|
// 0xFFFFFFFF = -1; 0x0FFFFFFFF = 4294967295
|
||||||
if (digits_end - p <= 8)
|
if (digits_end - p <= 8)
|
||||||
value = (SLONG) value;
|
return_value->truncate8();
|
||||||
|
else if (digits_end - p <= 16)
|
||||||
if (dtype == dtype_long)
|
return_value->truncate16();
|
||||||
{
|
|
||||||
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 0; // 0 scale for hex literals
|
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
|
// tricky: the value doesn't always become negative after an
|
||||||
// overflow!
|
// overflow!
|
||||||
|
|
||||||
if (value >= limit_by_10)
|
switch(return_value->compareLimitBy10())
|
||||||
{
|
{
|
||||||
// possibility of an overflow
|
case RetPtr::RETVAL_OVERFLOW:
|
||||||
if (value > limit_by_10)
|
if (fraction)
|
||||||
{
|
{
|
||||||
err(Arg::Gds(isc_arith_except) << Arg::Gds(isc_numeric_out_of_range));
|
while (p < end)
|
||||||
}
|
{
|
||||||
else if ((*p > '8' && sign == -1) || (*p > '7' && sign != -1))
|
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));
|
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)
|
if (fraction)
|
||||||
--scale;
|
--scale;
|
||||||
}
|
}
|
||||||
@ -2645,8 +2683,8 @@ SSHORT CVT_decompose(const char* string,
|
|||||||
if (!digit_seen)
|
if (!digit_seen)
|
||||||
CVT_conversion_error(&errd, err);
|
CVT_conversion_error(&errd, err);
|
||||||
|
|
||||||
if ((sign == -1) && value != lower_limit)
|
if ((sign == -1) && !return_value->isLowerLimit())
|
||||||
value = -value;
|
return_value->neg();
|
||||||
|
|
||||||
// If there's still something left, there must be an explicit exponent
|
// If there's still something left, there must be an explicit exponent
|
||||||
if (p < end)
|
if (p < end)
|
||||||
@ -2693,18 +2731,160 @@ SSHORT CVT_decompose(const char* string,
|
|||||||
|
|
||||||
if (!digit_seen)
|
if (!digit_seen)
|
||||||
CVT_conversion_error(&errd, err);
|
CVT_conversion_error(&errd, err);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dtype == dtype_long)
|
|
||||||
*return_value = (SLONG) value;
|
|
||||||
else
|
|
||||||
*((SINT64 *) return_value) = value;
|
|
||||||
|
|
||||||
return scale;
|
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,
|
USHORT CVT_get_string_ptr_common(const dsc* desc, USHORT* ttype, UCHAR** address,
|
||||||
vary* temp, USHORT length, DecimalStatus decSt, Callbacks* cb)
|
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;
|
return *(Decimal64*) p;
|
||||||
|
|
||||||
case dtype_dec128:
|
case dtype_dec128:
|
||||||
return ((Decimal128Base*) p)->toDecimal64(decSt);
|
return ((Decimal128*) p)->toDecimal64(decSt);
|
||||||
|
|
||||||
case dtype_dec_fixed:
|
case dtype_int128:
|
||||||
return d64.set(*((DecimalFixed*) p), decSt, scale);
|
return d64.set(*((Int128*) p), decSt, scale);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fb_assert(false);
|
fb_assert(false);
|
||||||
@ -2940,8 +3120,8 @@ Decimal128 CVT_get_dec128(const dsc* desc, DecimalStatus decSt, ErrorFunction er
|
|||||||
case dtype_dec128:
|
case dtype_dec128:
|
||||||
return *(Decimal128*) p;
|
return *(Decimal128*) p;
|
||||||
|
|
||||||
case dtype_dec_fixed:
|
case dtype_int128:
|
||||||
return d128.set(*((DecimalFixed*) p), decSt, scale);
|
return d128.set(*((Int128*) p), decSt, scale);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fb_assert(false);
|
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
|
VaryStr<1024> buffer; // represents unreasonably long decfloat literal in ASCII
|
||||||
DecimalFixed dfix;
|
Int128 int128;
|
||||||
Decimal128 tmp;
|
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
|
// adjust exact numeric values to same scaling
|
||||||
if (DTYPE_IS_EXACT(desc->dsc_dtype))
|
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)
|
switch (desc->dsc_dtype)
|
||||||
{
|
{
|
||||||
case dtype_short:
|
case dtype_short:
|
||||||
dfix.set(*(SSHORT*) p);
|
int128.set(SLONG(*(SSHORT*) p), scale);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case dtype_long:
|
case dtype_long:
|
||||||
dfix.set(*(SLONG*) p);
|
int128.set(*(SLONG*) p, scale);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case dtype_quad:
|
case dtype_quad:
|
||||||
dfix.set(CVT_get_int64(desc, 0, decSt, err));
|
int128.set(CVT_get_int64(desc, 0, decSt, err), scale);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case dtype_int64:
|
case dtype_int64:
|
||||||
dfix.set(*(SINT64*) p);
|
int128.set(*(SINT64*) p, scale);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case dtype_varying:
|
case dtype_varying:
|
||||||
case dtype_cstring:
|
case dtype_cstring:
|
||||||
case dtype_text:
|
case dtype_text:
|
||||||
CVT_make_null_string(desc, ttype_ascii, &p, &buffer, sizeof(buffer) - 1, decSt, err);
|
{
|
||||||
dfix.set(buffer.vary_string, scale, decSt);
|
USHORT length =
|
||||||
return dfix; // scale already corrected
|
CVT_make_string(desc, ttype_ascii, &p, &buffer, sizeof(buffer), decSt, err);
|
||||||
|
scale -= CVT_decompose(p, length, &int128, err);
|
||||||
|
int128.setScale(scale);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case dtype_blob:
|
case dtype_blob:
|
||||||
@ -3022,23 +3212,70 @@ DecimalFixed CVT_get_dec_fixed(const dsc* desc, SSHORT scale, DecimalStatus decS
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case dtype_real:
|
case dtype_real:
|
||||||
dfix.set(*((float*) p), scale, decSt);
|
|
||||||
return dfix; // scale already corrected
|
|
||||||
|
|
||||||
case dtype_double:
|
case dtype_double:
|
||||||
dfix.set(*((double*) p), scale, decSt);
|
if (desc->dsc_dtype == dtype_real)
|
||||||
return dfix; // scale already corrected
|
{
|
||||||
|
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:
|
case dtype_dec64:
|
||||||
dfix = tmp = *((Decimal64*) p);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case dtype_dec128:
|
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;
|
break;
|
||||||
|
|
||||||
case dtype_dec_fixed:
|
case dtype_int128:
|
||||||
dfix = *((DecimalFixed*) p);
|
int128 = *((Int128*) p);
|
||||||
|
int128.setScale(scale);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -3054,8 +3291,7 @@ DecimalFixed CVT_get_dec_fixed(const dsc* desc, SSHORT scale, DecimalStatus decS
|
|||||||
err(v);
|
err(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
dfix.exactInt(decSt, scale);
|
return int128;
|
||||||
return dfix;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3154,7 +3390,9 @@ SQUAD CVT_get_quad(const dsc* desc, SSHORT scale, DecimalStatus decSt, ErrorFunc
|
|||||||
{
|
{
|
||||||
USHORT length =
|
USHORT length =
|
||||||
CVT_make_string(desc, ttype_ascii, &p, &buffer, sizeof(buffer), decSt, err);
|
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;
|
break;
|
||||||
|
|
||||||
@ -3170,7 +3408,7 @@ SQUAD CVT_get_quad(const dsc* desc, SSHORT scale, DecimalStatus decSt, ErrorFunc
|
|||||||
|
|
||||||
case dtype_dec64:
|
case dtype_dec64:
|
||||||
case dtype_dec128:
|
case dtype_dec128:
|
||||||
case dtype_dec_fixed:
|
case dtype_int128:
|
||||||
SINT64_to_SQUAD(CVT_get_int64(desc, scale, decSt, err), value);
|
SINT64_to_SQUAD(CVT_get_int64(desc, scale, decSt, err), value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -3246,9 +3484,8 @@ SINT64 CVT_get_int64(const dsc* desc, SSHORT scale, DecimalStatus decSt, ErrorFu
|
|||||||
return d128.toInt64(decSt, scale);
|
return d128.toInt64(decSt, scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
case dtype_dec_fixed:
|
case dtype_int128:
|
||||||
value = ((DecimalFixed*) p)->toInt64(decSt);
|
return ((Int128*) p)->toInt64(scale);
|
||||||
break;
|
|
||||||
|
|
||||||
case dtype_real:
|
case dtype_real:
|
||||||
case dtype_double:
|
case dtype_double:
|
||||||
@ -3295,7 +3532,7 @@ SINT64 CVT_get_int64(const dsc* desc, SSHORT scale, DecimalStatus decSt, ErrorFu
|
|||||||
{
|
{
|
||||||
USHORT length =
|
USHORT length =
|
||||||
CVT_make_string(desc, ttype_ascii, &p, &buffer, sizeof(buffer), decSt, err);
|
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;
|
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
|
* 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.
|
// we already know this is a hex string, and there is no prefix.
|
||||||
// So, string is something like DEADBEEF.
|
// So, string is something like DEADBEEF.
|
||||||
|
|
||||||
SINT64 value = 0;
|
|
||||||
UCHAR byte = 0;
|
UCHAR byte = 0;
|
||||||
int nibble = ((end - string) & 1);
|
int nibble = ((end - string) & 1);
|
||||||
char ch;
|
char ch;
|
||||||
@ -3385,7 +3621,7 @@ static SINT64 hex_to_value(const char*& string, const char* end)
|
|||||||
{
|
{
|
||||||
byte = (byte << 4) + (UCHAR) c;
|
byte = (byte << 4) + (UCHAR) c;
|
||||||
nibble = 0;
|
nibble = 0;
|
||||||
value = (value << 8) + byte;
|
retValue->nextDigit(byte, 256);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -3397,8 +3633,6 @@ static SINT64 hex_to_value(const char*& string, const char* end)
|
|||||||
}
|
}
|
||||||
|
|
||||||
fb_assert(string <= end);
|
fb_assert(string <= end);
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -80,7 +80,9 @@ enum EXPECT_DATETIME
|
|||||||
expect_sql_time_tz
|
expect_sql_time_tz
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
class Int128;
|
||||||
|
|
||||||
|
} // namespace Firebird
|
||||||
|
|
||||||
|
|
||||||
void CVT_conversion_error(const dsc*, ErrorFunction);
|
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);
|
double CVT_get_double(const dsc*, Firebird::DecimalStatus, ErrorFunction, bool* getNumericOverflow = nullptr);
|
||||||
Firebird::Decimal64 CVT_get_dec64(const dsc*, Firebird::DecimalStatus, ErrorFunction);
|
Firebird::Decimal64 CVT_get_dec64(const dsc*, Firebird::DecimalStatus, ErrorFunction);
|
||||||
Firebird::Decimal128 CVT_get_dec128(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);
|
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_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_common(const dsc*, dsc*, Firebird::DecimalStatus, Firebird::Callbacks*);
|
||||||
void CVT_move(const dsc*, dsc*, Firebird::DecimalStatus, ErrorFunction);
|
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(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*);
|
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);
|
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
|
5, // dtype_boolean
|
||||||
23, // dtype_dec64 1 + 1 + 1 + 1 + 16(34) + 3(4)
|
23, // dtype_dec64 1 + 1 + 1 + 1 + 16(34) + 3(4)
|
||||||
42, // dtype_dec128 +- . e +- coeff + exp
|
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
|
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
|
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_double dtype_d_float dtype_sql_date dtype_sql_time
|
||||||
dtype_timestamp dtype_blob dtype_array dtype_int64
|
dtype_timestamp dtype_blob dtype_array dtype_int64
|
||||||
dtype_dbkey dtype_boolean dtype_dec64 dtype_dec128
|
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
|
// 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_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||||
dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
|
dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
|
||||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
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_cstring
|
||||||
{dtype_unknown, dtype_double, dtype_double, dtype_double,
|
{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_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||||
dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
|
dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
|
||||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
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_varying
|
||||||
{dtype_unknown, dtype_double, dtype_double, dtype_double,
|
{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_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||||
dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
|
dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
|
||||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
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)
|
// 4 (unused)
|
||||||
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
|
{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_double, dtype_d_float, dtype_sql_date, dtype_sql_time,
|
||||||
dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int64,
|
dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int64,
|
||||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
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_long
|
||||||
{dtype_unknown, dtype_double, dtype_double, dtype_double,
|
{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_double, dtype_d_float, dtype_sql_date, dtype_sql_time,
|
||||||
dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int64,
|
dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int64,
|
||||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
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_quad
|
||||||
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
|
{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_double, dtype_d_float, dtype_sql_date, dtype_sql_time,
|
||||||
dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int64,
|
dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int64,
|
||||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
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_dbkey
|
||||||
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
|
{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_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||||
dtype_dec128, dtype_sql_time_tz, dtype_timestamp_tz},
|
dtype_dec128, dtype_sql_time_tz, dtype_timestamp_tz},
|
||||||
|
|
||||||
// dtype_dec_fixed
|
// dtype_int128
|
||||||
{dtype_unknown, dtype_dec_fixed, dtype_dec_fixed, dtype_dec_fixed,
|
{dtype_unknown, dtype_int128, dtype_int128, dtype_int128,
|
||||||
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
|
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_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_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_sql_time_tz
|
||||||
{dtype_unknown, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
|
{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_double dtype_d_float dtype_sql_date dtype_sql_time
|
||||||
dtype_timestamp dtype_blob dtype_array dtype_int64
|
dtype_timestamp dtype_blob dtype_array dtype_int64
|
||||||
dtype_dbkey dtype_boolean dtype_dec64 dtype_dec128
|
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
|
// 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_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||||
dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
|
dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
|
||||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
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_cstring
|
||||||
{dtype_unknown, dtype_double, dtype_double, dtype_double,
|
{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_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||||
dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
|
dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
|
||||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
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_varying
|
||||||
{dtype_unknown, dtype_double, dtype_double, dtype_double,
|
{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_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||||
dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
|
dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
|
||||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
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)
|
// 4 (unused)
|
||||||
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
|
{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_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||||
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int64,
|
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int64,
|
||||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||||
dtype_dec_fixed, DTYPE_CANNOT, DTYPE_CANNOT},
|
dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||||
|
|
||||||
// dtype_long
|
// dtype_long
|
||||||
{dtype_unknown, dtype_double, dtype_double, dtype_double,
|
{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_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||||
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int64,
|
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int64,
|
||||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||||
dtype_dec_fixed, DTYPE_CANNOT, DTYPE_CANNOT},
|
dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||||
|
|
||||||
// dtype_quad
|
// dtype_quad
|
||||||
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
|
{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_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||||
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int64,
|
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int64,
|
||||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||||
dtype_dec_fixed, DTYPE_CANNOT, DTYPE_CANNOT},
|
dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||||
|
|
||||||
// dtype_dbkey
|
// dtype_dbkey
|
||||||
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
|
{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_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||||
dtype_dec128, DTYPE_CANNOT, DTYPE_CANNOT},
|
dtype_dec128, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||||
|
|
||||||
// dtype_dec_fixed
|
// dtype_int128
|
||||||
{dtype_unknown, dtype_dec_fixed, dtype_dec_fixed, dtype_dec_fixed,
|
{dtype_unknown, dtype_int128, dtype_int128, dtype_int128,
|
||||||
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
|
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_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_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_sql_time_tz
|
||||||
{dtype_unknown, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
|
{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_double dtype_d_float dtype_sql_date dtype_sql_time
|
||||||
dtype_timestamp dtype_blob dtype_array dtype_int64
|
dtype_timestamp dtype_blob dtype_array dtype_int64
|
||||||
dtype_dbkey dtype_boolean dtype_dec64 dtype_dec128
|
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
|
// 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_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||||
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
|
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
|
||||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||||
dtype_dec_fixed, DTYPE_CANNOT, DTYPE_CANNOT},
|
dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||||
|
|
||||||
// dtype_cstring
|
// dtype_cstring
|
||||||
{dtype_unknown, dtype_double, dtype_double, dtype_double,
|
{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_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||||
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
|
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
|
||||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||||
dtype_dec_fixed, DTYPE_CANNOT, DTYPE_CANNOT},
|
dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||||
|
|
||||||
// dtype_varying
|
// dtype_varying
|
||||||
{dtype_unknown, dtype_double, dtype_double, dtype_double,
|
{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_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||||
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
|
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
|
||||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||||
dtype_dec_fixed, DTYPE_CANNOT, DTYPE_CANNOT},
|
dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||||
|
|
||||||
// 4 (unused)
|
// 4 (unused)
|
||||||
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
|
{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_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||||
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int64,
|
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int64,
|
||||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||||
dtype_dec_fixed, DTYPE_CANNOT, DTYPE_CANNOT},
|
dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||||
|
|
||||||
// dtype_long
|
// dtype_long
|
||||||
{dtype_unknown, dtype_double, dtype_double, dtype_double,
|
{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_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||||
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int64,
|
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int64,
|
||||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||||
dtype_dec_fixed, DTYPE_CANNOT, DTYPE_CANNOT},
|
dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||||
|
|
||||||
// dtype_quad
|
// dtype_quad
|
||||||
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
|
{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_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||||
dtype_int64, dtype_int64, DTYPE_CANNOT, dtype_double,
|
dtype_int64, dtype_int64, DTYPE_CANNOT, dtype_double,
|
||||||
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
|
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_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||||
dtype_dec_fixed, DTYPE_CANNOT, DTYPE_CANNOT},
|
dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||||
|
|
||||||
// dtype_dbkey
|
// dtype_dbkey
|
||||||
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
|
{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_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||||
dtype_dec128, DTYPE_CANNOT, DTYPE_CANNOT},
|
dtype_dec128, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||||
|
|
||||||
// dtype_dec_fixed
|
// dtype_int128
|
||||||
{dtype_unknown, dtype_dec_fixed, dtype_dec_fixed, dtype_dec_fixed,
|
{dtype_unknown, dtype_int128, dtype_int128, dtype_int128,
|
||||||
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
|
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_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_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_sql_time_tz
|
||||||
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
|
{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_double dtype_d_float dtype_sql_date dtype_sql_time
|
||||||
dtype_timestamp dtype_blob dtype_array dtype_int64
|
dtype_timestamp dtype_blob dtype_array dtype_int64
|
||||||
dtype_dbkey dtype_boolean dtype_dec64 dtype_dec128
|
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
|
// 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_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||||
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
|
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
|
||||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||||
dtype_dec_fixed, DTYPE_CANNOT, DTYPE_CANNOT},
|
dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||||
|
|
||||||
// dtype_cstring
|
// dtype_cstring
|
||||||
{dtype_unknown, dtype_double, dtype_double, dtype_double,
|
{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_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||||
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
|
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
|
||||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||||
dtype_dec_fixed, DTYPE_CANNOT, DTYPE_CANNOT},
|
dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||||
|
|
||||||
// dtype_varying
|
// dtype_varying
|
||||||
{dtype_unknown, dtype_double, dtype_double, dtype_double,
|
{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_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||||
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
|
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
|
||||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||||
dtype_dec_fixed, DTYPE_CANNOT, DTYPE_CANNOT},
|
dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||||
|
|
||||||
// 4 (unused)
|
// 4 (unused)
|
||||||
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
|
{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_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||||
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
|
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
|
||||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||||
dtype_dec_fixed, DTYPE_CANNOT, DTYPE_CANNOT},
|
dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||||
|
|
||||||
// dtype_long
|
// dtype_long
|
||||||
{dtype_unknown, dtype_double, dtype_double, dtype_double,
|
{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_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||||
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
|
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
|
||||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||||
dtype_dec_fixed, DTYPE_CANNOT, DTYPE_CANNOT},
|
dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||||
|
|
||||||
// dtype_quad
|
// dtype_quad
|
||||||
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
|
{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_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||||
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
|
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
|
||||||
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||||
dtype_dec_fixed, DTYPE_CANNOT, DTYPE_CANNOT},
|
dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||||
|
|
||||||
// dtype_dbkey
|
// dtype_dbkey
|
||||||
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
|
{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_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
|
||||||
dtype_dec128, DTYPE_CANNOT, DTYPE_CANNOT},
|
dtype_dec128, DTYPE_CANNOT, DTYPE_CANNOT},
|
||||||
|
|
||||||
// dtype_dec_fixed
|
// dtype_int128
|
||||||
{dtype_unknown, dtype_dec_fixed, dtype_dec_fixed, dtype_dec_fixed,
|
{dtype_unknown, dtype_int128, dtype_int128, dtype_int128,
|
||||||
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
|
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_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_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_sql_time_tz
|
||||||
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
|
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
|
||||||
@ -1268,9 +1268,9 @@ bool DSC_make_descriptor(DSC* desc,
|
|||||||
desc->dsc_dtype = dtype_dec128;
|
desc->dsc_dtype = dtype_dec128;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case blr_dec_fixed:
|
case blr_int128:
|
||||||
desc->dsc_length = sizeof(DecimalFixed);
|
desc->dsc_length = sizeof(Int128);
|
||||||
desc->dsc_dtype = dtype_dec_fixed;
|
desc->dsc_dtype = dtype_int128;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case blr_timestamp:
|
case blr_timestamp:
|
||||||
@ -1448,7 +1448,7 @@ const char* dsc::typeToText() const
|
|||||||
return "decfloat(16)";
|
return "decfloat(16)";
|
||||||
case dtype_dec128:
|
case dtype_dec128:
|
||||||
return "decfloat(34)";
|
return "decfloat(34)";
|
||||||
case dtype_dec_fixed:
|
case dtype_int128:
|
||||||
return "decimal";
|
return "decimal";
|
||||||
case dtype_sql_time_tz:
|
case dtype_sql_time_tz:
|
||||||
return "time with timezone";
|
return "time with timezone";
|
||||||
@ -1552,8 +1552,8 @@ void dsc::getSqlInfo(SLONG* sqlLength, SLONG* sqlSubType, SLONG* sqlScale, SLONG
|
|||||||
*sqlScale = 0;
|
*sqlScale = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case dtype_dec_fixed:
|
case dtype_int128:
|
||||||
*sqlType = SQL_DEC_FIXED;
|
*sqlType = SQL_INT128;
|
||||||
*sqlScale = dsc_scale;
|
*sqlScale = dsc_scale;
|
||||||
if (dsc_sub_type)
|
if (dsc_sub_type)
|
||||||
*sqlSubType = dsc_sub_type;
|
*sqlSubType = dsc_sub_type;
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include "../jrd/ods.h"
|
#include "../jrd/ods.h"
|
||||||
#include "../intl/charsets.h"
|
#include "../intl/charsets.h"
|
||||||
#include "../common/DecFloat.h"
|
#include "../common/DecFloat.h"
|
||||||
|
#include "../common/Int128.h"
|
||||||
|
|
||||||
// Data type information
|
// Data type information
|
||||||
|
|
||||||
@ -60,7 +61,7 @@ inline bool DTYPE_IS_BLOB_OR_QUAD(UCHAR d)
|
|||||||
// Exact numeric?
|
// Exact numeric?
|
||||||
inline bool DTYPE_IS_EXACT(UCHAR d)
|
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)
|
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)
|
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)
|
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
|
// Descriptor format
|
||||||
@ -138,7 +140,8 @@ typedef struct dsc
|
|||||||
|
|
||||||
bool isExact() const
|
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
|
bool isNumeric() const
|
||||||
@ -187,14 +190,14 @@ typedef struct dsc
|
|||||||
return dsc_dtype == dtype_dec128 || dsc_dtype == dtype_dec64;
|
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
|
bool isDecOrInt() const
|
||||||
{
|
{
|
||||||
return isDecFloat() || isDecFixed() || isExact();
|
return isDecFloat() || isExact();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isApprox() const
|
bool isApprox() const
|
||||||
@ -339,6 +342,15 @@ typedef struct dsc
|
|||||||
dsc_address = (UCHAR*) address;
|
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)
|
void makeLong(SCHAR scale, SLONG* address = NULL)
|
||||||
{
|
{
|
||||||
clear();
|
clear();
|
||||||
|
@ -252,6 +252,7 @@ static const TOK tokens[] =
|
|||||||
{TOK_INSERT, "INSERT", false},
|
{TOK_INSERT, "INSERT", false},
|
||||||
{TOK_INSERTING, "INSERTING", false},
|
{TOK_INSERTING, "INSERTING", false},
|
||||||
{TOK_INT, "INT", false},
|
{TOK_INT, "INT", false},
|
||||||
|
{TOK_INT128, "INT128", true},
|
||||||
{TOK_INTEGER, "INTEGER", false},
|
{TOK_INTEGER, "INTEGER", false},
|
||||||
{TOK_INTO, "INTO", false},
|
{TOK_INTO, "INTO", false},
|
||||||
{TOK_INVOKER, "INVOKER", true},
|
{TOK_INVOKER, "INVOKER", true},
|
||||||
|
@ -855,9 +855,9 @@ static const UCHAR* sdl_desc(const UCHAR* ptr, DSC* desc)
|
|||||||
desc->dsc_length = sizeof(Decimal128);
|
desc->dsc_length = sizeof(Decimal128);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case blr_dec_fixed:
|
case blr_int128:
|
||||||
desc->dsc_dtype = dtype_dec_fixed;
|
desc->dsc_dtype = dtype_int128;
|
||||||
desc->dsc_length = sizeof(DecimalFixed);
|
desc->dsc_length = sizeof(Int128);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case blr_timestamp:
|
case blr_timestamp:
|
||||||
|
@ -1522,8 +1522,8 @@ UCHAR sqlTypeToDscType(SSHORT sqlType)
|
|||||||
return dtype_dec64;
|
return dtype_dec64;
|
||||||
case SQL_DEC34:
|
case SQL_DEC34:
|
||||||
return dtype_dec128;
|
return dtype_dec128;
|
||||||
case SQL_DEC_FIXED:
|
case SQL_INT128:
|
||||||
return dtype_dec_fixed;
|
return dtype_int128;
|
||||||
case SQL_TIME_TZ:
|
case SQL_TIME_TZ:
|
||||||
return dtype_sql_time_tz;
|
return dtype_sql_time_tz;
|
||||||
case SQL_TIMESTAMP_TZ:
|
case SQL_TIMESTAMP_TZ:
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#include "../yvalve/gds_proto.h"
|
#include "../yvalve/gds_proto.h"
|
||||||
#include "../common/gdsassert.h"
|
#include "../common/gdsassert.h"
|
||||||
#include "../common/DecFloat.h"
|
#include "../common/DecFloat.h"
|
||||||
|
#include "../common/Int128.h"
|
||||||
|
|
||||||
inline UCHAR* XDR_ALLOC(ULONG size)
|
inline UCHAR* XDR_ALLOC(ULONG size)
|
||||||
{
|
{
|
||||||
@ -268,12 +269,17 @@ bool_t xdr_datum( XDR* xdrs, const dsc* desc, UCHAR* buffer)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case dtype_dec128:
|
case dtype_dec128:
|
||||||
case dtype_dec_fixed:
|
|
||||||
fb_assert(desc->dsc_length >= sizeof(Firebird::Decimal128));
|
fb_assert(desc->dsc_length >= sizeof(Firebird::Decimal128));
|
||||||
if (!xdr_dec128(xdrs, reinterpret_cast<Firebird::Decimal128*>(p)))
|
if (!xdr_dec128(xdrs, reinterpret_cast<Firebird::Decimal128*>(p)))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
break;
|
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:
|
case dtype_timestamp:
|
||||||
fb_assert(desc->dsc_length >= 2 * sizeof(SLONG));
|
fb_assert(desc->dsc_length >= 2 * sizeof(SLONG));
|
||||||
if (!xdr_long(xdrs, &((SLONG*) p)[0]))
|
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)
|
bool_t xdr_enum(XDR* xdrs, xdr_op* ip)
|
||||||
{
|
{
|
||||||
/**************************************
|
/**************************************
|
||||||
|
@ -29,8 +29,9 @@
|
|||||||
|
|
||||||
bool_t xdr_datum(XDR*, const dsc*, UCHAR*);
|
bool_t xdr_datum(XDR*, const dsc*, UCHAR*);
|
||||||
bool_t xdr_double(XDR*, double*);
|
bool_t xdr_double(XDR*, double*);
|
||||||
bool_t xdr_dec64(XDR*, Firebird::Decimal64*);
|
bool_t xdr_dec64(XDR*, Firebird::Decimal64*);
|
||||||
bool_t xdr_dec128(XDR*, Firebird::Decimal128*);
|
bool_t xdr_dec128(XDR*, Firebird::Decimal128*);
|
||||||
|
bool_t xdr_int128(XDR*, Firebird::Int128*);
|
||||||
bool_t xdr_enum(XDR*, xdr_op*);
|
bool_t xdr_enum(XDR*, xdr_op*);
|
||||||
bool_t xdr_float(XDR*, float*);
|
bool_t xdr_float(XDR*, float*);
|
||||||
bool_t xdr_int(XDR*, int*);
|
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) <<
|
ERRD_post(Arg::Gds(isc_expression_eval_err) <<
|
||||||
Arg::Gds(isc_dsql_agg2_wrongarg) << Arg::Str("AVG"));
|
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))
|
else if (DTYPE_IS_EXACT(desc->dsc_dtype))
|
||||||
{
|
{
|
||||||
desc->dsc_dtype = dtype_int64;
|
desc->dsc_dtype = dtype_int64;
|
||||||
@ -584,13 +589,10 @@ void AvgAggNode::getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// In V6, the average of an exact type is computed in SINT64, rather than double as in prior
|
|
||||||
// releases.
|
|
||||||
switch (desc->dsc_dtype)
|
switch (desc->dsc_dtype)
|
||||||
{
|
{
|
||||||
case dtype_short:
|
case dtype_short:
|
||||||
case dtype_long:
|
case dtype_long:
|
||||||
case dtype_int64:
|
|
||||||
desc->dsc_dtype = dtype_int64;
|
desc->dsc_dtype = dtype_int64;
|
||||||
desc->dsc_length = sizeof(SINT64);
|
desc->dsc_length = sizeof(SINT64);
|
||||||
desc->dsc_sub_type = 0;
|
desc->dsc_sub_type = 0;
|
||||||
@ -598,6 +600,15 @@ void AvgAggNode::getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc)
|
|||||||
nodScale = desc->dsc_scale;
|
nodScale = desc->dsc_scale;
|
||||||
break;
|
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:
|
case dtype_unknown:
|
||||||
desc->dsc_dtype = dtype_unknown;
|
desc->dsc_dtype = dtype_unknown;
|
||||||
desc->dsc_length = 0;
|
desc->dsc_length = 0;
|
||||||
@ -697,12 +708,19 @@ dsc* AvgAggNode::aggExecute(thread_db* tdbb, jrd_req* request) const
|
|||||||
SINT64 i;
|
SINT64 i;
|
||||||
double d;
|
double d;
|
||||||
Decimal128 dec;
|
Decimal128 dec;
|
||||||
|
Int128 i128;
|
||||||
|
|
||||||
if (!dialect1 && impure->vlu_desc.dsc_dtype == dtype_int64)
|
if (!dialect1 && impure->vlu_desc.dsc_dtype == dtype_int64)
|
||||||
{
|
{
|
||||||
i = *((SINT64*) impure->vlu_desc.dsc_address) / impure->vlux_count;
|
i = *((SINT64*) impure->vlu_desc.dsc_address) / impure->vlux_count;
|
||||||
temp.makeInt64(impure->vlu_desc.dsc_scale, &i);
|
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))
|
else if (DTYPE_IS_DECFLOAT(impure->vlu_desc.dsc_dtype))
|
||||||
{
|
{
|
||||||
DecimalStatus decSt = tdbb->getAttachment()->att_dec_status;
|
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) <<
|
ERRD_post(Arg::Gds(isc_expression_eval_err) <<
|
||||||
Arg::Gds(isc_dsql_agg2_wrongarg) << Arg::Str("SUM"));
|
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))
|
else if (DTYPE_IS_EXACT(desc->dsc_dtype))
|
||||||
{
|
{
|
||||||
desc->dsc_dtype = dtype_int64;
|
desc->dsc_dtype = dtype_int64;
|
||||||
@ -1118,13 +1141,21 @@ void SumAggNode::getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc)
|
|||||||
{
|
{
|
||||||
case dtype_short:
|
case dtype_short:
|
||||||
case dtype_long:
|
case dtype_long:
|
||||||
case dtype_int64:
|
|
||||||
desc->dsc_dtype = dtype_int64;
|
desc->dsc_dtype = dtype_int64;
|
||||||
desc->dsc_length = sizeof(SINT64);
|
desc->dsc_length = sizeof(SINT64);
|
||||||
nodScale = desc->dsc_scale;
|
nodScale = desc->dsc_scale;
|
||||||
desc->dsc_flags = 0;
|
desc->dsc_flags = 0;
|
||||||
return;
|
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:
|
case dtype_unknown:
|
||||||
desc->dsc_dtype = dtype_unknown;
|
desc->dsc_dtype = dtype_unknown;
|
||||||
desc->dsc_length = 0;
|
desc->dsc_length = 0;
|
||||||
|
@ -4491,7 +4491,7 @@ void AlterDomainNode::checkUpdate(const dyn_fld& origFld, const dyn_fld& newFld)
|
|||||||
case blr_float:
|
case blr_float:
|
||||||
case blr_dec64:
|
case blr_dec64:
|
||||||
case blr_dec128:
|
case blr_dec128:
|
||||||
case blr_dec_fixed:
|
case blr_int128:
|
||||||
// Cannot convert column %s from character to non-character data.
|
// Cannot convert column %s from character to non-character data.
|
||||||
errorCode = isc_dyn_dtype_conv_invalid;
|
errorCode = isc_dyn_dtype_conv_invalid;
|
||||||
break;
|
break;
|
||||||
@ -4613,7 +4613,7 @@ void AlterDomainNode::checkUpdate(const dyn_fld& origFld, const dyn_fld& newFld)
|
|||||||
case blr_float:
|
case blr_float:
|
||||||
case blr_dec64:
|
case blr_dec64:
|
||||||
case blr_dec128:
|
case blr_dec128:
|
||||||
case blr_dec_fixed:
|
case blr_int128:
|
||||||
switch (newFld.dyn_dtype)
|
switch (newFld.dyn_dtype)
|
||||||
{
|
{
|
||||||
case blr_blob:
|
case blr_blob:
|
||||||
@ -4741,7 +4741,7 @@ void AlterDomainNode::checkUpdate(const dyn_fld& origFld, const dyn_fld& newFld)
|
|||||||
case blr_double:
|
case blr_double:
|
||||||
case blr_dec64:
|
case blr_dec64:
|
||||||
case blr_dec128:
|
case blr_dec128:
|
||||||
case blr_dec_fixed:
|
case blr_int128:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -4751,13 +4751,13 @@ void AlterDomainNode::checkUpdate(const dyn_fld& origFld, const dyn_fld& newFld)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case blr_dec_fixed:
|
case blr_int128:
|
||||||
switch (origFld.dyn_dtype)
|
switch (origFld.dyn_dtype)
|
||||||
{
|
{
|
||||||
case blr_short:
|
case blr_short:
|
||||||
case blr_long:
|
case blr_long:
|
||||||
case blr_int64:
|
case blr_int64:
|
||||||
case blr_dec_fixed:
|
case blr_int128:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -506,17 +506,19 @@ namespace
|
|||||||
const UCHAR DSC_ZTYPE_FLT64 = 0;
|
const UCHAR DSC_ZTYPE_FLT64 = 0;
|
||||||
const UCHAR DSC_ZTYPE_FLT128 = 1;
|
const UCHAR DSC_ZTYPE_FLT128 = 1;
|
||||||
const UCHAR DSC_ZTYPE_FIXED = 2;
|
const UCHAR DSC_ZTYPE_FIXED = 2;
|
||||||
const UCHAR DSC_ZTYPE_INT = 3;
|
const UCHAR DSC_ZTYPE_INT64 = 3;
|
||||||
const UCHAR DSC_ZTYPE_OTHER = 4;
|
const UCHAR DSC_ZTYPE_INT = 4;
|
||||||
const UCHAR DSC_ZTYPE_BAD = 5;
|
const UCHAR DSC_ZTYPE_OTHER = 5;
|
||||||
|
const UCHAR DSC_ZTYPE_BAD = 6;
|
||||||
|
|
||||||
const UCHAR decimalDescTable[5][5] = {
|
const UCHAR decimalDescTable[6][6] = {
|
||||||
/* DSC_ZTYPE_FLT64 DSC_ZTYPE_FLT128 DSC_ZTYPE_FIXED DSC_ZTYPE_INT DSC_ZTYPE_OTHER */
|
/* 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_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_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_FIXED */ {DSC_ZTYPE_FLT128, DSC_ZTYPE_FLT128, DSC_ZTYPE_FIXED, 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_INT64 */ {DSC_ZTYPE_FLT128, DSC_ZTYPE_FLT128, DSC_ZTYPE_FIXED, 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}
|
/* 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)
|
UCHAR getFType(const dsc& desc)
|
||||||
@ -527,8 +529,10 @@ UCHAR getFType(const dsc& desc)
|
|||||||
return DSC_ZTYPE_FLT64;
|
return DSC_ZTYPE_FLT64;
|
||||||
case dtype_dec128:
|
case dtype_dec128:
|
||||||
return DSC_ZTYPE_FLT128;
|
return DSC_ZTYPE_FLT128;
|
||||||
case dtype_dec_fixed:
|
case dtype_int128:
|
||||||
return DSC_ZTYPE_FIXED;
|
return DSC_ZTYPE_FIXED;
|
||||||
|
case dtype_int64:
|
||||||
|
return DSC_ZTYPE_INT64;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DTYPE_IS_EXACT(desc.dsc_dtype))
|
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
|
zipType = DSC_ZTYPE_FLT128; // In production case fallback to Decimal128
|
||||||
|
|
||||||
desc->dsc_dtype = zipType == DSC_ZTYPE_FLT64 ? dtype_dec64 :
|
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_sub_type = 0;
|
||||||
desc->dsc_flags = (desc1.dsc_flags | desc2.dsc_flags) & DSC_nullable;
|
desc->dsc_flags = (desc1.dsc_flags | desc2.dsc_flags) & DSC_nullable;
|
||||||
desc->dsc_scale = 0;
|
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;
|
*nodScale = desc->dsc_scale;
|
||||||
|
|
||||||
desc->dsc_length = zipType == DSC_ZTYPE_FLT64 ? sizeof(Decimal64) :
|
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
|
} // anon namespace
|
||||||
@ -764,7 +768,7 @@ void ArithmeticNode::makeDialect1(dsc* desc, dsc& desc1, dsc& desc2)
|
|||||||
|
|
||||||
case dtype_dec64:
|
case dtype_dec64:
|
||||||
case dtype_dec128:
|
case dtype_dec128:
|
||||||
case dtype_dec_fixed:
|
case dtype_int128:
|
||||||
setDecDesc(desc, desc1, desc2, SCALE_MIN);
|
setDecDesc(desc, desc1, desc2, SCALE_MIN);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -792,7 +796,7 @@ void ArithmeticNode::makeDialect1(dsc* desc, dsc& desc1, dsc& desc2)
|
|||||||
switch (dtype)
|
switch (dtype)
|
||||||
{
|
{
|
||||||
case dtype_dec128:
|
case dtype_dec128:
|
||||||
case dtype_dec_fixed:
|
case dtype_int128:
|
||||||
setDecDesc(desc, desc1, desc2, SCALE_SUM);
|
setDecDesc(desc, desc1, desc2, SCALE_SUM);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -887,8 +891,8 @@ void ArithmeticNode::makeDialect3(dsc* desc, dsc& desc1, dsc& desc2)
|
|||||||
// <timestamp> arithmetic, but returns a <double>
|
// <timestamp> arithmetic, but returns a <double>
|
||||||
if (DTYPE_IS_EXACT(dtype1) && DTYPE_IS_EXACT(dtype2))
|
if (DTYPE_IS_EXACT(dtype1) && DTYPE_IS_EXACT(dtype2))
|
||||||
{
|
{
|
||||||
if (desc1.isDecFixed() || desc2.isDecFixed())
|
if (desc1.isInt128() || desc2.isInt128())
|
||||||
dtype = dtype_dec_fixed;
|
dtype = dtype_int128;
|
||||||
else
|
else
|
||||||
dtype = dtype_int64;
|
dtype = dtype_int64;
|
||||||
}
|
}
|
||||||
@ -1027,7 +1031,7 @@ void ArithmeticNode::makeDialect3(dsc* desc, dsc& desc1, dsc& desc2)
|
|||||||
|
|
||||||
case dtype_dec64:
|
case dtype_dec64:
|
||||||
case dtype_dec128:
|
case dtype_dec128:
|
||||||
case dtype_dec_fixed:
|
case dtype_int128:
|
||||||
setDecDesc(desc, desc1, desc2, SCALE_MIN);
|
setDecDesc(desc, desc1, desc2, SCALE_MIN);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1076,7 +1080,7 @@ void ArithmeticNode::makeDialect3(dsc* desc, dsc& desc1, dsc& desc2)
|
|||||||
|
|
||||||
switch (dtype)
|
switch (dtype)
|
||||||
{
|
{
|
||||||
case dtype_dec_fixed:
|
case dtype_int128:
|
||||||
case dtype_dec128:
|
case dtype_dec128:
|
||||||
setDecDesc(desc, desc1, desc2, SCALE_SUM);
|
setDecDesc(desc, desc1, desc2, SCALE_SUM);
|
||||||
break;
|
break;
|
||||||
@ -1135,7 +1139,7 @@ void ArithmeticNode::makeDialect3(dsc* desc, dsc& desc1, dsc& desc2)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case dtype_dec128:
|
case dtype_dec128:
|
||||||
case dtype_dec_fixed:
|
case dtype_int128:
|
||||||
setDecDesc(desc, desc1, desc2, SCALE_SUM);
|
setDecDesc(desc, desc1, desc2, SCALE_SUM);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1347,7 +1351,7 @@ void ArithmeticNode::getDescDialect1(thread_db* /*tdbb*/, dsc* desc, dsc& desc1,
|
|||||||
|
|
||||||
case dtype_dec64:
|
case dtype_dec64:
|
||||||
case dtype_dec128:
|
case dtype_dec128:
|
||||||
case dtype_dec_fixed:
|
case dtype_int128:
|
||||||
nodFlags |= setDecDesc(desc, desc1, desc2, SCALE_MIN, &nodScale);
|
nodFlags |= setDecDesc(desc, desc1, desc2, SCALE_MIN, &nodScale);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1394,7 +1398,7 @@ void ArithmeticNode::getDescDialect1(thread_db* /*tdbb*/, dsc* desc, dsc& desc1,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case dtype_dec128:
|
case dtype_dec128:
|
||||||
case dtype_dec_fixed:
|
case dtype_int128:
|
||||||
nodFlags |= setDecDesc(desc, desc1, desc2, SCALE_SUM, &nodScale);
|
nodFlags |= setDecDesc(desc, desc1, desc2, SCALE_SUM, &nodScale);
|
||||||
break;
|
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 (DTYPE_IS_EXACT(dtype1) && DTYPE_IS_EXACT(dtype2))
|
||||||
{
|
{
|
||||||
if (desc1.isDecFixed() || desc2.isDecFixed())
|
if (desc1.isInt128() || desc2.isInt128())
|
||||||
dtype = dtype_dec_fixed;
|
dtype = dtype_int128;
|
||||||
else
|
else
|
||||||
dtype = dtype_int64;
|
dtype = dtype_int64;
|
||||||
}
|
}
|
||||||
@ -1620,7 +1624,7 @@ void ArithmeticNode::getDescDialect3(thread_db* /*tdbb*/, dsc* desc, dsc& desc1,
|
|||||||
|
|
||||||
case dtype_dec64:
|
case dtype_dec64:
|
||||||
case dtype_dec128:
|
case dtype_dec128:
|
||||||
case dtype_dec_fixed:
|
case dtype_int128:
|
||||||
nodFlags |= setDecDesc(desc, desc1, desc2, SCALE_MIN, &nodScale);
|
nodFlags |= setDecDesc(desc, desc1, desc2, SCALE_MIN, &nodScale);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -1674,7 +1678,7 @@ void ArithmeticNode::getDescDialect3(thread_db* /*tdbb*/, dsc* desc, dsc& desc1,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case dtype_dec128:
|
case dtype_dec128:
|
||||||
case dtype_dec_fixed:
|
case dtype_int128:
|
||||||
nodFlags |= setDecDesc(desc, desc1, desc2, SCALE_SUM, &nodScale);
|
nodFlags |= setDecDesc(desc, desc1, desc2, SCALE_SUM, &nodScale);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -1900,23 +1904,6 @@ dsc* ArithmeticNode::add(thread_db* tdbb, const dsc* desc, impure_value* value,
|
|||||||
return result;
|
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
|
// Handle floating arithmetic
|
||||||
|
|
||||||
if (node->nodFlags & FLAG_DOUBLE)
|
if (node->nodFlags & FLAG_DOUBLE)
|
||||||
@ -1996,19 +1983,20 @@ dsc* ArithmeticNode::add2(thread_db* tdbb, const dsc* desc, impure_value* value,
|
|||||||
return result;
|
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 Int128 d1 = MOV_get_int128(tdbb, desc, node->nodScale);
|
||||||
const DecimalFixed d2 = MOV_get_dec_fixed(tdbb, &value->vlu_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_int128 = (blrOp == blr_subtract) ? d2.sub(d1) : d1.add(d2);
|
||||||
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_dtype = dtype_int128;
|
||||||
result->dsc_length = sizeof(DecimalFixed);
|
result->dsc_length = sizeof(Int128);
|
||||||
result->dsc_scale = node->nodScale;
|
result->dsc_scale = node->nodScale;
|
||||||
result->dsc_sub_type = 0;
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
@ -2099,19 +2087,20 @@ dsc* ArithmeticNode::multiply(const dsc* desc, impure_value* value) const
|
|||||||
return &value->vlu_desc;
|
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 Int128 d1 = MOV_get_int128(tdbb, desc, nodScale);
|
||||||
const DecimalFixed d2 = MOV_get_dec_fixed(tdbb, &value->vlu_desc, nodScale);
|
const Int128 d2 = MOV_get_int128(tdbb, &value->vlu_desc, nodScale);
|
||||||
|
|
||||||
DecimalStatus decSt = tdbb->getAttachment()->att_dec_status;
|
value->vlu_misc.vlu_int128 = d1.mul(d2);
|
||||||
value->vlu_misc.vlu_dec_fixed = d1.mul(decSt, d2);
|
|
||||||
|
|
||||||
value->vlu_desc.dsc_dtype = dtype_dec_fixed;
|
value->vlu_desc.dsc_dtype = dtype_int128;
|
||||||
value->vlu_desc.dsc_length = sizeof(DecimalFixed);
|
value->vlu_desc.dsc_length = sizeof(Int128);
|
||||||
value->vlu_desc.dsc_scale = nodScale;
|
value->vlu_desc.dsc_scale = nodScale;
|
||||||
value->vlu_desc.dsc_sub_type = 0;
|
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;
|
return &value->vlu_desc;
|
||||||
}
|
}
|
||||||
@ -2210,20 +2199,21 @@ dsc* ArithmeticNode::multiply2(const dsc* desc, impure_value* value) const
|
|||||||
return &value->vlu_desc;
|
return &value->vlu_desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nodFlags & FLAG_DECFIXED)
|
// 128-bit arithmetic
|
||||||
|
|
||||||
|
if (nodFlags & FLAG_INT128)
|
||||||
{
|
{
|
||||||
const SSHORT scale = NUMERIC_SCALE(*desc);
|
const SSHORT scale = NUMERIC_SCALE(*desc);
|
||||||
const DecimalFixed d1 = MOV_get_dec_fixed(tdbb, desc, scale);
|
const Int128 d1 = MOV_get_int128(tdbb, desc, scale);
|
||||||
const DecimalFixed d2 = MOV_get_dec_fixed(tdbb, &value->vlu_desc, nodScale - scale);
|
const Int128 d2 = MOV_get_int128(tdbb, &value->vlu_desc, nodScale - scale);
|
||||||
|
|
||||||
DecimalStatus decSt = tdbb->getAttachment()->att_dec_status;
|
value->vlu_misc.vlu_int128 = d1.mul(d2);
|
||||||
value->vlu_misc.vlu_dec_fixed = d1.mul(decSt, d2);
|
|
||||||
|
|
||||||
value->vlu_desc.dsc_dtype = dtype_dec_fixed;
|
value->vlu_desc.dsc_dtype = dtype_int128;
|
||||||
value->vlu_desc.dsc_length = sizeof(DecimalFixed);
|
value->vlu_desc.dsc_length = sizeof(Int128);
|
||||||
value->vlu_desc.dsc_scale = nodScale;
|
value->vlu_desc.dsc_scale = nodScale;
|
||||||
value->vlu_desc.dsc_sub_type = 0;
|
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;
|
return &value->vlu_desc;
|
||||||
}
|
}
|
||||||
@ -2324,20 +2314,21 @@ dsc* ArithmeticNode::divide2(const dsc* desc, impure_value* value) const
|
|||||||
return &value->vlu_desc;
|
return &value->vlu_desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nodFlags & FLAG_DECFIXED)
|
// 128-bit arithmetic
|
||||||
|
|
||||||
|
if (nodFlags & FLAG_INT128)
|
||||||
{
|
{
|
||||||
const SSHORT scale = NUMERIC_SCALE(*desc);
|
const SSHORT scale = NUMERIC_SCALE(*desc);
|
||||||
const DecimalFixed d2 = MOV_get_dec_fixed(tdbb, desc, scale);
|
const Int128 d2 = MOV_get_int128(tdbb, desc, scale);
|
||||||
const DecimalFixed d1 = MOV_get_dec_fixed(tdbb, &value->vlu_desc, nodScale - scale);
|
const Int128 d1 = MOV_get_int128(tdbb, &value->vlu_desc, nodScale - scale);
|
||||||
|
|
||||||
DecimalStatus decSt = tdbb->getAttachment()->att_dec_status;
|
value->vlu_misc.vlu_int128 = d1.div(d2, scale * 2);
|
||||||
value->vlu_misc.vlu_dec_fixed = d1.div(decSt, d2, scale * 2);
|
|
||||||
|
|
||||||
value->vlu_desc.dsc_dtype = dtype_dec_fixed;
|
value->vlu_desc.dsc_dtype = dtype_int128;
|
||||||
value->vlu_desc.dsc_length = sizeof(DecimalFixed);
|
value->vlu_desc.dsc_length = sizeof(Int128);
|
||||||
value->vlu_desc.dsc_scale = nodScale;
|
value->vlu_desc.dsc_scale = nodScale;
|
||||||
value->vlu_desc.dsc_sub_type = 0;
|
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;
|
return &value->vlu_desc;
|
||||||
}
|
}
|
||||||
@ -7383,18 +7374,17 @@ DmlNode* LiteralNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch*
|
|||||||
case dtype_double:
|
case dtype_double:
|
||||||
case dtype_dec128:
|
case dtype_dec128:
|
||||||
{
|
{
|
||||||
SSHORT scale;
|
|
||||||
UCHAR dtype;
|
|
||||||
|
|
||||||
// The double literal could potentially be used for any numeric literal - the value is
|
// 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
|
// passed as if it were a text string. Convert the numeric string to its binary value
|
||||||
// (int64, long or double as appropriate).
|
// (int64, long or double as appropriate).
|
||||||
|
|
||||||
l = csb->csb_blr_reader.getWord();
|
l = csb->csb_blr_reader.getWord();
|
||||||
q = csb->csb_blr_reader.getPos();
|
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->litDesc.dsc_dtype = dtype;
|
||||||
node->dsqlStr = FB_NEW_POOL(pool) IntlString(pool, string(q, l));
|
node->dsqlStr = FB_NEW_POOL(pool) IntlString(pool, string(q, l));
|
||||||
|
node->litDesc.dsc_scale = (SCHAR) scale;
|
||||||
|
|
||||||
switch (dtype)
|
switch (dtype)
|
||||||
{
|
{
|
||||||
@ -7406,11 +7396,9 @@ DmlNode* LiteralNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch*
|
|||||||
break;
|
break;
|
||||||
case dtype_long:
|
case dtype_long:
|
||||||
node->litDesc.dsc_length = sizeof(SLONG);
|
node->litDesc.dsc_length = sizeof(SLONG);
|
||||||
node->litDesc.dsc_scale = (SCHAR) scale;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
node->litDesc.dsc_length = sizeof(SINT64);
|
node->litDesc.dsc_length = sizeof(SINT64);
|
||||||
node->litDesc.dsc_scale = (SCHAR) scale;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -7846,25 +7834,34 @@ bool LiteralNode::sameAs(CompilerScratch* csb, const ExprNode* other, bool ignor
|
|||||||
|
|
||||||
ValueExprNode* LiteralNode::pass2(thread_db* tdbb, CompilerScratch* csb)
|
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());
|
const string& s(dsqlStr->getString());
|
||||||
dsc desc;
|
dsc desc;
|
||||||
desc.makeText(s.length(), CS_ASCII, (UCHAR*) s.c_str());
|
desc.makeText(s.length(), CS_ASCII, (UCHAR*) s.c_str());
|
||||||
|
|
||||||
switch (csb->csb_preferredDataType)
|
switch (csb->csb_preferredDesc->dsc_dtype)
|
||||||
{
|
{
|
||||||
case dtype_dec64:
|
case dtype_dec64:
|
||||||
*((Decimal64*) litDesc.dsc_address) = CVT_get_dec64(&desc,
|
*((Decimal64*) litDesc.dsc_address) = CVT_get_dec64(&desc,
|
||||||
tdbb->getAttachment()->att_dec_status, ERR_post);
|
tdbb->getAttachment()->att_dec_status, ERR_post);
|
||||||
litDesc.dsc_dtype = dtype_dec64;
|
litDesc.dsc_dtype = dtype_dec64;
|
||||||
|
litDesc.dsc_scale = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case dtype_dec128:
|
case dtype_dec128:
|
||||||
case dtype_dec_fixed:
|
|
||||||
*((Decimal128*) litDesc.dsc_address) = CVT_get_dec128(&desc,
|
*((Decimal128*) litDesc.dsc_address) = CVT_get_dec128(&desc,
|
||||||
tdbb->getAttachment()->att_dec_status, ERR_post);
|
tdbb->getAttachment()->att_dec_status, ERR_post);
|
||||||
litDesc.dsc_dtype = dtype_dec128;
|
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;
|
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();
|
impure->vlu_misc.vlu_dec128 = impure->vlu_misc.vlu_dec128.neg();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case dtype_dec_fixed:
|
case dtype_int128:
|
||||||
impure->vlu_misc.vlu_dec_fixed = impure->vlu_misc.vlu_dec_fixed.neg();
|
impure->vlu_misc.vlu_int128 = impure->vlu_misc.vlu_int128.neg();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case dtype_int64:
|
case dtype_int64:
|
||||||
@ -11091,7 +11088,7 @@ void SubQueryNode::getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc)
|
|||||||
|
|
||||||
case dtype_dec64:
|
case dtype_dec64:
|
||||||
case dtype_dec128:
|
case dtype_dec128:
|
||||||
case dtype_dec_fixed:
|
case dtype_int128:
|
||||||
desc->dsc_dtype = dtype_dec128;
|
desc->dsc_dtype = dtype_dec128;
|
||||||
desc->dsc_length = sizeof(Decimal128);
|
desc->dsc_length = sizeof(Decimal128);
|
||||||
desc->dsc_scale = 0;
|
desc->dsc_scale = 0;
|
||||||
|
@ -532,7 +532,7 @@ public:
|
|||||||
static const unsigned FLAG_DATE = 0x20;
|
static const unsigned FLAG_DATE = 0x20;
|
||||||
static const unsigned FLAG_DECFLOAT = 0x40;
|
static const unsigned FLAG_DECFLOAT = 0x40;
|
||||||
static const unsigned FLAG_VALUE = 0x80; // Full value area required in impure space.
|
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)
|
explicit ExprNode(Type aType, MemoryPool& pool)
|
||||||
: DmlNode(pool),
|
: DmlNode(pool),
|
||||||
|
@ -501,7 +501,7 @@ AssignmentNode* AssignmentNode::pass2(thread_db* tdbb, CompilerScratch* csb)
|
|||||||
{ // scope
|
{ // scope
|
||||||
dsc desc;
|
dsc desc;
|
||||||
asgnTo->getDesc(tdbb, csb, &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, asgnFrom.getAddress());
|
||||||
}
|
}
|
||||||
ExprNode::doPass2(tdbb, csb, asgnTo.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);
|
SET_TDBB(tdbb);
|
||||||
Attachment* const attachment = tdbb->getAttachment();
|
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/Nodes.h"
|
||||||
#include "../dsql/DdlNodes.h"
|
#include "../dsql/DdlNodes.h"
|
||||||
#include "../dsql/NodePrinter.h"
|
#include "../dsql/NodePrinter.h"
|
||||||
|
#include "../common/DecFloat.h"
|
||||||
|
|
||||||
namespace Jrd {
|
namespace Jrd {
|
||||||
|
|
||||||
@ -1748,11 +1749,13 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class SetDecFloatBindNode : public SessionManagementNode
|
class SetHighPrecBindNode : public SessionManagementNode
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SetDecFloatBindNode(MemoryPool& pool)
|
SetHighPrecBindNode(MemoryPool& pool, bool isInt128)
|
||||||
: SessionManagementNode(pool)
|
: SessionManagementNode(pool),
|
||||||
|
bind(Firebird::NumericBinding::NUM_NATIVE),
|
||||||
|
bindInt128(isInt128)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1764,13 +1767,14 @@ public:
|
|||||||
NODE_PRINT(printer, bind.bind);
|
NODE_PRINT(printer, bind.bind);
|
||||||
NODE_PRINT(printer, bind.numScale);
|
NODE_PRINT(printer, bind.numScale);
|
||||||
|
|
||||||
return "SetDecFloatBindNode";
|
return "SetHighPrecBindNode";
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void execute(thread_db* tdbb, dsql_req* request, jrd_tra** traHandle) const;
|
virtual void execute(thread_db* tdbb, dsql_req* request, jrd_tra** traHandle) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Firebird::DecimalBinding bind;
|
Firebird::NumericBinding bind;
|
||||||
|
bool bindInt128;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ const USHORT blr_dtypes[] = {
|
|||||||
blr_bool, // dtype_boolean
|
blr_bool, // dtype_boolean
|
||||||
blr_dec64, // dtype_dec64
|
blr_dec64, // dtype_dec64
|
||||||
blr_dec128, // dtype_dec128
|
blr_dec128, // dtype_dec128
|
||||||
blr_dec_fixed, // dtype_dec_fixed
|
blr_int128, // dtype_int128
|
||||||
blr_sql_time_tz, // dtype_sql_time_tz
|
blr_sql_time_tz, // dtype_sql_time_tz
|
||||||
blr_timestamp_tz // dtype_timestamp_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;
|
desc.dsc_address = dsql_msg_buf + (IPTR) desc.dsc_address;
|
||||||
|
|
||||||
if (notNull)
|
if (notNull)
|
||||||
MOVD_move(tdbb, &parDesc, &desc, toExternal);
|
MOVD_move(tdbb, &parDesc, &desc);
|
||||||
else
|
else
|
||||||
memset(desc.dsc_address, 0, desc.dsc_length);
|
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.
|
// Safe cast because desc is used as source only.
|
||||||
desc.dsc_address = const_cast<UCHAR*>(in_dsql_msg_buf) + (IPTR) desc.dsc_address;
|
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
|
else
|
||||||
memset(parDesc.dsc_address, 0, parDesc.dsc_length);
|
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;
|
dsc desc = parameter->par_desc;
|
||||||
desc.dsc_address = msgBuffer + (IPTR) desc.dsc_address;
|
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;
|
dsql_par* null_ind = parameter->par_null;
|
||||||
if (null_ind != 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;
|
dsc desc = parameter->par_desc;
|
||||||
desc.dsc_address = msgBuffer + (IPTR) desc.dsc_address;
|
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;
|
dsql_par* null_ind = parameter->par_null;
|
||||||
if (null_ind != NULL)
|
if (null_ind != NULL)
|
||||||
|
@ -256,8 +256,8 @@ public:
|
|||||||
precision = 18;
|
precision = 18;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case dtype_dec_fixed:
|
case dtype_int128:
|
||||||
precision = 34;
|
precision = 38;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -203,21 +203,24 @@ void GEN_port(DsqlCompilerScratch* dsqlScratch, dsql_msg* message)
|
|||||||
if (fromCharSet != toCharSet)
|
if (fromCharSet != toCharSet)
|
||||||
parameter->par_desc.setTextType(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)
|
switch (b.bind)
|
||||||
{
|
{
|
||||||
case DecimalBinding::DEC_NATIVE:
|
case NumericBinding::NUM_NATIVE:
|
||||||
break;
|
break;
|
||||||
case DecimalBinding::DEC_TEXT:
|
case NumericBinding::NUM_TEXT:
|
||||||
parameter->par_desc.makeText((parameter->par_desc.dsc_dtype == dtype_dec64 ?
|
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;
|
break;
|
||||||
case DecimalBinding::DEC_DOUBLE:
|
case NumericBinding::NUM_DOUBLE:
|
||||||
parameter->par_desc.makeDouble();
|
parameter->par_desc.makeDouble();
|
||||||
break;
|
break;
|
||||||
case DecimalBinding::DEC_NUMERIC:
|
case NumericBinding::NUM_INT64:
|
||||||
parameter->par_desc.makeInt64(b.numScale);
|
parameter->par_desc.makeInt64(b.numScale);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -415,8 +418,8 @@ void GEN_descriptor( DsqlCompilerScratch* dsqlScratch, const dsc* desc, bool tex
|
|||||||
dsqlScratch->appendUChar(blr_dec128);
|
dsqlScratch->appendUChar(blr_dec128);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case dtype_dec_fixed:
|
case dtype_int128:
|
||||||
dsqlScratch->appendUChar(blr_dec_fixed);
|
dsqlScratch->appendUChar(blr_int128);
|
||||||
dsqlScratch->appendUChar(desc->dsc_scale);
|
dsqlScratch->appendUChar(desc->dsc_scale);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -33,11 +33,11 @@ using namespace Firebird;
|
|||||||
|
|
||||||
|
|
||||||
// Move (and possible convert) something to something else.
|
// 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
|
try
|
||||||
{
|
{
|
||||||
MOV_move_ext(tdbb, from, to, toExternal);
|
MOV_move(tdbb, from, to);
|
||||||
}
|
}
|
||||||
catch (const status_exception& ex)
|
catch (const status_exception& ex)
|
||||||
{
|
{
|
||||||
|
@ -24,6 +24,6 @@
|
|||||||
#ifndef DSQL_MOVD_PROTO_H
|
#ifndef DSQL_MOVD_PROTO_H
|
||||||
#define 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
|
#endif // DSQL_MOVD_PROTO_H
|
||||||
|
@ -613,6 +613,7 @@ using namespace Firebird;
|
|||||||
%token <metaNamePtr> HEX_ENCODE
|
%token <metaNamePtr> HEX_ENCODE
|
||||||
%token <metaNamePtr> IDLE
|
%token <metaNamePtr> IDLE
|
||||||
%token <metaNamePtr> INVOKER
|
%token <metaNamePtr> INVOKER
|
||||||
|
%token <metaNamePtr> INT128
|
||||||
%token <metaNamePtr> IV
|
%token <metaNamePtr> IV
|
||||||
%token <metaNamePtr> LAST_DAY
|
%token <metaNamePtr> LAST_DAY
|
||||||
%token <metaNamePtr> LEGACY
|
%token <metaNamePtr> LEGACY
|
||||||
@ -816,7 +817,7 @@ using namespace Firebird;
|
|||||||
Jrd::CreateAlterRoleNode* createAlterRoleNode;
|
Jrd::CreateAlterRoleNode* createAlterRoleNode;
|
||||||
Jrd::SetDecFloatRoundNode* setDecFloatRoundNode;
|
Jrd::SetDecFloatRoundNode* setDecFloatRoundNode;
|
||||||
Jrd::SetDecFloatTrapsNode* setDecFloatTrapsNode;
|
Jrd::SetDecFloatTrapsNode* setDecFloatTrapsNode;
|
||||||
Jrd::SetDecFloatBindNode* setDecFloatBindNode;
|
Jrd::SetHighPrecBindNode* setHighPrecBindNode;
|
||||||
Jrd::SessionResetNode* sessionResetNode;
|
Jrd::SessionResetNode* sessionResetNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4224,6 +4225,7 @@ keyword_or_column
|
|||||||
| VAR_SAMP
|
| VAR_SAMP
|
||||||
| VAR_POP
|
| VAR_POP
|
||||||
| DECFLOAT // added in FB 4.0
|
| DECFLOAT // added in FB 4.0
|
||||||
|
| INT128
|
||||||
| LOCAL
|
| LOCAL
|
||||||
| LOCALTIME
|
| LOCALTIME
|
||||||
| LOCALTIMESTAMP
|
| LOCALTIMESTAMP
|
||||||
@ -4971,14 +4973,14 @@ prec_scale
|
|||||||
{
|
{
|
||||||
$$ = newNode<dsql_fld>();
|
$$ = newNode<dsql_fld>();
|
||||||
|
|
||||||
if ($2 < 1 || $2 > 34)
|
if ($2 < 1 || $2 > 38)
|
||||||
yyabandon(YYPOSNARG(2), -842, Arg::Gds(isc_precision_err2) << Arg::Num(1) << Arg::Num(34));
|
yyabandon(YYPOSNARG(2), -842, Arg::Gds(isc_precision_err2) << Arg::Num(1) << Arg::Num(38));
|
||||||
// Precision must be between 1 and 34
|
// Precision must be between 1 and 38
|
||||||
|
|
||||||
if ($2 > 18)
|
if ($2 > 18)
|
||||||
{
|
{
|
||||||
$$->dtype = dtype_dec_fixed;
|
$$->dtype = dtype_int128;
|
||||||
$$->length = sizeof(DecimalFixed);
|
$$->length = sizeof(Int128);
|
||||||
}
|
}
|
||||||
else if ($2 > 9)
|
else if ($2 > 9)
|
||||||
{
|
{
|
||||||
@ -5027,17 +5029,17 @@ prec_scale
|
|||||||
{
|
{
|
||||||
$$ = newNode<dsql_fld>();
|
$$ = newNode<dsql_fld>();
|
||||||
|
|
||||||
if ($2 < 1 || $2 > 34)
|
if ($2 < 1 || $2 > 38)
|
||||||
yyabandon(YYPOSNARG(2), -842, Arg::Gds(isc_precision_err2) << Arg::Num(1) << Arg::Num(34));
|
yyabandon(YYPOSNARG(2), -842, Arg::Gds(isc_precision_err2) << Arg::Num(1) << Arg::Num(38));
|
||||||
// Precision must be between 1 and 34
|
// Precision must be between 1 and 38
|
||||||
|
|
||||||
if ($4 > $2 || $4 < 0)
|
if ($4 > $2 || $4 < 0)
|
||||||
yyabandon(YYPOSNARG(4), -842, isc_scale_nogt); // Scale must be between 0 and precision
|
yyabandon(YYPOSNARG(4), -842, isc_scale_nogt); // Scale must be between 0 and precision
|
||||||
|
|
||||||
if ($2 > 18)
|
if ($2 > 18)
|
||||||
{
|
{
|
||||||
$$->dtype = dtype_dec_fixed;
|
$$->dtype = dtype_int128;
|
||||||
$$->length = sizeof(DecimalFixed);
|
$$->length = sizeof(Int128);
|
||||||
}
|
}
|
||||||
else if ($2 > 9)
|
else if ($2 > 9)
|
||||||
{
|
{
|
||||||
@ -5270,14 +5272,20 @@ set_decfloat_traps
|
|||||||
{ $$ = $5; }
|
{ $$ = $5; }
|
||||||
;
|
;
|
||||||
|
|
||||||
%type <setDecFloatBindNode> set_decfloat_bind
|
%type <setHighPrecBindNode> set_decfloat_bind
|
||||||
set_decfloat_bind
|
set_decfloat_bind
|
||||||
: SET DECFLOAT BIND
|
: SET bind_to_type BIND
|
||||||
{ $$ = newNode<SetDecFloatBindNode>(); }
|
{ $$ = newNode<SetHighPrecBindNode>($2); }
|
||||||
decfloat_bind_clause($4)
|
decfloat_bind_clause($4)
|
||||||
{ $$ = $4; }
|
{ $$ = $4; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
%type <boolVal> bind_to_type
|
||||||
|
bind_to_type
|
||||||
|
: DECFLOAT { $$ = false; }
|
||||||
|
| INT128 { $$ = true; }
|
||||||
|
;
|
||||||
|
|
||||||
%type decfloat_traps_list_opt(<setDecFloatTrapsNode>)
|
%type decfloat_traps_list_opt(<setDecFloatTrapsNode>)
|
||||||
decfloat_traps_list_opt($setDecFloatTrapsNode)
|
decfloat_traps_list_opt($setDecFloatTrapsNode)
|
||||||
: // nothing
|
: // nothing
|
||||||
@ -5296,26 +5304,26 @@ decfloat_trap($setDecFloatTrapsNode)
|
|||||||
{ $setDecFloatTrapsNode->trap($1); }
|
{ $setDecFloatTrapsNode->trap($1); }
|
||||||
;
|
;
|
||||||
|
|
||||||
%type decfloat_bind_clause(<setDecFloatBindNode>)
|
%type decfloat_bind_clause(<setHighPrecBindNode>)
|
||||||
decfloat_bind_clause($setDecFloatBindNode)
|
decfloat_bind_clause($setHighPrecBindNode)
|
||||||
: NATIVE
|
: NATIVE
|
||||||
// do nothing
|
// do nothing
|
||||||
| character_keyword
|
| character_keyword
|
||||||
{ $setDecFloatBindNode->bind.bind = DecimalBinding::DEC_TEXT; }
|
{ $setHighPrecBindNode->bind.bind = NumericBinding::NUM_TEXT; }
|
||||||
| DOUBLE PRECISION
|
| DOUBLE PRECISION
|
||||||
{ $setDecFloatBindNode->bind.bind = DecimalBinding::DEC_DOUBLE; }
|
{ $setHighPrecBindNode->bind.bind = NumericBinding::NUM_DOUBLE; }
|
||||||
| BIGINT decfloat_scale_clause($setDecFloatBindNode)
|
| BIGINT decfloat_scale_clause($setHighPrecBindNode)
|
||||||
{ $setDecFloatBindNode->bind.bind = DecimalBinding::DEC_NUMERIC; }
|
{ $setHighPrecBindNode->bind.bind = NumericBinding::NUM_INT64; }
|
||||||
;
|
;
|
||||||
|
|
||||||
%type decfloat_scale_clause(<setDecFloatBindNode>)
|
%type decfloat_scale_clause(<setHighPrecBindNode>)
|
||||||
decfloat_scale_clause($setDecFloatBindNode)
|
decfloat_scale_clause($setHighPrecBindNode)
|
||||||
: // nothing
|
: // nothing
|
||||||
| ',' signed_long_integer
|
| ',' 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
|
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
|
%type <setSessionNode> session_statement
|
||||||
|
@ -34,6 +34,7 @@ typedef ISC_TIME_TZ;
|
|||||||
typedef ISC_TIMESTAMP_TZ;
|
typedef ISC_TIMESTAMP_TZ;
|
||||||
typedef FB_DEC16;
|
typedef FB_DEC16;
|
||||||
typedef FB_DEC34;
|
typedef FB_DEC34;
|
||||||
|
typedef FB_I128;
|
||||||
typedef isc_tr_handle;
|
typedef isc_tr_handle;
|
||||||
typedef isc_stmt_handle;
|
typedef isc_stmt_handle;
|
||||||
|
|
||||||
@ -1093,7 +1094,7 @@ interface Util : Versioned
|
|||||||
XpbBuilder getXpbBuilder(Status status, uint kind, const uchar* buf, uint len);
|
XpbBuilder getXpbBuilder(Status status, uint kind, const uchar* buf, uint len);
|
||||||
uint setOffsets(Status status, MessageMetadata metadata, OffsetsCallback callback);
|
uint setOffsets(Status status, MessageMetadata metadata, OffsetsCallback callback);
|
||||||
|
|
||||||
version: // 3.0 => 4.0
|
version: // 3.0 => 4.0 Alpha1
|
||||||
DecFloat16 getDecFloat16(Status status);
|
DecFloat16 getDecFloat16(Status status);
|
||||||
DecFloat34 getDecFloat34(Status status);
|
DecFloat34 getDecFloat34(Status status);
|
||||||
Transaction getTransactionByHandle(Status status, isc_tr_handle* hndlPtr);
|
Transaction getTransactionByHandle(Status status, isc_tr_handle* hndlPtr);
|
||||||
@ -1106,6 +1107,9 @@ version: // 3.0 => 4.0
|
|||||||
uint fractions, const string timeZone);
|
uint fractions, const string timeZone);
|
||||||
void encodeTimeStampTz(Status status, ISC_TIMESTAMP_TZ* timeStampTz, uint year, uint month, uint day,
|
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);
|
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
|
interface OffsetsCallback : Versioned
|
||||||
@ -1515,6 +1519,15 @@ interface DecFloat34 : Versioned
|
|||||||
void fromString(Status status, const string from, FB_DEC34* to);
|
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
|
// Replication interfaces
|
||||||
|
|
||||||
interface ReplicatedRecord : Versioned
|
interface ReplicatedRecord : Versioned
|
||||||
|
@ -116,6 +116,7 @@ namespace Firebird
|
|||||||
class IUdrPlugin;
|
class IUdrPlugin;
|
||||||
class IDecFloat16;
|
class IDecFloat16;
|
||||||
class IDecFloat34;
|
class IDecFloat34;
|
||||||
|
class IInt128;
|
||||||
class IReplicatedRecord;
|
class IReplicatedRecord;
|
||||||
class IReplicatedBlob;
|
class IReplicatedBlob;
|
||||||
class IReplicatedTransaction;
|
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 *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 *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();
|
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:
|
protected:
|
||||||
@ -4064,7 +4066,7 @@ namespace Firebird
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static const unsigned VERSION = 3;
|
static const unsigned VERSION = 4;
|
||||||
|
|
||||||
template <typename StatusType> void getFbVersion(StatusType* status, IAttachment* att, IVersionCallback* callback)
|
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);
|
static_cast<VTable*>(this->cloopVTable)->encodeTimeStampTz(this, status, timeStampTz, year, month, day, hours, minutes, seconds, fractions, timeZone);
|
||||||
StatusType::checkException(status);
|
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
|
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
|
class IReplicatedRecord : public IVersioned
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -14332,6 +14387,7 @@ namespace Firebird
|
|||||||
this->decodeTimeStampTz = &Name::cloopdecodeTimeStampTzDispatcher;
|
this->decodeTimeStampTz = &Name::cloopdecodeTimeStampTzDispatcher;
|
||||||
this->encodeTimeTz = &Name::cloopencodeTimeTzDispatcher;
|
this->encodeTimeTz = &Name::cloopencodeTimeTzDispatcher;
|
||||||
this->encodeTimeStampTz = &Name::cloopencodeTimeStampTzDispatcher;
|
this->encodeTimeStampTz = &Name::cloopencodeTimeStampTzDispatcher;
|
||||||
|
this->getInt128 = &Name::cloopgetInt128Dispatcher;
|
||||||
}
|
}
|
||||||
} vTable;
|
} vTable;
|
||||||
|
|
||||||
@ -14630,6 +14686,21 @@ namespace Firebird
|
|||||||
StatusType::catchException(&status2);
|
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> > >
|
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 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 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 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>
|
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;
|
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>
|
template <typename Name, typename StatusType, typename Base>
|
||||||
class IReplicatedRecordBaseImpl : public Base
|
class IReplicatedRecordBaseImpl : public Base
|
||||||
{
|
{
|
||||||
|
@ -69,7 +69,7 @@
|
|||||||
#define blr_bool (unsigned char)23
|
#define blr_bool (unsigned char)23
|
||||||
#define blr_dec64 (unsigned char)24
|
#define blr_dec64 (unsigned char)24
|
||||||
#define blr_dec128 (unsigned char)25
|
#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_sql_time_tz (unsigned char)28
|
||||||
#define blr_timestamp_tz (unsigned char)29
|
#define blr_timestamp_tz (unsigned char)29
|
||||||
|
|
||||||
|
@ -129,6 +129,7 @@
|
|||||||
#define isc_dpb_decfloat_bind 94
|
#define isc_dpb_decfloat_bind 94
|
||||||
#define isc_dpb_decfloat_round 95
|
#define isc_dpb_decfloat_round 95
|
||||||
#define isc_dpb_decfloat_traps 96
|
#define isc_dpb_decfloat_traps 96
|
||||||
|
#define isc_dpb_int128_bind 97
|
||||||
|
|
||||||
|
|
||||||
/**************************************************/
|
/**************************************************/
|
||||||
|
@ -63,7 +63,7 @@
|
|||||||
#define dtype_boolean 21
|
#define dtype_boolean 21
|
||||||
#define dtype_dec64 22
|
#define dtype_dec64 22
|
||||||
#define dtype_dec128 23
|
#define dtype_dec128 23
|
||||||
#define dtype_dec_fixed 24
|
#define dtype_int128 24
|
||||||
#define dtype_sql_time_tz 25
|
#define dtype_sql_time_tz 25
|
||||||
#define dtype_timestamp_tz 26
|
#define dtype_timestamp_tz 26
|
||||||
#define DTYPE_TYPE_MAX 27
|
#define DTYPE_TYPE_MAX 27
|
||||||
|
@ -78,9 +78,9 @@ typedef struct
|
|||||||
#define SQL_TYPE_TIME 560
|
#define SQL_TYPE_TIME 560
|
||||||
#define SQL_TYPE_DATE 570
|
#define SQL_TYPE_DATE 570
|
||||||
#define SQL_INT64 580
|
#define SQL_INT64 580
|
||||||
|
#define SQL_INT128 32752
|
||||||
#define SQL_TIMESTAMP_TZ 32754
|
#define SQL_TIMESTAMP_TZ 32754
|
||||||
#define SQL_TIME_TZ 32756
|
#define SQL_TIME_TZ 32756
|
||||||
#define SQL_DEC_FIXED 32758
|
|
||||||
#define SQL_DEC16 32760
|
#define SQL_DEC16 32760
|
||||||
#define SQL_DEC34 32762
|
#define SQL_DEC34 32762
|
||||||
#define SQL_BOOLEAN 32764
|
#define SQL_BOOLEAN 32764
|
||||||
|
@ -197,7 +197,12 @@ struct FB_DEC34_t {
|
|||||||
ISC_UINT64 fb_data[2];
|
ISC_UINT64 fb_data[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct FB_I128_t {
|
||||||
|
ISC_UINT64 fb_data[2];
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct FB_DEC16_t FB_DEC16;
|
typedef struct FB_DEC16_t FB_DEC16;
|
||||||
typedef struct FB_DEC34_t FB_DEC34;
|
typedef struct FB_DEC34_t FB_DEC34;
|
||||||
|
typedef struct FB_I128_t FB_I128;
|
||||||
|
|
||||||
#endif /* FIREBIRD_IMPL_TYPES_PUB_H */
|
#endif /* FIREBIRD_IMPL_TYPES_PUB_H */
|
||||||
|
@ -320,6 +320,7 @@ IsqlGlobals::IsqlGlobals()
|
|||||||
|
|
||||||
df16 = Firebird::UtilInterfacePtr()->getDecFloat16(&statusWrapper);
|
df16 = Firebird::UtilInterfacePtr()->getDecFloat16(&statusWrapper);
|
||||||
df34 = Firebird::UtilInterfacePtr()->getDecFloat34(&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
|
// 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 INTEGER:
|
||||||
case BIGINT:
|
case BIGINT:
|
||||||
case DOUBLE_PRECISION:
|
case DOUBLE_PRECISION:
|
||||||
case DEC_FIXED_TYPE:
|
case blr_int128:
|
||||||
// Handle Integral subtypes NUMERIC and DECIMAL
|
// Handle Integral subtypes NUMERIC and DECIMAL
|
||||||
// We are ODS >= 10 and could be any Dialect
|
// 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:
|
case DOUBLE_PRECISION:
|
||||||
isqlGlob.printf("NUMERIC(15, %d)", -fieldScale);
|
isqlGlob.printf("NUMERIC(15, %d)", -fieldScale);
|
||||||
break;
|
break;
|
||||||
case DEC_FIXED_TYPE:
|
case blr_int128:
|
||||||
isqlGlob.printf("NUMERIC(34, %d)", -fieldScale);
|
isqlGlob.printf("NUMERIC(38, %d)", -fieldScale);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2288,6 +2289,7 @@ static processing_state add_row(TEXT* tabname)
|
|||||||
double* dvalue;
|
double* dvalue;
|
||||||
FB_DEC16* d64value;
|
FB_DEC16* d64value;
|
||||||
FB_DEC34* d128value;
|
FB_DEC34* d128value;
|
||||||
|
FB_I128* i128value;
|
||||||
UCHAR* boolean;
|
UCHAR* boolean;
|
||||||
ISC_QUAD* blobid;
|
ISC_QUAD* blobid;
|
||||||
vary* avary;
|
vary* avary;
|
||||||
@ -2361,11 +2363,27 @@ static processing_state add_row(TEXT* tabname)
|
|||||||
if ((!isqlGlob.df16) || (fbStatus->getState() & Firebird::IStatus::STATE_ERRORS))
|
if ((!isqlGlob.df16) || (fbStatus->getState() & Firebird::IStatus::STATE_ERRORS))
|
||||||
{
|
{
|
||||||
STDERROUT("Input parsing problem");
|
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;
|
done = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_DEC_FIXED:
|
|
||||||
case SQL_DEC34:
|
case SQL_DEC34:
|
||||||
d128value = (FB_DEC34*) datap;
|
d128value = (FB_DEC34*) datap;
|
||||||
if (isqlGlob.df34)
|
if (isqlGlob.df34)
|
||||||
@ -2373,6 +2391,7 @@ static processing_state add_row(TEXT* tabname)
|
|||||||
if ((!isqlGlob.df34) || (fbStatus->getState() & Firebird::IStatus::STATE_ERRORS))
|
if ((!isqlGlob.df34) || (fbStatus->getState() & Firebird::IStatus::STATE_ERRORS))
|
||||||
{
|
{
|
||||||
STDERROUT("Input parsing problem");
|
STDERROUT("Input parsing problem");
|
||||||
|
ISQL_errmsg(fbStatus);
|
||||||
done = true;
|
done = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -3068,6 +3087,7 @@ static processing_state bulk_insert_hack(const char* command)
|
|||||||
tm times;
|
tm times;
|
||||||
FB_DEC16* d64value;
|
FB_DEC16* d64value;
|
||||||
FB_DEC34* d128value;
|
FB_DEC34* d128value;
|
||||||
|
FB_I128* i128value;
|
||||||
// Initialize the time structure.
|
// Initialize the time structure.
|
||||||
memset(×, 0, sizeof(times));
|
memset(×, 0, sizeof(times));
|
||||||
char msec_str[5] = "";
|
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))
|
if ((!isqlGlob.df16) || (fbStatus->getState() & Firebird::IStatus::STATE_ERRORS))
|
||||||
{
|
{
|
||||||
STDERROUT("Input parsing problem");
|
STDERROUT("Input parsing problem");
|
||||||
|
ISQL_errmsg(fbStatus);
|
||||||
done = true;
|
done = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_DEC34:
|
case SQL_DEC34:
|
||||||
case SQL_DEC_FIXED:
|
|
||||||
d128value = (FB_DEC34*) datap;
|
d128value = (FB_DEC34*) datap;
|
||||||
if (isqlGlob.df34)
|
if (isqlGlob.df34)
|
||||||
isqlGlob.df34->fromString(fbStatus, get_numeric_value(lastPos).c_str(), d128value);
|
isqlGlob.df34->fromString(fbStatus, get_numeric_value(lastPos).c_str(), d128value);
|
||||||
if ((!isqlGlob.df34) || (fbStatus->getState() & Firebird::IStatus::STATE_ERRORS))
|
if ((!isqlGlob.df34) || (fbStatus->getState() & Firebird::IStatus::STATE_ERRORS))
|
||||||
{
|
{
|
||||||
STDERROUT("Input parsing problem");
|
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;
|
done = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -7312,7 +7352,6 @@ static unsigned print_item(TEXT** s, const IsqlVar* var, const unsigned length)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_DEC34:
|
case SQL_DEC34:
|
||||||
case SQL_DEC_FIXED:
|
|
||||||
{
|
{
|
||||||
char decStr[Firebird::IDecFloat34::STRING_SIZE];
|
char decStr[Firebird::IDecFloat34::STRING_SIZE];
|
||||||
if (isqlGlob.df34)
|
if (isqlGlob.df34)
|
||||||
@ -7325,9 +7364,34 @@ static unsigned print_item(TEXT** s, const IsqlVar* var, const unsigned length)
|
|||||||
strcpy(decStr, convErr);
|
strcpy(decStr, convErr);
|
||||||
|
|
||||||
if (setValues.List)
|
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
|
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;
|
break;
|
||||||
|
|
||||||
@ -8169,7 +8233,9 @@ static unsigned process_message_display(Firebird::IMessageMetadata* message, uns
|
|||||||
case SQL_DEC16:
|
case SQL_DEC16:
|
||||||
disp_length = Firebird::IDecFloat16::STRING_SIZE - 1;
|
disp_length = Firebird::IDecFloat16::STRING_SIZE - 1;
|
||||||
break;
|
break;
|
||||||
case SQL_DEC_FIXED:
|
case SQL_INT128:
|
||||||
|
disp_length = Firebird::IInt128::STRING_SIZE - 1;
|
||||||
|
break;
|
||||||
case SQL_DEC34:
|
case SQL_DEC34:
|
||||||
disp_length = Firebird::IDecFloat34::STRING_SIZE - 1;
|
disp_length = Firebird::IDecFloat34::STRING_SIZE - 1;
|
||||||
break;
|
break;
|
||||||
@ -8847,8 +8913,8 @@ static const char* sqltype_to_string(unsigned sqltype)
|
|||||||
return "DECFLOAT(16)";
|
return "DECFLOAT(16)";
|
||||||
case SQL_DEC34:
|
case SQL_DEC34:
|
||||||
return "DECFLOAT(34)";
|
return "DECFLOAT(34)";
|
||||||
case SQL_DEC_FIXED:
|
case SQL_INT128:
|
||||||
return "DECIMAL FIXED";
|
return "NUMERIC(38)";
|
||||||
case SQL_D_FLOAT:
|
case SQL_D_FLOAT:
|
||||||
return "D_FLOAT";
|
return "D_FLOAT";
|
||||||
case SQL_TIMESTAMP:
|
case SQL_TIMESTAMP:
|
||||||
|
@ -306,7 +306,6 @@ const int BIGINT = 16;
|
|||||||
const int BOOLEAN_TYPE = 23;
|
const int BOOLEAN_TYPE = 23;
|
||||||
const int DEC64_TYPE = 24;
|
const int DEC64_TYPE = 24;
|
||||||
const int DEC128_TYPE = 25;
|
const int DEC128_TYPE = 25;
|
||||||
const int DEC_FIXED_TYPE = 26;
|
|
||||||
|
|
||||||
static const sqltypes Column_types[] = {
|
static const sqltypes Column_types[] = {
|
||||||
{SMALLINT, "SMALLINT"}, // keyword
|
{SMALLINT, "SMALLINT"}, // keyword
|
||||||
@ -326,7 +325,7 @@ static const sqltypes Column_types[] = {
|
|||||||
{BOOLEAN_TYPE, "BOOLEAN"}, // keyword
|
{BOOLEAN_TYPE, "BOOLEAN"}, // keyword
|
||||||
{DEC64_TYPE, "DECFLOAT(16)"},
|
{DEC64_TYPE, "DECFLOAT(16)"},
|
||||||
{DEC128_TYPE, "DECFLOAT(34)"},
|
{DEC128_TYPE, "DECFLOAT(34)"},
|
||||||
{DEC_FIXED_TYPE, "<Should not be shown>"},
|
{blr_int128, "INT64"},
|
||||||
{blr_sql_time_tz, "TIME WITH TIME ZONE"}, // keyword
|
{blr_sql_time_tz, "TIME WITH TIME ZONE"}, // keyword
|
||||||
{blr_timestamp_tz, "TIMESTAMP WITH TIME ZONE"}, // keyword
|
{blr_timestamp_tz, "TIMESTAMP WITH TIME ZONE"}, // keyword
|
||||||
{0, ""}
|
{0, ""}
|
||||||
@ -417,6 +416,7 @@ public:
|
|||||||
USHORT att_charset;
|
USHORT att_charset;
|
||||||
Firebird::IDecFloat16* df16;
|
Firebird::IDecFloat16* df16;
|
||||||
Firebird::IDecFloat34* df34;
|
Firebird::IDecFloat34* df34;
|
||||||
|
Firebird::IInt128* i128;
|
||||||
void printf(const char* buffer, ...);
|
void printf(const char* buffer, ...);
|
||||||
void prints(const char* buffer);
|
void prints(const char* buffer);
|
||||||
|
|
||||||
@ -478,6 +478,7 @@ struct IsqlVar
|
|||||||
char* asChar;
|
char* asChar;
|
||||||
FB_DEC16* asDec16;
|
FB_DEC16* asDec16;
|
||||||
FB_DEC34* asDec34;
|
FB_DEC34* asDec34;
|
||||||
|
FB_I128* asInt128;
|
||||||
void* setPtr;
|
void* setPtr;
|
||||||
};
|
};
|
||||||
TypeMix value;
|
TypeMix value;
|
||||||
|
@ -243,7 +243,7 @@ Jrd::Attachment::Attachment(MemoryPool* pool, Database* dbb, const InitialOption
|
|||||||
att_internal(*pool),
|
att_internal(*pool),
|
||||||
att_dyn_req(*pool),
|
att_dyn_req(*pool),
|
||||||
att_dec_status(DecimalStatus::DEFAULT),
|
att_dec_status(DecimalStatus::DEFAULT),
|
||||||
att_dec_binding(DecimalBinding::DEFAULT),
|
att_dec_binding(NumericBinding::DEFAULT),
|
||||||
att_charsets(*pool),
|
att_charsets(*pool),
|
||||||
att_charset_ids(*pool),
|
att_charset_ids(*pool),
|
||||||
att_pools(*pool),
|
att_pools(*pool),
|
||||||
|
@ -363,8 +363,11 @@ public:
|
|||||||
void resetAttachment(Attachment* attachment) const;
|
void resetAttachment(Attachment* attachment) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void setBinding(Firebird::string option, Firebird::NumericBinding& bind);
|
||||||
|
|
||||||
Firebird::DecimalStatus decFloatStatus = Firebird::DecimalStatus::DEFAULT;
|
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;
|
Firebird::TimeZoneUtil::Bind timeZoneBind = Firebird::TimeZoneUtil::BIND_NATIVE;
|
||||||
USHORT originalTimeZone = Firebird::TimeZoneUtil::GMT_ZONE;
|
USHORT originalTimeZone = Firebird::TimeZoneUtil::GMT_ZONE;
|
||||||
@ -466,7 +469,8 @@ public:
|
|||||||
Firebird::Array<JrdStatement*> att_dyn_req; // internal dyn statements
|
Firebird::Array<JrdStatement*> att_dyn_req; // internal dyn statements
|
||||||
Firebird::ICryptKeyCallback* att_crypt_callback; // callback for DB crypt
|
Firebird::ICryptKeyCallback* att_crypt_callback; // callback for DB crypt
|
||||||
Firebird::DecimalStatus att_dec_status; // error handling and rounding
|
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);
|
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)
|
if (field)
|
||||||
{
|
{
|
||||||
dsc d(relFormat->fmt_desc[i]);
|
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);
|
fieldsMsg->addItem(field->fld_name, !field->fld_not_null, d);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -109,10 +109,10 @@ namespace
|
|||||||
item.length = sizeof(Decimal128);
|
item.length = sizeof(Decimal128);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case dtype_dec_fixed:
|
case dtype_int128:
|
||||||
item.type = SQL_DEC_FIXED;
|
item.type = SQL_INT128;
|
||||||
item.scale = desc->dsc_scale;
|
item.scale = desc->dsc_scale;
|
||||||
item.length = sizeof(DecimalFixed);
|
item.length = sizeof(Int128);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case dtype_sql_date:
|
case dtype_sql_date:
|
||||||
|
@ -44,7 +44,7 @@ MsgMetadata* Routine::createMetadata(const Array<NestConst<Parameter> >& paramet
|
|||||||
++i)
|
++i)
|
||||||
{
|
{
|
||||||
dsc d((*i)->prm_desc);
|
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;
|
d.dsc_dtype = dtype_dec128;
|
||||||
metadata->addItem((*i)->prm_name, (*i)->prm_nullable, d);
|
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/DecFloat.h"
|
||||||
|
#include "../common/Int128.h"
|
||||||
#include "firebird/impl/blr.h"
|
#include "firebird/impl/blr.h"
|
||||||
|
|
||||||
/* The following macro must be defined as the highest-numericly-valued
|
/* 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_boolean, // blr_bool == 23
|
||||||
dtype_dec64, /* blr_dec64 == 24 */
|
dtype_dec64, /* blr_dec64 == 24 */
|
||||||
dtype_dec128, /* blr_dec128 == 25 */
|
dtype_dec128, /* blr_dec128 == 25 */
|
||||||
dtype_dec_fixed, /* blr_dec_fixed == 26 */
|
dtype_int128, /* blr_int128 == 26 */
|
||||||
dtype_double, /* blr_double == 27 */
|
dtype_double, /* blr_double == 27 */
|
||||||
dtype_sql_time_tz, /* blr_sql_time_tz == 28 */
|
dtype_sql_time_tz, /* blr_sql_time_tz == 28 */
|
||||||
dtype_timestamp_tz, /* blr_timestamp_tz == 29 */
|
dtype_timestamp_tz, /* blr_timestamp_tz == 29 */
|
||||||
@ -111,7 +112,7 @@ static const USHORT type_alignments[DTYPE_TYPE_MAX] =
|
|||||||
sizeof(UCHAR), /* dtype_boolean */
|
sizeof(UCHAR), /* dtype_boolean */
|
||||||
sizeof(Firebird::Decimal64),/* dtype_dec64 */
|
sizeof(Firebird::Decimal64),/* dtype_dec64 */
|
||||||
sizeof(Firebird::Decimal64),/* dtype_dec128 */
|
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_TIME), /* dtype_sql_time_tz */
|
||||||
sizeof(GDS_DATE) /* dtype_timestamp_tz */
|
sizeof(GDS_DATE) /* dtype_timestamp_tz */
|
||||||
};
|
};
|
||||||
@ -142,7 +143,7 @@ static const USHORT type_lengths[DTYPE_TYPE_MAX] =
|
|||||||
sizeof(UCHAR), /* dtype_boolean */
|
sizeof(UCHAR), /* dtype_boolean */
|
||||||
sizeof(Firebird::Decimal64),/* dtype_dec64 */
|
sizeof(Firebird::Decimal64),/* dtype_dec64 */
|
||||||
sizeof(Firebird::Decimal128),/*dtype_dec128 */
|
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_TIME_TZ), /* dtype_sql_time_tz */
|
||||||
sizeof(ISC_TIMESTAMP_TZ) /* dtype_timestamp_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_boolean
|
||||||
0, // dtype_dec64
|
0, // dtype_dec64
|
||||||
0, // dtype_dec128
|
0, // dtype_dec128
|
||||||
0, // dtype_dec_fixed
|
0, // dtype_int128
|
||||||
0, // dtype_sql_time_tz
|
0, // dtype_sql_time_tz
|
||||||
0 // dtype_timestamp_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
|
// tricky: the value doesn't always become negative after an
|
||||||
// overflow!
|
// overflow!
|
||||||
|
|
||||||
if (value >= NUMERIC_LIMIT)
|
if (!over)
|
||||||
{
|
{
|
||||||
// possibility of an overflow
|
if (value >= NUMERIC_LIMIT)
|
||||||
if ((value > NUMERIC_LIMIT) || (*p > '8' && sign == -1) || (*p > '7' && sign != -1))
|
|
||||||
{
|
{
|
||||||
over = true;
|
// possibility of an overflow
|
||||||
break;
|
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)
|
if (fraction)
|
||||||
--local_scale;
|
--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))
|
if ((local_scale > MAX_SCHAR) || (local_scale < MIN_SCHAR))
|
||||||
over = true;
|
over = true;
|
||||||
|
|
||||||
|
*scale = local_scale;
|
||||||
|
|
||||||
if ((!over) && ((p < end) || // there is an exponent
|
if ((!over) && ((p < end) || // there is an exponent
|
||||||
((value < 0) && (sign != -1)))) // MAX_SINT64+1 wrapped around
|
((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;
|
return dtype_dec128;
|
||||||
}
|
}
|
||||||
|
|
||||||
*scale = local_scale;
|
|
||||||
|
|
||||||
// The literal has already been converted to a 64-bit integer: return
|
// 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.
|
// 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
|
9, // dtype_long
|
||||||
// Move quad up by one to make room for int64 at its proper place in the table.
|
// Move quad up by one to make room for int64 at its proper place in the table.
|
||||||
11, // dtype_quad
|
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
|
15, // dtype_real
|
||||||
16, // dtype_double
|
16, // dtype_double
|
||||||
17, // dtype_d_float
|
17, // dtype_d_float
|
||||||
@ -99,8 +99,8 @@ const BYTE CVT2_compare_priority[] =
|
|||||||
10, // dtype_int64 - goes right after long
|
10, // dtype_int64 - goes right after long
|
||||||
25, // dtype_dbkey - compares with nothing except itself
|
25, // dtype_dbkey - compares with nothing except itself
|
||||||
26, // dtype_boolean - compares with nothing except itself
|
26, // dtype_boolean - compares with nothing except itself
|
||||||
12, // dtype_dec_fixed - go after quad
|
12, // dtype_int128 - go after quad
|
||||||
13, // dec64 - go after dtype_dec_fixed
|
13, // dec64 - go after dtype_int128
|
||||||
14, // dec128 - go after dec64 and before real
|
14, // dec128 - go after dec64 and before real
|
||||||
20, // dtype_sql_time_tz - go after dtype_sql_time
|
20, // dtype_sql_time_tz - go after dtype_sql_time
|
||||||
22 // dtype_timestamp_tz - go after dtype_timestamp
|
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:
|
case dtype_dec128:
|
||||||
return ((Decimal128*) p1)->compare(decSt, *(Decimal128*) p2);
|
return ((Decimal128*) p1)->compare(decSt, *(Decimal128*) p2);
|
||||||
|
|
||||||
case dtype_dec_fixed:
|
case dtype_int128:
|
||||||
return ((DecimalFixed*) p1)->compare(decSt, *(DecimalFixed*) p2);
|
return ((Int128*) p1)->compare(*(Int128*) p2);
|
||||||
|
|
||||||
case dtype_boolean:
|
case dtype_boolean:
|
||||||
return *p1 == *p2 ? 0 : *p1 < *p2 ? -1 : 1;
|
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);
|
return temp1.compare(decSt, temp2);
|
||||||
}
|
}
|
||||||
|
|
||||||
case dtype_dec_fixed:
|
case dtype_int128:
|
||||||
{
|
{
|
||||||
SSHORT scale;
|
SSHORT scale;
|
||||||
if (arg2->dsc_dtype > dtype_varying)
|
if (arg2->dsc_dtype > dtype_varying)
|
||||||
@ -572,9 +572,9 @@ int CVT2_compare(const dsc* arg1, const dsc* arg2, Firebird::DecimalStatus decSt
|
|||||||
else
|
else
|
||||||
scale = arg1->dsc_scale;
|
scale = arg1->dsc_scale;
|
||||||
|
|
||||||
const DecimalFixed temp1 = CVT_get_dec_fixed(arg1, scale, decSt, ERR_post);
|
const Int128 temp1 = CVT_get_int128(arg1, scale, decSt, ERR_post);
|
||||||
const DecimalFixed temp2 = CVT_get_dec_fixed(arg2, scale, decSt, ERR_post);
|
const Int128 temp2 = CVT_get_int128(arg2, scale, decSt, ERR_post);
|
||||||
return temp1.compare(decSt, temp2);
|
return temp1.compare(temp2);
|
||||||
}
|
}
|
||||||
|
|
||||||
case dtype_blob:
|
case dtype_blob:
|
||||||
|
@ -1302,7 +1302,7 @@ USHORT DFW_assign_index_type(thread_db* tdbb, const Firebird::MetaName& name, SS
|
|||||||
return idx_boolean;
|
return idx_boolean;
|
||||||
case dtype_dec64:
|
case dtype_dec64:
|
||||||
case dtype_dec128:
|
case dtype_dec128:
|
||||||
case dtype_dec_fixed:
|
case dtype_int128:
|
||||||
return idx_decimal;
|
return idx_decimal;
|
||||||
default:
|
default:
|
||||||
return idx_numeric;
|
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);
|
value->vlu_misc.vlu_dec128 = *((Decimal128*) from.dsc_address);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case dtype_dec_fixed:
|
case dtype_int128:
|
||||||
value->vlu_misc.vlu_dec_fixed = *((DecimalFixed*) from.dsc_address);
|
value->vlu_misc.vlu_int128 = *((Int128*) from.dsc_address);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case dtype_sql_time:
|
case dtype_sql_time:
|
||||||
|
@ -64,7 +64,6 @@ DEFINE_TRACE_ROUTINE(cmp_trace);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
class VaryingString;
|
class VaryingString;
|
||||||
struct dsc;
|
|
||||||
|
|
||||||
namespace Jrd {
|
namespace Jrd {
|
||||||
|
|
||||||
@ -463,7 +462,7 @@ public:
|
|||||||
csb_currentForNode(NULL),
|
csb_currentForNode(NULL),
|
||||||
csb_currentDMLNode(NULL),
|
csb_currentDMLNode(NULL),
|
||||||
csb_currentAssignTarget(NULL),
|
csb_currentAssignTarget(NULL),
|
||||||
csb_preferredDataType(0),
|
csb_preferredDesc(NULL),
|
||||||
csb_rpt(p)
|
csb_rpt(p)
|
||||||
{
|
{
|
||||||
csb_dbg_info = FB_NEW_POOL(p) Firebird::DbgInfo(p);
|
csb_dbg_info = FB_NEW_POOL(p) Firebird::DbgInfo(p);
|
||||||
@ -546,7 +545,7 @@ public:
|
|||||||
ForNode* csb_currentForNode;
|
ForNode* csb_currentForNode;
|
||||||
StmtNode* csb_currentDMLNode; // could be StoreNode or ModifyNode
|
StmtNode* csb_currentDMLNode; // could be StoreNode or ModifyNode
|
||||||
ExprNode* csb_currentAssignTarget;
|
ExprNode* csb_currentAssignTarget;
|
||||||
UCHAR csb_preferredDataType; // expected by receiving side datatype
|
dsc* csb_preferredDesc; // expected by receiving side data format
|
||||||
|
|
||||||
struct csb_repeat
|
struct csb_repeat
|
||||||
{
|
{
|
||||||
|
@ -606,7 +606,7 @@ void FUN_evaluate(thread_db* tdbb, const Function* function, const NestValueArra
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case dtype_dec128:
|
case dtype_dec128:
|
||||||
case dtype_dec_fixed:
|
case dtype_int128:
|
||||||
{
|
{
|
||||||
const Decimal128 d = MOV_get_dec128(tdbb, input);
|
const Decimal128 d = MOV_get_dec128(tdbb, input);
|
||||||
if (parameter->prm_fun_mechanism == FUN_value)
|
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()));
|
Arg::Str(function->getName().toString()));
|
||||||
}
|
}
|
||||||
break;
|
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;
|
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);
|
value->vlu_misc.vlu_dec128 = CALL_UDF<Decimal128>(tdbb, function->fun_entrypoint, args);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case dtype_dec_fixed:
|
case dtype_int128:
|
||||||
value->vlu_misc.vlu_dec_fixed = CALL_UDF<DecimalFixed>(tdbb, function->fun_entrypoint, args);
|
value->vlu_misc.vlu_int128 = CALL_UDF<Int128>(tdbb, function->fun_entrypoint, args);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case dtype_timestamp:
|
case dtype_timestamp:
|
||||||
|
@ -1020,6 +1020,7 @@ namespace Jrd
|
|||||||
string dpb_decfloat_bind;
|
string dpb_decfloat_bind;
|
||||||
string dpb_decfloat_round;
|
string dpb_decfloat_round;
|
||||||
string dpb_decfloat_traps;
|
string dpb_decfloat_traps;
|
||||||
|
string dpb_int128_bind;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static const ULONG DPB_FLAGS_MASK = DBB_damaged;
|
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)
|
Attachment::InitialOptions::InitialOptions(const DatabaseOptions& options)
|
||||||
{
|
{
|
||||||
if (options.dpb_time_zone_bind.hasData())
|
if (options.dpb_time_zone_bind.hasData())
|
||||||
@ -1078,42 +1116,10 @@ namespace Jrd
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (options.dpb_decfloat_bind.hasData())
|
if (options.dpb_decfloat_bind.hasData())
|
||||||
{
|
setBinding(options.dpb_decfloat_bind, decFloatBinding);
|
||||||
auto option = options.dpb_decfloat_bind;
|
|
||||||
option.lower();
|
|
||||||
|
|
||||||
if (option == "native")
|
if (options.dpb_int128_bind.hasData())
|
||||||
decFloatBinding = DecimalBinding::DEFAULT;
|
setBinding(options.dpb_int128_bind, int128Binding);
|
||||||
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_decfloat_round.hasData())
|
if (options.dpb_decfloat_round.hasData())
|
||||||
{
|
{
|
||||||
@ -1172,6 +1178,7 @@ namespace Jrd
|
|||||||
// reset DecFloat options
|
// reset DecFloat options
|
||||||
attachment->att_dec_status = decFloatStatus;
|
attachment->att_dec_status = decFloatStatus;
|
||||||
attachment->att_dec_binding = decFloatBinding;
|
attachment->att_dec_binding = decFloatBinding;
|
||||||
|
attachment->att_i128_binding = int128Binding;
|
||||||
|
|
||||||
// reset time zone options
|
// reset time zone options
|
||||||
attachment->att_timezone_bind = timeZoneBind;
|
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);
|
rdr.getString(dpb_decfloat_bind);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case isc_dpb_int128_bind:
|
||||||
|
rdr.getString(dpb_int128_bind);
|
||||||
|
break;
|
||||||
|
|
||||||
case isc_dpb_decfloat_round:
|
case isc_dpb_decfloat_round:
|
||||||
rdr.getString(dpb_decfloat_round);
|
rdr.getString(dpb_decfloat_round);
|
||||||
break;
|
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)
|
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,
|
Firebird::string MOV_make_string2(Jrd::thread_db* tdbb, const dsc* desc, USHORT ttype,
|
||||||
bool limit = true);
|
bool limit = true);
|
||||||
void MOV_move(Jrd::thread_db*, /*const*/ dsc*, dsc*);
|
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::Decimal64 MOV_get_dec64(Jrd::thread_db*, const dsc*);
|
||||||
Firebird::Decimal128 MOV_get_dec128(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
|
namespace Jrd
|
||||||
{
|
{
|
||||||
|
@ -419,7 +419,7 @@ static const UCHAR sort_dtypes[] =
|
|||||||
SKD_bytes, // dtype_boolean
|
SKD_bytes, // dtype_boolean
|
||||||
SKD_dec64, // dtype_dec64
|
SKD_dec64, // dtype_dec64
|
||||||
SKD_dec128, // dtype_dec128
|
SKD_dec128, // dtype_dec128
|
||||||
SKD_dec128, // dtype_dec_fixed
|
SKD_int128, // dtype_int128
|
||||||
SKD_sql_time_tz, // dtype_sql_time_tz
|
SKD_sql_time_tz, // dtype_sql_time_tz
|
||||||
SKD_timestamp_tz // dtype_timestamp_tz
|
SKD_timestamp_tz // dtype_timestamp_tz
|
||||||
};
|
};
|
||||||
|
@ -405,9 +405,9 @@ USHORT PAR_datatype(BlrReader& blrReader, dsc* desc)
|
|||||||
desc->dsc_length = sizeof(Decimal128);
|
desc->dsc_length = sizeof(Decimal128);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case blr_dec_fixed:
|
case blr_int128:
|
||||||
desc->dsc_dtype = dtype_dec_fixed;
|
desc->dsc_dtype = dtype_int128;
|
||||||
desc->dsc_length = sizeof(DecimalFixed);
|
desc->dsc_length = sizeof(Int128);
|
||||||
desc->dsc_scale = (int) blrReader.getByte();
|
desc->dsc_scale = (int) blrReader.getByte();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -804,6 +804,7 @@ void Sort::diddleKey(UCHAR* record, bool direction, bool duplicateHandling)
|
|||||||
case SKD_timestamp:
|
case SKD_timestamp:
|
||||||
case SKD_sql_date:
|
case SKD_sql_date:
|
||||||
case SKD_int64:
|
case SKD_int64:
|
||||||
|
case SKD_int128:
|
||||||
*p ^= 1 << 7;
|
*p ^= 1 << 7;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1047,6 +1048,24 @@ void Sort::diddleKey(UCHAR* record, bool direction, bool duplicateHandling)
|
|||||||
SWAP_LONGS(lwp[0], lwp[1], lw);
|
SWAP_LONGS(lwp[0], lwp[1], lw);
|
||||||
break;
|
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
|
#ifdef IEEE
|
||||||
case SKD_double:
|
case SKD_double:
|
||||||
if (!direction)
|
if (!direction)
|
||||||
|
@ -145,6 +145,7 @@ const int SKD_dec64 = 16;
|
|||||||
const int SKD_dec128 = 17;
|
const int SKD_dec128 = 17;
|
||||||
const int SKD_sql_time_tz = 18;
|
const int SKD_sql_time_tz = 18;
|
||||||
const int SKD_timestamp_tz = 19;
|
const int SKD_timestamp_tz = 19;
|
||||||
|
const int SKD_int128 = 20;
|
||||||
|
|
||||||
// skd_flags
|
// skd_flags
|
||||||
const UCHAR SKD_ascending = 0; // default initializer
|
const UCHAR SKD_ascending = 0; // default initializer
|
||||||
|
@ -85,7 +85,7 @@ struct impure_value
|
|||||||
double vlu_double;
|
double vlu_double;
|
||||||
Firebird::Decimal64 vlu_dec64;
|
Firebird::Decimal64 vlu_dec64;
|
||||||
Firebird::Decimal128 vlu_dec128;
|
Firebird::Decimal128 vlu_dec128;
|
||||||
Firebird::DecimalFixed vlu_dec_fixed;
|
Firebird::Int128 vlu_int128;
|
||||||
GDS_TIMESTAMP vlu_timestamp;
|
GDS_TIMESTAMP vlu_timestamp;
|
||||||
ISC_TIMESTAMP_TZ vlu_timestamp_tz;
|
ISC_TIMESTAMP_TZ vlu_timestamp_tz;
|
||||||
GDS_TIME vlu_sql_time;
|
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_int64(const SINT64 val, const signed char scale = 0);
|
||||||
void make_double(const double val);
|
void make_double(const double val);
|
||||||
void make_decimal128(const Firebird::Decimal128 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.
|
// 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);
|
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_misc.vlu_int128 = val;
|
||||||
this->vlu_desc.dsc_dtype = dtype_dec_fixed;
|
this->vlu_desc.dsc_dtype = dtype_int128;
|
||||||
this->vlu_desc.dsc_length = sizeof(Firebird::DecimalFixed);
|
this->vlu_desc.dsc_length = sizeof(Firebird::Int128);
|
||||||
this->vlu_desc.dsc_scale = scale;
|
this->vlu_desc.dsc_scale = scale;
|
||||||
this->vlu_desc.dsc_sub_type = 0;
|
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
|
struct impure_value_ex : public impure_value
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
ISC_QUAD = array [1..2] of Integer;
|
ISC_QUAD = array [1..2] of Integer;
|
||||||
FB_DEC16 = array [1..1] of Int64;
|
FB_DEC16 = array [1..1] of Int64;
|
||||||
FB_DEC34 = array [1..2] 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_tr_handle = ^integer32;
|
||||||
isc_stmt_handle = ^integer32;
|
isc_stmt_handle = ^integer32;
|
||||||
|
@ -127,10 +127,10 @@ void BlrFromMessage::buildBlr(IMessageMetadata* metadata)
|
|||||||
dtype = dtype_dec128;
|
dtype = dtype_dec128;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_DEC_FIXED:
|
case SQL_INT128:
|
||||||
appendUChar(blr_dec_fixed);
|
appendUChar(blr_int128);
|
||||||
appendUChar(scale);
|
appendUChar(scale);
|
||||||
dtype = dtype_dec_fixed;
|
dtype = dtype_int128;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_DOUBLE:
|
case SQL_DOUBLE:
|
||||||
|
@ -300,11 +300,11 @@ static rem_fmt* parse_format(const UCHAR*& blr, size_t& blr_length)
|
|||||||
align = type_alignments[dtype_dec128];
|
align = type_alignments[dtype_dec128];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case blr_dec_fixed:
|
case blr_int128:
|
||||||
desc->dsc_dtype = dtype_dec_fixed;
|
desc->dsc_dtype = dtype_int128;
|
||||||
desc->dsc_length = sizeof(DecimalFixed);
|
desc->dsc_length = sizeof(Int128);
|
||||||
desc->dsc_scale = *blr++;
|
desc->dsc_scale = *blr++;
|
||||||
align = type_alignments[dtype_dec_fixed];
|
align = type_alignments[dtype_int128];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// this case cannot occur as switch paramater is char and blr_blob
|
// this case cannot occur as switch paramater is char and blr_blob
|
||||||
|
@ -762,7 +762,7 @@ void TracePluginImpl::appendParams(ITraceParams* params)
|
|||||||
case dtype_dec128:
|
case dtype_dec128:
|
||||||
paramtype = "decfloat(34)";
|
paramtype = "decfloat(34)";
|
||||||
break;
|
break;
|
||||||
case dtype_dec_fixed:
|
case dtype_int128:
|
||||||
paramtype = "decimal";
|
paramtype = "decimal";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -887,11 +887,10 @@ void TracePluginImpl::appendParams(ITraceParams* params)
|
|||||||
((Decimal128*) parameters->dsc_address)->toString(paramvalue);
|
((Decimal128*) parameters->dsc_address)->toString(paramvalue);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case dtype_dec_fixed:
|
case dtype_int128:
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
DecimalStatus decSt(FB_DEC_Errors);
|
((Int128*) parameters->dsc_address)->toString(parameters->dsc_scale, paramvalue);
|
||||||
((DecimalFixed*) parameters->dsc_address)->toString(decSt, parameters->dsc_scale, paramvalue);
|
|
||||||
}
|
}
|
||||||
catch (const Exception& ex)
|
catch (const Exception& ex)
|
||||||
{
|
{
|
||||||
|
@ -686,6 +686,7 @@ public:
|
|||||||
void encodeTimeStampTz(Firebird::CheckStatusWrapper* status, ISC_TIMESTAMP_TZ* timeStampTz,
|
void encodeTimeStampTz(Firebird::CheckStatusWrapper* status, ISC_TIMESTAMP_TZ* timeStampTz,
|
||||||
unsigned year, unsigned month, unsigned day,
|
unsigned year, unsigned month, unsigned day,
|
||||||
unsigned hours, unsigned minutes, unsigned seconds, unsigned fractions, const char* timeZone);
|
unsigned hours, unsigned minutes, unsigned seconds, unsigned fractions, const char* timeZone);
|
||||||
|
Firebird::IInt128* getInt128(Firebird::CheckStatusWrapper* status);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Why
|
} // namespace Why
|
||||||
|
@ -60,6 +60,7 @@
|
|||||||
#include "../common/classes/TempFile.h"
|
#include "../common/classes/TempFile.h"
|
||||||
#include "../common/utils_proto.h"
|
#include "../common/utils_proto.h"
|
||||||
#include "../common/ThreadStart.h"
|
#include "../common/ThreadStart.h"
|
||||||
|
#include "../common/Int128.h"
|
||||||
|
|
||||||
#ifdef HAVE_UNISTD_H
|
#ifdef HAVE_UNISTD_H
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@ -3034,9 +3035,9 @@ static int blr_print_dtype(gds_ctl* control)
|
|||||||
length = sizeof(Firebird::Decimal64);
|
length = sizeof(Firebird::Decimal64);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case blr_dec_fixed:
|
case blr_int128:
|
||||||
string = "dec_fixed";
|
string = "int128";
|
||||||
length = sizeof(Firebird::DecimalFixed);
|
length = sizeof(Firebird::Int128);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case blr_domain_name:
|
case blr_domain_name:
|
||||||
@ -3100,7 +3101,7 @@ static int blr_print_dtype(gds_ctl* control)
|
|||||||
case blr_long:
|
case blr_long:
|
||||||
case blr_quad:
|
case blr_quad:
|
||||||
case blr_int64:
|
case blr_int64:
|
||||||
case blr_dec_fixed:
|
case blr_int128:
|
||||||
blr_print_byte(control);
|
blr_print_byte(control);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1303,6 +1303,49 @@ IDecFloat34* UtilInterface::getDecFloat34(CheckStatusWrapper* status)
|
|||||||
return &decFloat34;
|
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,
|
unsigned UtilInterface::setOffsets(CheckStatusWrapper* status, IMessageMetadata* metadata,
|
||||||
IOffsetsCallback* callback)
|
IOffsetsCallback* callback)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user