8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-22 17:23:03 +01:00

Merge branch 'master' into read_consistency

This commit is contained in:
hvlad 2017-07-10 23:54:42 +03:00
parent c34a914553
commit bdc7bd8d3e
205 changed files with 27977 additions and 2856 deletions

1
.gitignore vendored
View File

@ -17,3 +17,4 @@ libtool
*.tmp
src/dsql/parse.cpp
.vscode/.browse.VC.db
extern/decNumber/libdecFloat.a

View File

@ -1,10 +1,103 @@
# v4.0 Alpha 1 (unreleased)
## New features
* [CORE-5568](http://tracker.firebirdsql.org/browse/CORE-5568): SQL SECURITY feature
Reference(s): [/doc/sql.extentions/README.sql_security](https://github.com/FirebirdSQL/firebird/raw/master/doc/sql.extensions/README.sql_security.txt)
Contributor(s): Roman Simakov
* [CORE-5525](http://tracker.firebirdsql.org/browse/CORE-5525): Create high-precision floating point datatype named DECFLOAT
Reference(s): [/doc/sql.extentions/README.data_types](https://github.com/FirebirdSQL/firebird/raw/master/doc/sql.extensions/README.data_types)
Contributor(s): Alex Peshkoff
* [CORE-5488](http://tracker.firebirdsql.org/browse/CORE-5488): Timeouts for running SQL statements and idle connections
Reference(s): [/doc/README.session_idle_timeouts](https://github.com/FirebirdSQL/firebird/raw/master/doc/README.session_idle_timeouts), [/doc/README.statement_timeouts](https://github.com/FirebirdSQL/firebird/raw/master/doc/README.statement_timeouts)
Contributor(s): Vlad Khorsun
* [CORE-5463](http://tracker.firebirdsql.org/browse/CORE-5463): Support DEFAULT context value in INSERT, UPDATE, MERGE and UPDATE OR INSERT statements
Contributor(s): Adriano dos Santos Fernandes
* [CORE-5449](http://tracker.firebirdsql.org/browse/CORE-5449): Support GENERATED ALWAYS identity columns and OVERRIDE clause
Reference(s): [doc/sql.extensions/README.identity_columns](https://github.com/FirebirdSQL/firebird/raw/master/doc/sql.extensions/README.identity_columns.txt)
Contributor(s): Adriano dos Santos Fernandes
* [CORE-5346](http://tracker.firebirdsql.org/browse/CORE-5346): Named windows
Reference(s): [doc/sql.extensions/README.window_functions](https://github.com/FirebirdSQL/firebird/raw/master/doc/sql.extensions/README.window_functions.md)
Contributor(s): Adriano dos Santos Fernandes
* [CORE-5343](http://tracker.firebirdsql.org/browse/CORE-5343): Allow particular DBA privileges to be transferred to regular users
Reference(s): [doc/sql.extensions/README.builtin_functions](https://github.com/FirebirdSQL/firebird/raw/master/doc/sql.extensions/README.builtin_functions.txt), [doc/sql.extensions/README.ddl](https://github.com/FirebirdSQL/firebird/raw/master/doc/sql.extensions/README.ddl.txt)
Contributor(s): Alex Peshkoff
* [CORE-3647](http://tracker.firebirdsql.org/browse/CORE-3647): Frames for window functions
Reference(s): [doc/sql.extensions/README.window_functions](https://github.com/FirebirdSQL/firebird/raw/master/doc/sql.extensions/README.window_functions.md)
Contributor(s): Adriano dos Santos Fernandes
* [CORE-2762](http://tracker.firebirdsql.org/browse/CORE-2762): New built-in function to check whether some role is implicitly active
Reference(s): [doc/sql.extensions/README.cumulative_roles](https://github.com/FirebirdSQL/firebird/raw/master/doc/sql.extensions/README.cumulative_roles.txt)
Contributor(s): Roman Simakov
* [CORE-1815](http://tracker.firebirdsql.org/browse/CORE-1815): Ability to grant role to another role
Reference(s): [doc/sql.extensions/README.cumulative_roles](https://github.com/FirebirdSQL/firebird/raw/master/doc/sql.extensions/README.cumulative_roles.txt)
Contributor(s): Roman Simakov
* [CORE-1688](http://tracker.firebirdsql.org/browse/CORE-1688): More ANSI SQL:2003 window functions (PERCENK_RANK, CUME_DIST, NTILE)
Reference(s): [doc/sql.extensions/README.window_functions](https://github.com/FirebirdSQL/firebird/raw/master/doc/sql.extensions/README.window_functions.md)
Contributor(s): Hajime Nakagami, Adriano dos Santos Fernandes
* [CORE-751](http://tracker.firebirdsql.org/browse/CORE-751): Implicitly active roles (and their permissions summarized)
Contributor(s): Roman Simakov
## Improvements
* [CORE-5431](http://tracker.firebirdsql.org/browse/CORE-5431): Support for DROP IDENTITY clause
Reference(s): [doc/sql.extensions/README.identity_columns](https://github.com/FirebirdSQL/firebird/raw/master/doc/sql.extensions/README.identity_columns.txt)
Contributor(s): Adriano dos Santos Fernandes
* [CORE-5430](http://tracker.firebirdsql.org/browse/CORE-5430): Support for INCREMENT option in identity columns
Reference(s): [doc/sql.extensions/README.identity_columns](https://github.com/FirebirdSQL/firebird/raw/master/doc/sql.extensions/README.identity_columns.txt)
Contributor(s): Adriano dos Santos Fernandes
* [CORE-5119](http://tracker.firebirdsql.org/browse/CORE-5119): Support autocommit mode in SET TRANSACTION statement
Contributor(s): Dmitry Yemanov
* [CORE-5064](http://tracker.firebirdsql.org/browse/CORE-5064): Add datatypes (VAR)BINARY(n) and BINARY VARYING(n) as aliases for (VAR)CHAR(n) CHARACTER SET OCTETS
Contributor(s): Dimitry Sibiryakov
* [CORE-2557](http://tracker.firebirdsql.org/browse/CORE-2557): Grants on MON$ tables
Contributor(s): Alex Peshkoff
* [CORE-2216](http://tracker.firebirdsql.org/browse/CORE-2216): NBackup as online dump
Contributor(s): Roman Simakov, Vlad Khorsun
* [CORE-2192](http://tracker.firebirdsql.org/browse/CORE-2192): Extend maximum database page size to 32KB
Contributor(s): Dmitry Yemanov
* [CORE-2040](http://tracker.firebirdsql.org/browse/CORE-2040): Allow exception name and possibly exception text to be determined within a "WHEN ANY" error handling block
Reference(s): [doc/sql.extensions/README.context_variables](https://github.com/FirebirdSQL/firebird/raw/master/doc/sql.extensions/README.context_variables)
Contributor(s): Dmitry Yemanov
* [CORE-1132](http://tracker.firebirdsql.org/browse/CORE-1132): Exception context in PSQL exception handlers
Reference(s): [doc/sql.extensions/README.context_variables](https://github.com/FirebirdSQL/firebird/raw/master/doc/sql.extensions/README.context_variables)
Contributor(s): Dmitry Yemanov
* [CORE-749](http://tracker.firebirdsql.org/browse/CORE-749): Increase maximum length of object names to 63 characters
Contributor(s): Adriano dos Santos Fernandes
## Bugfixes
* [CORE-5545](http://tracker.firebirdsql.org/browse/CORE-5545): Wrong syntax with CREATE TRIGGER ... ON <table> used with POSITION
Contributor(s): Adriano dos Santos Fernandes
* [CORE-5454](http://tracker.firebirdsql.org/browse/CORE-5454): INSERT into updatable view without explicit field list failed
Contributor(s): Adriano dos Santos Fernandes
* [CORE-5408](http://tracker.firebirdsql.org/browse/CORE-5408): Result of boolean expression can not be concatenated with string literal
Contributor(s): Adriano dos Santos Fernandes
* [CORE-5404](http://tracker.firebirdsql.org/browse/CORE-5404): Inconsistent column/line references when PSQL definitions return errors
Contributor(s): Adriano dos Santos Fernandes
* [CORE-5237](http://tracker.firebirdsql.org/browse/CORE-5237): Invalid handling of dot (.) and asterisk (*) in config file name and path for include clause
Contributor(s): Dimitry Sibiryakov
@ -26,58 +119,3 @@
* [CORE-4424](http://tracker.firebirdsql.org/browse/CORE-4424): Rollback to wrong savepoint if several exception handlers on the same level are executed
Contributor(s): Dimitry Sibiryakov
## Improvements
* [CORE-5431](http://tracker.firebirdsql.org/browse/CORE-5431): Support for DROP IDENTITY clause
Contributor(s): Adriano dos Santos Fernandes
* [CORE-5430](http://tracker.firebirdsql.org/browse/CORE-5430): Support for INCREMENT option in identity columns
Contributor(s): Adriano dos Santos Fernandes
* [CORE-5119](http://tracker.firebirdsql.org/browse/CORE-5119): Support autocommit mode in SET TRANSACTION statement
Contributor(s): Dmitry Yemanov
* [CORE-2557](http://tracker.firebirdsql.org/browse/CORE-2557): Grants on MON$ tables
Contributor(s): Alex Peshkoff
* [CORE-2216](http://tracker.firebirdsql.org/browse/CORE-2216): NBackup as online dump
Contributor(s): Roman Simakov, Vlad Khorsun
* [CORE-2192](http://tracker.firebirdsql.org/browse/CORE-2192): Extend maximum database page size to 32KB
Contributor(s): Dmitry Yemanov
* [CORE-2040](http://tracker.firebirdsql.org/browse/CORE-2040): Allow exception name and possibly exception text to be determined within a "WHEN ANY" error handling block
Contributor(s): Dmitry Yemanov
* [CORE-1132](http://tracker.firebirdsql.org/browse/CORE-1132): Exception context in PSQL exception handlers
Contributor(s): Dmitry Yemanov
* [CORE-749](http://tracker.firebirdsql.org/browse/CORE-749): Increase maximum length of object names to 63 characters
Contributor(s): Adriano dos Santos Fernandes
## New features
* [CORE-5346](http://tracker.firebirdsql.org/browse/CORE-5346): Named windows
Contributor(s): Adriano dos Santos Fernandes
* [CORE-5343](http://tracker.firebirdsql.org/browse/CORE-5343): Allow particular DBA privileges to be transferred to regular users
Contributor(s): Alex Peshkoff
* [CORE-3647](http://tracker.firebirdsql.org/browse/CORE-3647): Frames for window functions
Contributor(s): Adriano dos Santos Fernandes
* [CORE-2990](http://tracker.firebirdsql.org/browse/CORE-2990): Physical (page-level) standby replication / page shipping
Contributor(s): Roman Simakov, Vlad Khorsun
* [CORE-2762](http://tracker.firebirdsql.org/browse/CORE-2762): New built-in function to check whether some role is implicitly active
Contributor(s): Roman Simakov
* [CORE-1815](http://tracker.firebirdsql.org/browse/CORE-1815): Ability to grant role to another role
Contributor(s): Roman Simakov
* [CORE-1688](http://tracker.firebirdsql.org/browse/CORE-1688): More ANSI SQL:2003 window functions (PERCENK_RANK, CUME_DIST, NTILE)
Contributor(s): Hajime Nakagami, Adriano dos Santos Fernandes
* [CORE-751](http://tracker.firebirdsql.org/browse/CORE-751): Implicitly active roles (and their permissions summarized)
Contributor(s): Roman Simakov

View File

@ -206,7 +206,7 @@ copyFiles() {
cp $BuiltFBDir/examples/empbuild/*.fdb ${TargetDir}@FB_SAMPLEDBDIR@
ReadOnlyTree ${TargetDir}@FB_SAMPLEDIR@
chmod 0444 ${TargetDir}@FB_SAMPLEDBDIR@/*.fdb
chmod 0664 ${TargetDir}@FB_SAMPLEDBDIR@/*.fdb
fi
#QLI help

View File

@ -1,7 +1,7 @@
#!/bin/sh
# install - install a program, script, or datafile
scriptversion=2011-11-20.07; # UTC
scriptversion=2013-12-25.23; # UTC
# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
@ -41,19 +41,15 @@ scriptversion=2011-11-20.07; # UTC
# This script is compatible with the BSD install script, but was written
# from scratch.
tab=' '
nl='
'
IFS=" "" $nl"
IFS=" $tab$nl"
# set DOITPROG to echo to test this script
# Set DOITPROG to "echo" to test this script.
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit=${DOITPROG-}
if test -z "$doit"; then
doit_exec=exec
else
doit_exec=$doit
fi
doit_exec=${doit:-exec}
# Put in absolute file names if you don't have them in your path;
# or use environment vars.
@ -68,17 +64,6 @@ mvprog=${MVPROG-mv}
rmprog=${RMPROG-rm}
stripprog=${STRIPPROG-strip}
posix_glob='?'
initialize_posix_glob='
test "$posix_glob" != "?" || {
if (set -f) 2>/dev/null; then
posix_glob=
else
posix_glob=:
fi
}
'
posix_mkdir=
# Desired mode of installed file.
@ -97,7 +82,7 @@ dir_arg=
dst_arg=
copy_on_change=false
no_target_directory=
is_target_a_directory=possibly
usage="\
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
@ -137,46 +122,57 @@ while test $# -ne 0; do
-d) dir_arg=true;;
-g) chgrpcmd="$chgrpprog $2"
shift;;
shift;;
--help) echo "$usage"; exit $?;;
-m) mode=$2
case $mode in
*' '* | *' '* | *'
'* | *'*'* | *'?'* | *'['*)
echo "$0: invalid mode: $mode" >&2
exit 1;;
esac
shift;;
case $mode in
*' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
echo "$0: invalid mode: $mode" >&2
exit 1;;
esac
shift;;
-o) chowncmd="$chownprog $2"
shift;;
shift;;
-s) stripcmd=$stripprog;;
-t) dst_arg=$2
# Protect names problematic for 'test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
shift;;
-t)
is_target_a_directory=always
dst_arg=$2
# Protect names problematic for 'test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
shift;;
-T) no_target_directory=true;;
-T) is_target_a_directory=never;;
--version) echo "$0 $scriptversion"; exit $?;;
--) shift
break;;
--) shift
break;;
-*) echo "$0: invalid option: $1" >&2
exit 1;;
-*) echo "$0: invalid option: $1" >&2
exit 1;;
*) break;;
esac
shift
done
# We allow the use of options -d and -T together, by making -d
# take the precedence; this is for compatibility with GNU install.
if test -n "$dir_arg"; then
if test -n "$dst_arg"; then
echo "$0: target directory not allowed when installing a directory." >&2
exit 1
fi
fi
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
# When -d is used, all remaining arguments are directories to create.
# When -t is used, the destination is already specified.
@ -207,6 +203,15 @@ if test $# -eq 0; then
exit 0
fi
if test -z "$dir_arg"; then
if test $# -gt 1 || test "$is_target_a_directory" = always; then
if test ! -d "$dst_arg"; then
echo "$0: $dst_arg: Is not a directory." >&2
exit 1
fi
fi
fi
if test -z "$dir_arg"; then
do_exit='(exit $ret); exit $ret'
trap "ret=129; $do_exit" 1
@ -223,16 +228,16 @@ if test -z "$dir_arg"; then
*[0-7])
if test -z "$stripcmd"; then
u_plus_rw=
u_plus_rw=
else
u_plus_rw='% 200'
u_plus_rw='% 200'
fi
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
*)
if test -z "$stripcmd"; then
u_plus_rw=
u_plus_rw=
else
u_plus_rw=,u+rw
u_plus_rw=,u+rw
fi
cp_umask=$mode$u_plus_rw;;
esac
@ -269,41 +274,15 @@ do
# If destination is a directory, append the input filename; won't work
# if double slashes aren't ignored.
if test -d "$dst"; then
if test -n "$no_target_directory"; then
echo "$0: $dst_arg: Is a directory" >&2
exit 1
if test "$is_target_a_directory" = never; then
echo "$0: $dst_arg: Is a directory" >&2
exit 1
fi
dstdir=$dst
dst=$dstdir/`basename "$src"`
dstdir_status=0
else
# Prefer dirname, but fall back on a substitute if dirname fails.
dstdir=`
(dirname "$dst") 2>/dev/null ||
expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$dst" : 'X\(//\)[^/]' \| \
X"$dst" : 'X\(//\)$' \| \
X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
echo X"$dst" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
}
/^X\(\/\/\)[^/].*/{
s//\1/
q
}
/^X\(\/\/\)$/{
s//\1/
q
}
/^X\(\/\).*/{
s//\1/
q
}
s/.*/./; q'
`
dstdir=`dirname "$dst"`
test -d "$dstdir"
dstdir_status=$?
fi
@ -314,74 +293,74 @@ do
if test $dstdir_status != 0; then
case $posix_mkdir in
'')
# Create intermediate dirs using mode 755 as modified by the umask.
# This is like FreeBSD 'install' as of 1997-10-28.
umask=`umask`
case $stripcmd.$umask in
# Optimize common cases.
*[2367][2367]) mkdir_umask=$umask;;
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
# Create intermediate dirs using mode 755 as modified by the umask.
# This is like FreeBSD 'install' as of 1997-10-28.
umask=`umask`
case $stripcmd.$umask in
# Optimize common cases.
*[2367][2367]) mkdir_umask=$umask;;
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
*[0-7])
mkdir_umask=`expr $umask + 22 \
- $umask % 100 % 40 + $umask % 20 \
- $umask % 10 % 4 + $umask % 2
`;;
*) mkdir_umask=$umask,go-w;;
esac
*[0-7])
mkdir_umask=`expr $umask + 22 \
- $umask % 100 % 40 + $umask % 20 \
- $umask % 10 % 4 + $umask % 2
`;;
*) mkdir_umask=$umask,go-w;;
esac
# With -d, create the new directory with the user-specified mode.
# Otherwise, rely on $mkdir_umask.
if test -n "$dir_arg"; then
mkdir_mode=-m$mode
else
mkdir_mode=
fi
# With -d, create the new directory with the user-specified mode.
# Otherwise, rely on $mkdir_umask.
if test -n "$dir_arg"; then
mkdir_mode=-m$mode
else
mkdir_mode=
fi
posix_mkdir=false
case $umask in
*[123567][0-7][0-7])
# POSIX mkdir -p sets u+wx bits regardless of umask, which
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
;;
*)
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
posix_mkdir=false
case $umask in
*[123567][0-7][0-7])
# POSIX mkdir -p sets u+wx bits regardless of umask, which
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
;;
*)
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
if (umask $mkdir_umask &&
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
then
if test -z "$dir_arg" || {
# Check for POSIX incompatibilities with -m.
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
# other-writable bit of parent directory when it shouldn't.
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
ls_ld_tmpdir=`ls -ld "$tmpdir"`
case $ls_ld_tmpdir in
d????-?r-*) different_mode=700;;
d????-?--*) different_mode=755;;
*) false;;
esac &&
$mkdirprog -m$different_mode -p -- "$tmpdir" && {
ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
}
}
then posix_mkdir=:
fi
rmdir "$tmpdir/d" "$tmpdir"
else
# Remove any dirs left behind by ancient mkdir implementations.
rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
fi
trap '' 0;;
esac;;
if (umask $mkdir_umask &&
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
then
if test -z "$dir_arg" || {
# Check for POSIX incompatibilities with -m.
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
# other-writable bit of parent directory when it shouldn't.
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
ls_ld_tmpdir=`ls -ld "$tmpdir"`
case $ls_ld_tmpdir in
d????-?r-*) different_mode=700;;
d????-?--*) different_mode=755;;
*) false;;
esac &&
$mkdirprog -m$different_mode -p -- "$tmpdir" && {
ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
}
}
then posix_mkdir=:
fi
rmdir "$tmpdir/d" "$tmpdir"
else
# Remove any dirs left behind by ancient mkdir implementations.
rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
fi
trap '' 0;;
esac;;
esac
if
$posix_mkdir && (
umask $mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
umask $mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
)
then :
else
@ -391,53 +370,51 @@ do
# directory the slow way, step by step, checking for races as we go.
case $dstdir in
/*) prefix='/';;
[-=\(\)!]*) prefix='./';;
*) prefix='';;
/*) prefix='/';;
[-=\(\)!]*) prefix='./';;
*) prefix='';;
esac
eval "$initialize_posix_glob"
oIFS=$IFS
IFS=/
$posix_glob set -f
set -f
set fnord $dstdir
shift
$posix_glob set +f
set +f
IFS=$oIFS
prefixes=
for d
do
test X"$d" = X && continue
test X"$d" = X && continue
prefix=$prefix$d
if test -d "$prefix"; then
prefixes=
else
if $posix_mkdir; then
(umask=$mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
# Don't fail if two instances are running concurrently.
test -d "$prefix" || exit 1
else
case $prefix in
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
*) qprefix=$prefix;;
esac
prefixes="$prefixes '$qprefix'"
fi
fi
prefix=$prefix/
prefix=$prefix$d
if test -d "$prefix"; then
prefixes=
else
if $posix_mkdir; then
(umask=$mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
# Don't fail if two instances are running concurrently.
test -d "$prefix" || exit 1
else
case $prefix in
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
*) qprefix=$prefix;;
esac
prefixes="$prefixes '$qprefix'"
fi
fi
prefix=$prefix/
done
if test -n "$prefixes"; then
# Don't fail if two instances are running concurrently.
(umask $mkdir_umask &&
eval "\$doit_exec \$mkdirprog $prefixes") ||
test -d "$dstdir" || exit 1
obsolete_mkdir_used=true
# Don't fail if two instances are running concurrently.
(umask $mkdir_umask &&
eval "\$doit_exec \$mkdirprog $prefixes") ||
test -d "$dstdir" || exit 1
obsolete_mkdir_used=true
fi
fi
fi
@ -472,15 +449,12 @@ do
# If -C, don't bother to copy if it wouldn't change the file.
if $copy_on_change &&
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
eval "$initialize_posix_glob" &&
$posix_glob set -f &&
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
set -f &&
set X $old && old=:$2:$4:$5:$6 &&
set X $new && new=:$2:$4:$5:$6 &&
$posix_glob set +f &&
set +f &&
test "$old" = "$new" &&
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
then
@ -493,24 +467,24 @@ do
# to itself, or perhaps because mv is so ancient that it does not
# support -f.
{
# Now remove or move aside any old file at destination location.
# We try this two ways since rm can't unlink itself on some
# systems and the destination file might be busy for other
# reasons. In this case, the final cleanup might fail but the new
# file should still install successfully.
{
test ! -f "$dst" ||
$doit $rmcmd -f "$dst" 2>/dev/null ||
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
{ $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
} ||
{ echo "$0: cannot unlink or rename $dst" >&2
(exit 1); exit 1
}
} &&
# Now remove or move aside any old file at destination location.
# We try this two ways since rm can't unlink itself on some
# systems and the destination file might be busy for other
# reasons. In this case, the final cleanup might fail but the new
# file should still install successfully.
{
test ! -f "$dst" ||
$doit $rmcmd -f "$dst" 2>/dev/null ||
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
{ $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
} ||
{ echo "$0: cannot unlink or rename $dst" >&2
(exit 1); exit 1
}
} &&
# Now rename the file to the real destination.
$doit $mvcmd "$dsttmp" "$dst"
# Now rename the file to the real destination.
$doit $mvcmd "$dsttmp" "$dst"
}
fi || exit 1

View File

@ -66,7 +66,7 @@ else
GCC=gcc
endif
.PHONY: master_process cross_process firebird Debug Release extern
.PHONY: master_process cross_process firebird Debug Release external
all: firebird
@ -130,10 +130,13 @@ $(GEN_ROOT)/Make.Version : $(SRC_ROOT)/misc/writeBuildNum.sh
# build external software
#
extern:
external:
$(MAKE) -C $(ROOT)/extern/btyacc
$(MAKE) -C $(ROOT)/extern/cloop TARGET=release WITH_FPC=0 BUILD_DIR=$(TMP_ROOT)/cloop OUT_DIR=$(GEN_ROOT)/$(TARGET)/cloop
$(MAKE) -C $(ROOT)/extern/decNumber
ln -sf $(ROOT)/extern/decNumber/libdecFloat.a $(LIB)
ifeq ($(TOMBUILD_FLG),Y)
CFLAGS="$(CFLAGS)" $(MAKE) -C $(ROOT)/extern/libtommath -f makefile.shared GCC=$(GCC)
ln -sf $(TOMMATH_SO).$(TOMMATH_VER) $(LIB)
@ -180,7 +183,7 @@ master_process:
ln -sf $(SRC_ROOT)/include/gen/autoconfig.auto $(SRC_ROOT)/include/gen/autoconfig.h
$(MAKE) updateBuildNum
$(MAKE) export_lists
$(MAKE) extern
$(MAKE) external
$(MAKE) updateCloopInterfaces
$(MAKE) boot
$(MAKE) yvalve
@ -215,7 +218,7 @@ cross1:
ln -sf $(SRC_ROOT)/include/gen/autoconfig.auto $(SRC_ROOT)/include/gen/autoconfig.h
$(MAKE) updateBuildNum
$(MAKE) export_lists
$(MAKE) extern
$(MAKE) external
$(MAKE) updateCloopInterfaces
$(MAKE) boot
$(MAKE) yvalve
@ -657,11 +660,12 @@ install install-embedded silent_install package packages dist:
#
.PHONY: clean clean_objects clean_dependancies clean_extern_objects clean_build \
clean_gpre_gen clean_icu clean_dbs clean_examples clean_makefiles \
clean_editline clean_all
clean_editline clean_all clean_decfloat
clean: clean_objects clean_dependancies clean_extern_objects clean_build \
clean_yacc_gen clean_gpre_gen clean_dbs clean_examples clean_tommath
clean_yacc_gen clean_gpre_gen clean_dbs clean_examples clean_tommath \
clean_decfloat
ifeq ($(EDITLINE_FLG),Y)
ifeq ($(STD_EDITLINE),false)
@ -701,6 +705,9 @@ clean_editline:
clean_tommath:
-$(MAKE) -C $(ROOT)/extern/libtommath clean
clean_decfloat:
-$(MAKE) -C $(ROOT)/extern/decNumber clean
clean_objects:
$(RM) `find $(TMP_ROOT)/ -type f -name '*.o' -print`
$(RM) `find $(TMP_ROOT)/ -type f -name '*.a' -print`

View File

@ -56,7 +56,6 @@ LDFLAGS += --sysroot=$(CROSS_PLATFORM) -L$(NDK)/sources/cxx-stl/gnu-libstdc++/$(
DroidLibs := -lm -ldl -lsupc++
LINK_LIBS = $(DroidLibs)
STATICLINK_LIBS = $(DroidLibs)
SO_LINK_LIBS = $(DroidLibs)
EXE_LINK_OPTIONS= $(LDFLAGS) $(UNDEF_FLAGS) $(LIB_PATH_OPTS) $(LINK_EMPTY_SYMBOLS)

View File

@ -132,6 +132,7 @@ CAS_OPTIONS=@CAS_OPTIONS@
# multiple-precision integer library
MATHLIB=@MATHLIB@
DECLIB=-ldecFloat
LSB_FLG=@LSB_FLG@
ifeq ($(LSB_FLG), Y)
@ -177,9 +178,8 @@ STATICLIB_LINK = $(AR) crus
EXE_LINK = $(CXX) $(GLOB_OPTIONS) $(CXXFLAGS)
STATICEXE_LINK = $(CXX) $(GLOB_OPTIONS) $(CXXFLAGS)
LINK_LIBS = @LIBS@
STATICLINK_LIBS = @LIBS@
SO_LINK_LIBS = @LIBS@
LINK_LIBS = @LIBS@ $(DECLIB)
SO_LINK_LIBS = @LIBS@ $(DECLIB)
# Default extensions

View File

@ -30,7 +30,6 @@ DEV_FLAGS=$(COMM_SOLX_FLAGS) -ggdb -g3 -p $(WARNINGS)
ifdef SFIO
LINK_LIBS+=$(SFIO_LDFLAGS) -lstdio -lsfio
STATICLINK_LIBS+=$(SFIO_LDFLAGS) -lstdio -lsfio
SO_LINK_LIBS+=$(SFIO_LDFLAGS) -lstdio -lsfio
endif

View File

@ -1,8 +1,8 @@
# Helper functions
doObjects= $(patsubst %.y,%.o,$(patsubst %.epp,%.o,$(patsubst %.c,%.o,$(1:.cpp=.o))))
makeObjects= $(addprefix $(OBJ)/$(1)/,$(call doObjects,$2))
dirFiles= $(notdir $(wildcard ../src/$(1)/*.cpp)) $(notdir $(wildcard ../src/$(1)/*.c)) \
$(notdir $(wildcard ../src/$(1)/*.epp)) $(notdir $(wildcard ../src/$(1)/*.y))
dirFiles= $(sort $(notdir $(wildcard ../src/$(1)/*.cpp)) $(notdir $(wildcard ../src/$(1)/*.c)) \
$(notdir $(wildcard ../src/$(1)/*.epp)) $(notdir $(wildcard ../src/$(1)/*.y)))
dirInPath= $(call makeObjects,$(1),$(call dirFiles,$(1)))
dirMaster= $(call dirInPath,$(1))

View File

@ -36,7 +36,6 @@ PROD_FLAGS=-w $(COMM_SOLX_FLAGS) -O2 -march=pentium
DEV_FLAGS=$(COMM_SOLX_FLAGS) -ggdb -g3 -p $(WARNINGS)
ifdef SFIO
LINK_LIBS+=$(SFIO_LDFLAGS) -lstdio -lsfio
STATICLINK_LIBS+=$(SFIO_LDFLAGS) -lstdio -lsfio
SO_LINK_LIBS+=$(SFIO_LDFLAGS) -lstdio -lsfio
endif

View File

@ -27,7 +27,7 @@
# ./configure --build=x86_64-pc-solaris2.10
# copy libncurses.a from the ncurses build to gen/firebird/lib
# make sure that make.defaults uses -lncurses instead of -lcurses for
# LINK_LIBS and STATICLINK_LIBS e.g. -lncurses -leditline
# LINK_LIBS and SO_LINK_LIBS e.g. -lncurses -leditline
WARNINGS=-Wall -Wno-switch -Wno-parentheses -Wno-unused-variable -Wno-non-virtual-dtor
COMM_SOLX_FLAGS:=-DSOLARIS -DBSD_COMP -DAMD64 -pipe -fmessage-length=0 -MMD -fPIC
@ -46,7 +46,6 @@ PROD_FLAGS=-w $(COMM_SOLX_FLAGS) -O2
DEV_FLAGS=$(COMM_SOLX_FLAGS) -ggdb $(WARNINGS)
ifdef SFIO
LINK_LIBS+=$(SFIO_LDFLAGS) -lstdio -lsfio
STATICLINK_LIBS+=$(SFIO_LDFLAGS) -lstdio -lsfio
SO_LINK_LIBS+=$(SFIO_LDFLAGS) -lstdio -lsfio
endif

View File

@ -38,6 +38,9 @@ if "%ERRLEV%"=="1" goto :END
call :LibTomMath
if "%ERRLEV%"=="1" goto :END
call :decNumber
if "%ERRLEV%"=="1" goto :END
call :zlib
if "%ERRLEV%"=="1" goto :END
@ -133,6 +136,21 @@ if errorlevel 1 call :boot2 libtommath_%FB_OBJ_DIR%
@call set_build_target.bat %*
goto :EOF
::===================
:: BUILD decNumber
:decNumber
@echo.
@call set_build_target.bat %* RELEASE
@echo Building decNumber (%FB_OBJ_DIR%)...
@call compile.bat %FB_ROOT_PATH%\extern\decNumber\msvc\decNumber_MSVC%MSVC_VERSION% decNumber_%FB_OBJ_DIR%_%FB_TARGET_PLATFORM%.log decNumber
if errorlevel 1 call :boot2 decNumber_%FB_OBJ_DIR%
@call set_build_target.bat %* DEBUG
@echo Building decNumber (%FB_OBJ_DIR%)...
@call compile.bat %FB_ROOT_PATH%\extern\decNumber\msvc\decNumber_MSVC%MSVC_VERSION% decNumber_%FB_OBJ_DIR%_%FB_TARGET_PLATFORM%.log decNumber
if errorlevel 1 call :boot2 decNumber_%FB_OBJ_DIR%
@call set_build_target.bat %*
goto :EOF
::===================
:: Extract zlib
:zlib

View File

@ -58,6 +58,7 @@
</ClCompile>
<ClCompile Include="..\..\..\src\common\cvt.cpp" />
<ClCompile Include="..\..\..\src\common\db_alias.cpp" />
<ClCompile Include="..\..\..\src\common\DecFloat.cpp" />
<ClCompile Include="..\..\..\src\common\dllinst.cpp" />
<ClCompile Include="..\..\..\src\common\dsc.cpp" />
<ClCompile Include="..\..\..\src\common\DynamicStrings.cpp" />
@ -154,6 +155,7 @@
<ClInclude Include="..\..\..\src\common\CsConvert.h" />
<ClInclude Include="..\..\..\src\common\cvt.h" />
<ClInclude Include="..\..\..\src\common\db_alias.h" />
<ClInclude Include="..\..\..\src\common\DecFloat.h" />
<ClInclude Include="..\..\..\src\common\dllinst.h" />
<ClInclude Include="..\..\..\src\common\dsc.h" />
<ClInclude Include="..\..\..\src\common\dsc_proto.h" />
@ -283,7 +285,7 @@
<Culture>0x041d</Culture>
</ResourceCompile>
<Lib>
<AdditionalDependencies>ws2_32.lib;../../../extern/libtommath/lib/$(PlatformName)\Release\tommath.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>ws2_32.lib;../../../extern/libtommath/lib/$(PlatformName)\$(Configuration)\tommath.lib;../../../extern/decNumber/lib/$(PlatformName)\$(Configuration)\decnumber.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
@ -299,7 +301,7 @@
<Culture>0x041d</Culture>
</ResourceCompile>
<Lib>
<AdditionalDependencies>ws2_32.lib;../../../extern/libtommath/lib/$(PlatformName)\Debug\tommath.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>ws2_32.lib;../../../extern/libtommath/lib/$(PlatformName)\$(Configuration)\tommath.lib;../../../extern/decNumber/lib/$(PlatformName)\$(Configuration)\decnumber.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@ -318,7 +320,7 @@
<Culture>0x041d</Culture>
</ResourceCompile>
<Lib>
<AdditionalDependencies>ws2_32.lib;../../../extern/libtommath/lib/$(PlatformName)\Release\tommath.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>ws2_32.lib;../../../extern/libtommath/lib/$(PlatformName)\$(Configuration)\tommath.lib;../../../extern/decNumber/lib/$(PlatformName)\$(Configuration)\decnumber.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@ -336,7 +338,7 @@
<Culture>0x041d</Culture>
</ResourceCompile>
<Lib>
<AdditionalDependencies>ws2_32.lib;../../../extern/libtommath/lib/$(PlatformName)\Debug\tommath.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>ws2_32.lib;../../../extern/libtommath/lib/$(PlatformName)\$(Configuration)\tommath.lib;../../../extern/decNumber/lib/$(PlatformName)\$(Configuration)\decnumber.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Lib>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View File

@ -216,6 +216,9 @@
<ClCompile Include="..\..\..\src\common\CRC32C.cpp">
<Filter>common</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\common\DecFloat.cpp">
<Filter>classes</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\src\common\xdr_proto.h">
@ -530,5 +533,8 @@
<ClInclude Include="..\..\..\src\common\Tokens.h">
<Filter>headers</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\common\DecFloat.h">
<Filter>headers</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -870,6 +870,16 @@ dnl if 64-bit mode, then archive tool, ar, needs -X64 option
[AC_LANG_PROGRAM(,[[int lp64 = __64BIT__; ]])],
[AR_OPTIONS=-X64],)
fi
XE_SAVE_ENV()
CXXFLAGS="$CXXFLAGS -std=c++11"
AC_CACHE_CHECK([whether the C++ compiler understands noexcept], [ac_cv_cxx_noexcept], [
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[int f(int x) noexcept { return x + 1; }]], [[]])],
[ac_cv_cxx_noexcept=yes], [ac_cv_cxx_noexcept=no])])
XE_RESTORE_ENV()
if test "$ac_cv_cxx_noexcept" = yes; then
AC_DEFINE([HAS_NOEXCEPT], [1], [Define if the C++ compiler understands noexcept.])
fi
AC_LANG_POP(C++)
dnl Check for functions

View File

@ -101,3 +101,87 @@ BINARY, VARBINARY, BINARY VARYING (FB 4.0)
2. Can be distinguished from text types by value 1 in RDB$FIELD_SUB_TYPE.
3. Character set is set to OCTETS for backward compatibility.
4. In API are similar to corresponding text types, getSubType() returns 0.
DECFLOAT (FB 4.0)
--------------
Function:
DB2-compliant numeric type. DECFLOAT precisely (unlike FLOAT or DOUBLE PRECISION that provide
binary approximation) stores decimal values being therefore ideal choice for business appli-
cations. Firebird according to IEEE standard has both 16- and 34-digit decimal float encodings.
All intermediate calculations are performed with 34-digit values.
Author:
Alex Peshkoff <peshkoff@mail.ru>
Syntax rules:
DECFLOAT(16)
DECFLOAT(34)
Storage:
64-bit / 128-bit, format according to IEEE 754.
Example(s):
1. DECLARE VARIABLE VAR1 DECFLOAT(34);
2. CREATE TABLE TABLE1 (FIELD1 DECFLOAT(16));
Note(s):
1. A number of standard functions can be used with DECFLOAT datatype. It is:
ABS, CEILING, EXP, FLOOR, LN, LOG, LOG10, POWER, SIGN, SQRT.
Agregate functions SUM, AVG, MAX and MIN also work with DECFLOAT data.
All statistics aggregates (like but not limited to STDDEV or CORR) work with DECFLOAT data.
2. Firebird supports four functions, specially designed to support DECFLOAT data:
- COMPARE_DECFLOAT - compares two DECFLOAT values to be equal, different or unordered.
Returns SMALLINT value which can be as follows:
0 - values are equal
1 - first value is less than second
2 - first value is greater than second
3 - values unordered (i.e. one or both is NAN / SNAN)
Unlike comparison operators ('<', '=', '>', etc.) comparison is exact - i.e.
COMPARE_DECFLOAT(2.17, 2.170) returns 2, not 0.
- NORMALIZE_DECFLOAT - has single DECFLOAT argument returned in it's simplest form. That
means that for any nonzero value trailing zero are removed with appropriate correction
of an exponent. For example NORMALIZE_DECFLOAT(12.00) returns 12 and
NORMALIZE_DECFLOAT(120) returns 1.2E+2.
- QUANTIZE - has two DECFLOAT arguments. The returned value is first argument scaled using
second value as a pattern. For example QUANTIZE(1234, 9.999) returns 1234.000.
- TOTALORDER - compares two DECFLOAT values including any special value. The comparison is
exact. Returns SMALLINT value which can be as follows:
-1 - first value is less than second
0 - values are equal
1 - first value is greater than second
DECFLOAT values are ordered as follows:
-nan < -snan < -inf < -0.1 < -0.10 < -0 < 0 < 0.10 < 0.1 < inf < snan < nan
3. Firebird supports new session control operator SET DECFLOAT. It has following forms:
SET DECFLOAT ROUND <mode> - controls rounding mode used in operations with DECFLOAT
values. Valid modes are: CEILING (towards +infinity), UP (away from 0), HALF_UP
(to nearest, if equidistant - up), HALF_EVEN (to nearest, if equidistant - ensure
last digit in the result to be even), HALF_DOWN (to nearest, if equidistant - down),
DOWN (towards 0), FLOOR (towards -infinity), REROUND (up if digit to be rounded is
0 or 5, down in other cases).
SET DECFLOAT TRAPS TO <comma-separated traps list - may be empty> - controls which
exceptional conditions cause a trap. Valid traps are: Division_by_zero, Inexact,
Invalid_operation, Overflow and Underflow. By default traps are set to:
Division_by_zero, Invalid_operation, Overflow, Underflow.
SET DECFLOAT BIND <bind-type> - controls how are DECFLOAT values represented in outer
world (i.e. in messages or in XSQLDA). Valid binding types are: NATIVE (use IEEE754
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 DECFLOAT values 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 is a tool like
generic purporse GUI client choice of CHAR binding is OK in most cases.
4. The length of DECFLOAT literals are limited to 1024 characters. For longer values, you will
need to use the scientific notation. For example, the 0.0<1020 zeroes>11 cannot be used
as a literal, instead you can use the equivalent in scientific notation: 1.1E-1022.
Similarly 10<1022 zeroes>0 can be presented as 1.0E1024.

View File

@ -4,6 +4,9 @@
* DESCRIPTION: A sample of using static messages.
* Prints user-defined tables with comments.
*
* Example for the following interface:
* IDecFloat16 - support for IEEE-754 64-bit decimal float numbers
*
* Example for the following macro:
*
* FB_MESSAGE - defines static messages
@ -32,6 +35,7 @@
#include <firebird/Message.h>
static IMaster* master = fb_get_master_interface();
static IDecFloat16* idf = NULL;
int main()
{
@ -51,6 +55,8 @@ int main()
try
{
idf = master->getUtilInterface()->getDecFloat16(&status);
att = prov->attachDatabase(&status, dbName, 0, NULL);
tra = att->startTransaction(&status, 0, NULL);
@ -72,13 +78,15 @@ int main()
(FB_SMALLINT, relationId)
(FB_VARCHAR(31), relationName)
(FB_VARCHAR(100), description)
(FB_DECFLOAT16, df16)
) output(&status, master);
input.clear();
input->systemFlag = 0;
rs = att->openCursor(&status, tra, 0,
"select rdb$relation_id, rdb$relation_name, rdb$description"
"select rdb$relation_id, rdb$relation_name, rdb$description,"
" cast (rdb$relation_id as decfloat(16)) * 0.05 as df16"
" from rdb$relations"
" where rdb$system_flag = ?"
" order by rdb$relation_id",
@ -89,10 +97,13 @@ int main()
{
unsigned lRelName = output->relationNameNull ? 0 : output->relationName.length;
unsigned lDesc = output->descriptionNull ? 0 : output->description.length;
printf("%4d %*.*s%c%*.*s\n", output->relationId,
char t[IDecFloat16::STRING_SIZE];
idf->toStr(&output->df16, t);
printf("%4d %*.*s%c%*.*s (%s)\n", output->relationId,
lRelName, lRelName, output->relationName.str,
lDesc ? '/' : ' ',
lDesc, lDesc, output->description.str);
lDesc, lDesc, output->description.str, t);
}
rs->close(&status);

View File

@ -20,7 +20,7 @@
*/
#include "CalcCApi.h"
#include <malloc.h>
#include <stdlib.h>
#include <stdio.h>
#ifdef WIN32

2
extern/decNumber/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
temp/
lib/

45
extern/decNumber/ICU-license.html vendored Normal file
View File

@ -0,0 +1,45 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii"></meta>
<title>ICU License - ICU 1.8.1 and later</title>
</head>
<body>
<h1>ICU License - ICU 1.8.1 and later</h1>
<pre>
COPYRIGHT AND PERMISSION NOTICE
Copyright (c) 1995-2005 International Business Machines Corporation and others
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, and/or sell copies of the Software, and to permit persons
to whom the Software is furnished to do so, provided that the above
copyright notice(s) and this permission notice appear in all copies of
the Software and that both the above copyright notice(s) and this
permission notice appear in supporting documentation.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Except as contained in this notice, the name of a copyright holder
shall not be used in advertising or otherwise to promote the sale, use
or other dealings in this Software without prior written authorization
of the copyright holder.
--------------------------------------------------------------------------------
All trademarks and registered trademarks mentioned herein are the property of their respective owners.
</pre>
</body>
</html>

11
extern/decNumber/Makefile vendored Normal file
View File

@ -0,0 +1,11 @@
LIBRARY=libdecFloat.a
$(LIBRARY): $(wildcard *.c) $(wildcard *.h) Makefile
$(RM) -f *.o
$(CC) -c -O3 -fPIC $(subst decCommon.c,,$(subst decBasic.c,,$(wildcard *.c)))
$(AR) crs $(LIBRARY) *.o
$(RM) -f *.o
.PHONY: clean
clean:
$(RM) -f *.o $(LIBRARY)

3908
extern/decNumber/decBasic.c vendored Normal file

File diff suppressed because it is too large Load Diff

1835
extern/decNumber/decCommon.c vendored Normal file

File diff suppressed because it is too large Load Diff

437
extern/decNumber/decContext.c vendored Normal file
View File

@ -0,0 +1,437 @@
/* ------------------------------------------------------------------ */
/* Decimal Context module */
/* ------------------------------------------------------------------ */
/* Copyright (c) IBM Corporation, 2000, 2009. All rights reserved. */
/* */
/* This software is made available under the terms of the */
/* ICU License -- ICU 1.8.1 and later. */
/* */
/* The description and User's Guide ("The decNumber C Library") for */
/* this software is called decNumber.pdf. This document is */
/* available, together with arithmetic and format specifications, */
/* testcases, and Web links, on the General Decimal Arithmetic page. */
/* */
/* Please send comments, suggestions, and corrections to the author: */
/* mfc@uk.ibm.com */
/* Mike Cowlishaw, IBM Fellow */
/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */
/* ------------------------------------------------------------------ */
/* This module comprises the routines for handling arithmetic */
/* context structures. */
/* ------------------------------------------------------------------ */
#include <string.h> // for strcmp
#include <stdio.h> // for printf if DECCHECK
#include "decContext.h" // context and base types
#include "decNumberLocal.h" // decNumber local types, etc.
/* compile-time endian tester [assumes sizeof(Int)>1] */
static const Int mfcone=1; // constant 1
static const Flag *mfctop=(const Flag *)&mfcone; // -> top byte
#define LITEND *mfctop // named flag; 1=little-endian
/* ------------------------------------------------------------------ */
/* round-for-reround digits */
/* ------------------------------------------------------------------ */
const uByte DECSTICKYTAB[10]={1,1,2,3,4,6,6,7,8,9}; /* used if sticky */
/* ------------------------------------------------------------------ */
/* Powers of ten (powers[n]==10**n, 0<=n<=9) */
/* ------------------------------------------------------------------ */
const uInt DECPOWERS[10]={1, 10, 100, 1000, 10000, 100000, 1000000,
10000000, 100000000, 1000000000};
/* ------------------------------------------------------------------ */
/* decContextClearStatus -- clear bits in current status */
/* */
/* context is the context structure to be queried */
/* mask indicates the bits to be cleared (the status bit that */
/* corresponds to each 1 bit in the mask is cleared) */
/* returns context */
/* */
/* No error is possible. */
/* ------------------------------------------------------------------ */
decContext *decContextClearStatus(decContext *context, uInt mask) {
context->status&=~mask;
return context;
} // decContextClearStatus
/* ------------------------------------------------------------------ */
/* decContextDefault -- initialize a context structure */
/* */
/* context is the structure to be initialized */
/* kind selects the required set of default values, one of: */
/* DEC_INIT_BASE -- select ANSI X3-274 defaults */
/* DEC_INIT_DECIMAL32 -- select IEEE 754 defaults, 32-bit */
/* DEC_INIT_DECIMAL64 -- select IEEE 754 defaults, 64-bit */
/* DEC_INIT_DECIMAL128 -- select IEEE 754 defaults, 128-bit */
/* For any other value a valid context is returned, but with */
/* Invalid_operation set in the status field. */
/* returns a context structure with the appropriate initial values. */
/* ------------------------------------------------------------------ */
decContext * decContextDefault(decContext *context, Int kind) {
// set defaults...
context->digits=9; // 9 digits
context->emax=DEC_MAX_EMAX; // 9-digit exponents
context->emin=DEC_MIN_EMIN; // .. balanced
context->round=DEC_ROUND_HALF_UP; // 0.5 rises
context->traps=DEC_Errors; // all but informational
context->status=0; // cleared
context->clamp=0; // no clamping
#if DECSUBSET
context->extended=0; // cleared
#endif
switch (kind) {
case DEC_INIT_BASE:
// [use defaults]
break;
case DEC_INIT_DECIMAL32:
context->digits=7; // digits
context->emax=96; // Emax
context->emin=-95; // Emin
context->round=DEC_ROUND_HALF_EVEN; // 0.5 to nearest even
context->traps=0; // no traps set
context->clamp=1; // clamp exponents
#if DECSUBSET
context->extended=1; // set
#endif
break;
case DEC_INIT_DECIMAL64:
context->digits=16; // digits
context->emax=384; // Emax
context->emin=-383; // Emin
context->round=DEC_ROUND_HALF_EVEN; // 0.5 to nearest even
context->traps=0; // no traps set
context->clamp=1; // clamp exponents
#if DECSUBSET
context->extended=1; // set
#endif
break;
case DEC_INIT_DECIMAL128:
context->digits=34; // digits
context->emax=6144; // Emax
context->emin=-6143; // Emin
context->round=DEC_ROUND_HALF_EVEN; // 0.5 to nearest even
context->traps=0; // no traps set
context->clamp=1; // clamp exponents
#if DECSUBSET
context->extended=1; // set
#endif
break;
default: // invalid Kind
// use defaults, and ..
decContextSetStatus(context, DEC_Invalid_operation); // trap
}
return context;} // decContextDefault
/* ------------------------------------------------------------------ */
/* decContextGetRounding -- return current rounding mode */
/* */
/* context is the context structure to be queried */
/* returns the rounding mode */
/* */
/* No error is possible. */
/* ------------------------------------------------------------------ */
enum rounding decContextGetRounding(decContext *context) {
return context->round;
} // decContextGetRounding
/* ------------------------------------------------------------------ */
/* decContextGetStatus -- return current status */
/* */
/* context is the context structure to be queried */
/* returns status */
/* */
/* No error is possible. */
/* ------------------------------------------------------------------ */
uInt decContextGetStatus(decContext *context) {
return context->status;
} // decContextGetStatus
/* ------------------------------------------------------------------ */
/* decContextRestoreStatus -- restore bits in current status */
/* */
/* context is the context structure to be updated */
/* newstatus is the source for the bits to be restored */
/* mask indicates the bits to be restored (the status bit that */
/* corresponds to each 1 bit in the mask is set to the value of */
/* the correspnding bit in newstatus) */
/* returns context */
/* */
/* No error is possible. */
/* ------------------------------------------------------------------ */
decContext *decContextRestoreStatus(decContext *context,
uInt newstatus, uInt mask) {
context->status&=~mask; // clear the selected bits
context->status|=(mask&newstatus); // or in the new bits
return context;
} // decContextRestoreStatus
/* ------------------------------------------------------------------ */
/* decContextSaveStatus -- save bits in current status */
/* */
/* context is the context structure to be queried */
/* mask indicates the bits to be saved (the status bits that */
/* correspond to each 1 bit in the mask are saved) */
/* returns the AND of the mask and the current status */
/* */
/* No error is possible. */
/* ------------------------------------------------------------------ */
uInt decContextSaveStatus(decContext *context, uInt mask) {
return context->status&mask;
} // decContextSaveStatus
/* ------------------------------------------------------------------ */
/* decContextSetRounding -- set current rounding mode */
/* */
/* context is the context structure to be updated */
/* newround is the value which will replace the current mode */
/* returns context */
/* */
/* No error is possible. */
/* ------------------------------------------------------------------ */
decContext *decContextSetRounding(decContext *context,
enum rounding newround) {
context->round=newround;
return context;
} // decContextSetRounding
/* ------------------------------------------------------------------ */
/* decContextSetStatus -- set status and raise trap if appropriate */
/* */
/* context is the context structure to be updated */
/* status is the DEC_ exception code */
/* returns the context structure */
/* */
/* Control may never return from this routine, if there is a signal */
/* handler and it takes a long jump. */
/* ------------------------------------------------------------------ */
decContext * decContextSetStatus(decContext *context, uInt status) {
context->status|=status;
if (status & context->traps) raise(SIGFPE);
return context;} // decContextSetStatus
/* ------------------------------------------------------------------ */
/* decContextSetStatusFromString -- set status from a string + trap */
/* */
/* context is the context structure to be updated */
/* string is a string exactly equal to one that might be returned */
/* by decContextStatusToString */
/* */
/* The status bit corresponding to the string is set, and a trap */
/* is raised if appropriate. */
/* */
/* returns the context structure, unless the string is equal to */
/* DEC_Condition_MU or is not recognized. In these cases NULL is */
/* returned. */
/* ------------------------------------------------------------------ */
decContext * decContextSetStatusFromString(decContext *context,
const char *string) {
if (strcmp(string, DEC_Condition_CS)==0)
return decContextSetStatus(context, DEC_Conversion_syntax);
if (strcmp(string, DEC_Condition_DZ)==0)
return decContextSetStatus(context, DEC_Division_by_zero);
if (strcmp(string, DEC_Condition_DI)==0)
return decContextSetStatus(context, DEC_Division_impossible);
if (strcmp(string, DEC_Condition_DU)==0)
return decContextSetStatus(context, DEC_Division_undefined);
if (strcmp(string, DEC_Condition_IE)==0)
return decContextSetStatus(context, DEC_Inexact);
if (strcmp(string, DEC_Condition_IS)==0)
return decContextSetStatus(context, DEC_Insufficient_storage);
if (strcmp(string, DEC_Condition_IC)==0)
return decContextSetStatus(context, DEC_Invalid_context);
if (strcmp(string, DEC_Condition_IO)==0)
return decContextSetStatus(context, DEC_Invalid_operation);
#if DECSUBSET
if (strcmp(string, DEC_Condition_LD)==0)
return decContextSetStatus(context, DEC_Lost_digits);
#endif
if (strcmp(string, DEC_Condition_OV)==0)
return decContextSetStatus(context, DEC_Overflow);
if (strcmp(string, DEC_Condition_PA)==0)
return decContextSetStatus(context, DEC_Clamped);
if (strcmp(string, DEC_Condition_RO)==0)
return decContextSetStatus(context, DEC_Rounded);
if (strcmp(string, DEC_Condition_SU)==0)
return decContextSetStatus(context, DEC_Subnormal);
if (strcmp(string, DEC_Condition_UN)==0)
return decContextSetStatus(context, DEC_Underflow);
if (strcmp(string, DEC_Condition_ZE)==0)
return context;
return NULL; // Multiple status, or unknown
} // decContextSetStatusFromString
/* ------------------------------------------------------------------ */
/* decContextSetStatusFromStringQuiet -- set status from a string */
/* */
/* context is the context structure to be updated */
/* string is a string exactly equal to one that might be returned */
/* by decContextStatusToString */
/* */
/* The status bit corresponding to the string is set; no trap is */
/* raised. */
/* */
/* returns the context structure, unless the string is equal to */
/* DEC_Condition_MU or is not recognized. In these cases NULL is */
/* returned. */
/* ------------------------------------------------------------------ */
decContext * decContextSetStatusFromStringQuiet(decContext *context,
const char *string) {
if (strcmp(string, DEC_Condition_CS)==0)
return decContextSetStatusQuiet(context, DEC_Conversion_syntax);
if (strcmp(string, DEC_Condition_DZ)==0)
return decContextSetStatusQuiet(context, DEC_Division_by_zero);
if (strcmp(string, DEC_Condition_DI)==0)
return decContextSetStatusQuiet(context, DEC_Division_impossible);
if (strcmp(string, DEC_Condition_DU)==0)
return decContextSetStatusQuiet(context, DEC_Division_undefined);
if (strcmp(string, DEC_Condition_IE)==0)
return decContextSetStatusQuiet(context, DEC_Inexact);
if (strcmp(string, DEC_Condition_IS)==0)
return decContextSetStatusQuiet(context, DEC_Insufficient_storage);
if (strcmp(string, DEC_Condition_IC)==0)
return decContextSetStatusQuiet(context, DEC_Invalid_context);
if (strcmp(string, DEC_Condition_IO)==0)
return decContextSetStatusQuiet(context, DEC_Invalid_operation);
#if DECSUBSET
if (strcmp(string, DEC_Condition_LD)==0)
return decContextSetStatusQuiet(context, DEC_Lost_digits);
#endif
if (strcmp(string, DEC_Condition_OV)==0)
return decContextSetStatusQuiet(context, DEC_Overflow);
if (strcmp(string, DEC_Condition_PA)==0)
return decContextSetStatusQuiet(context, DEC_Clamped);
if (strcmp(string, DEC_Condition_RO)==0)
return decContextSetStatusQuiet(context, DEC_Rounded);
if (strcmp(string, DEC_Condition_SU)==0)
return decContextSetStatusQuiet(context, DEC_Subnormal);
if (strcmp(string, DEC_Condition_UN)==0)
return decContextSetStatusQuiet(context, DEC_Underflow);
if (strcmp(string, DEC_Condition_ZE)==0)
return context;
return NULL; // Multiple status, or unknown
} // decContextSetStatusFromStringQuiet
/* ------------------------------------------------------------------ */
/* decContextSetStatusQuiet -- set status without trap */
/* */
/* context is the context structure to be updated */
/* status is the DEC_ exception code */
/* returns the context structure */
/* */
/* No error is possible. */
/* ------------------------------------------------------------------ */
decContext * decContextSetStatusQuiet(decContext *context, uInt status) {
context->status|=status;
return context;} // decContextSetStatusQuiet
/* ------------------------------------------------------------------ */
/* decContextStatusToString -- convert status flags to a string */
/* */
/* context is a context with valid status field */
/* */
/* returns a constant string describing the condition. If multiple */
/* (or no) flags are set, a generic constant message is returned. */
/* ------------------------------------------------------------------ */
const char *decContextStatusToString(const decContext *context) {
Int status=context->status;
// test the five IEEE first, as some of the others are ambiguous when
// DECEXTFLAG=0
if (status==DEC_Invalid_operation ) return DEC_Condition_IO;
if (status==DEC_Division_by_zero ) return DEC_Condition_DZ;
if (status==DEC_Overflow ) return DEC_Condition_OV;
if (status==DEC_Underflow ) return DEC_Condition_UN;
if (status==DEC_Inexact ) return DEC_Condition_IE;
if (status==DEC_Division_impossible ) return DEC_Condition_DI;
if (status==DEC_Division_undefined ) return DEC_Condition_DU;
if (status==DEC_Rounded ) return DEC_Condition_RO;
if (status==DEC_Clamped ) return DEC_Condition_PA;
if (status==DEC_Subnormal ) return DEC_Condition_SU;
if (status==DEC_Conversion_syntax ) return DEC_Condition_CS;
if (status==DEC_Insufficient_storage ) return DEC_Condition_IS;
if (status==DEC_Invalid_context ) return DEC_Condition_IC;
#if DECSUBSET
if (status==DEC_Lost_digits ) return DEC_Condition_LD;
#endif
if (status==0 ) return DEC_Condition_ZE;
return DEC_Condition_MU; // Multiple errors
} // decContextStatusToString
/* ------------------------------------------------------------------ */
/* decContextTestEndian -- test whether DECLITEND is set correctly */
/* */
/* quiet is 1 to suppress message; 0 otherwise */
/* returns 0 if DECLITEND is correct */
/* 1 if DECLITEND is incorrect and should be 1 */
/* -1 if DECLITEND is incorrect and should be 0 */
/* */
/* A message is displayed if the return value is not 0 and quiet==0. */
/* */
/* No error is possible. */
/* ------------------------------------------------------------------ */
Int decContextTestEndian(Flag quiet) {
Int res=0; // optimist
uInt dle=(uInt)DECLITEND; // unsign
if (dle>1) dle=1; // ensure 0 or 1
if (LITEND!=DECLITEND) {
if (!quiet) { // always refer to this
#if DECPRINT
const char *adj;
if (LITEND) adj="little";
else adj="big";
printf("Warning: DECLITEND is set to %d, but this computer appears to be %s-endian\n",
DECLITEND, adj);
#endif
}
res=(Int)LITEND-dle;
}
return res;
} // decContextTestEndian
/* ------------------------------------------------------------------ */
/* decContextTestSavedStatus -- test bits in saved status */
/* */
/* oldstatus is the status word to be tested */
/* mask indicates the bits to be tested (the oldstatus bits that */
/* correspond to each 1 bit in the mask are tested) */
/* returns 1 if any of the tested bits are 1, or 0 otherwise */
/* */
/* No error is possible. */
/* ------------------------------------------------------------------ */
uInt decContextTestSavedStatus(uInt oldstatus, uInt mask) {
return (oldstatus&mask)!=0;
} // decContextTestSavedStatus
/* ------------------------------------------------------------------ */
/* decContextTestStatus -- test bits in current status */
/* */
/* context is the context structure to be updated */
/* mask indicates the bits to be tested (the status bits that */
/* correspond to each 1 bit in the mask are tested) */
/* returns 1 if any of the tested bits are 1, or 0 otherwise */
/* */
/* No error is possible. */
/* ------------------------------------------------------------------ */
uInt decContextTestStatus(decContext *context, uInt mask) {
return (context->status&mask)!=0;
} // decContextTestStatus
/* ------------------------------------------------------------------ */
/* decContextZeroStatus -- clear all status bits */
/* */
/* context is the context structure to be updated */
/* returns context */
/* */
/* No error is possible. */
/* ------------------------------------------------------------------ */
decContext *decContextZeroStatus(decContext *context) {
context->status=0;
return context;
} // decContextZeroStatus

254
extern/decNumber/decContext.h vendored Normal file
View File

@ -0,0 +1,254 @@
/* ------------------------------------------------------------------ */
/* Decimal Context module header */
/* ------------------------------------------------------------------ */
/* Copyright (c) IBM Corporation, 2000, 2010. All rights reserved. */
/* */
/* This software is made available under the terms of the */
/* ICU License -- ICU 1.8.1 and later. */
/* */
/* The description and User's Guide ("The decNumber C Library") for */
/* this software is called decNumber.pdf. This document is */
/* available, together with arithmetic and format specifications, */
/* testcases, and Web links, on the General Decimal Arithmetic page. */
/* */
/* Please send comments, suggestions, and corrections to the author: */
/* mfc@uk.ibm.com */
/* Mike Cowlishaw, IBM Fellow */
/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */
/* ------------------------------------------------------------------ */
/* */
/* Context variables must always have valid values: */
/* */
/* status -- [any bits may be cleared, but not set, by user] */
/* round -- must be one of the enumerated rounding modes */
/* */
/* The following variables are implied for fixed size formats (i.e., */
/* they are ignored) but should still be set correctly in case used */
/* with decNumber functions: */
/* */
/* clamp -- must be either 0 or 1 */
/* digits -- must be in the range 1 through 999999999 */
/* emax -- must be in the range 0 through 999999999 */
/* emin -- must be in the range 0 through -999999999 */
/* extended -- must be either 0 or 1 [present only if DECSUBSET] */
/* traps -- only defined bits may be set */
/* */
/* ------------------------------------------------------------------ */
#if !defined(DECCONTEXT)
#define DECCONTEXT
#define DECCNAME "decContext" /* Short name */
#define DECCFULLNAME "Decimal Context Descriptor" /* Verbose name */
#define DECCAUTHOR "Mike Cowlishaw" /* Who to blame */
#if !defined(int32_t)
#include <stdint.h> /* C99 standard integers */
#endif
#include <stdio.h> /* for printf, etc. */
#include <signal.h> /* for traps */
/* Extended flags setting -- set this to 0 to use only IEEE flags */
#if !defined(DECEXTFLAG)
#define DECEXTFLAG 1 /* 1=enable extended flags */
#endif
/* Conditional code flag -- set this to 0 for best performance */
#if !defined(DECSUBSET)
#define DECSUBSET 0 /* 1=enable subset arithmetic */
#endif
/* Context for operations, with associated constants */
enum rounding {
DEC_ROUND_CEILING, /* round towards +infinity */
DEC_ROUND_UP, /* round away from 0 */
DEC_ROUND_HALF_UP, /* 0.5 rounds up */
DEC_ROUND_HALF_EVEN, /* 0.5 rounds to nearest even */
DEC_ROUND_HALF_DOWN, /* 0.5 rounds down */
DEC_ROUND_DOWN, /* round towards 0 (truncate) */
DEC_ROUND_FLOOR, /* round towards -infinity */
DEC_ROUND_05UP, /* round for reround */
DEC_ROUND_MAX /* enum must be less than this */
};
#define DEC_ROUND_DEFAULT DEC_ROUND_HALF_EVEN;
typedef struct {
int32_t digits; /* working precision */
int32_t emax; /* maximum positive exponent */
int32_t emin; /* minimum negative exponent */
enum rounding round; /* rounding mode */
uint32_t traps; /* trap-enabler flags */
uint32_t status; /* status flags */
uint8_t clamp; /* flag: apply IEEE exponent clamp */
#if DECSUBSET
uint8_t extended; /* flag: special-values allowed */
#endif
} decContext;
/* Maxima and Minima for context settings */
#define DEC_MAX_DIGITS 999999999
#define DEC_MIN_DIGITS 1
#define DEC_MAX_EMAX 999999999
#define DEC_MIN_EMAX 0
#define DEC_MAX_EMIN 0
#define DEC_MIN_EMIN -999999999
#define DEC_MAX_MATH 999999 /* max emax, etc., for math funcs. */
/* Classifications for decimal numbers, aligned with 754 (note that */
/* 'normal' and 'subnormal' are meaningful only with a decContext */
/* or a fixed size format). */
enum decClass {
DEC_CLASS_SNAN,
DEC_CLASS_QNAN,
DEC_CLASS_NEG_INF,
DEC_CLASS_NEG_NORMAL,
DEC_CLASS_NEG_SUBNORMAL,
DEC_CLASS_NEG_ZERO,
DEC_CLASS_POS_ZERO,
DEC_CLASS_POS_SUBNORMAL,
DEC_CLASS_POS_NORMAL,
DEC_CLASS_POS_INF
};
/* Strings for the decClasses */
#define DEC_ClassString_SN "sNaN"
#define DEC_ClassString_QN "NaN"
#define DEC_ClassString_NI "-Infinity"
#define DEC_ClassString_NN "-Normal"
#define DEC_ClassString_NS "-Subnormal"
#define DEC_ClassString_NZ "-Zero"
#define DEC_ClassString_PZ "+Zero"
#define DEC_ClassString_PS "+Subnormal"
#define DEC_ClassString_PN "+Normal"
#define DEC_ClassString_PI "+Infinity"
#define DEC_ClassString_UN "Invalid"
/* Trap-enabler and Status flags (exceptional conditions), and */
/* their names. The top byte is reserved for internal use */
#if DECEXTFLAG
/* Extended flags */
#define DEC_Conversion_syntax 0x00000001
#define DEC_Division_by_zero 0x00000002
#define DEC_Division_impossible 0x00000004
#define DEC_Division_undefined 0x00000008
#define DEC_Insufficient_storage 0x00000010 /* [when malloc fails] */
#define DEC_Inexact 0x00000020
#define DEC_Invalid_context 0x00000040
#define DEC_Invalid_operation 0x00000080
#if DECSUBSET
#define DEC_Lost_digits 0x00000100
#endif
#define DEC_Overflow 0x00000200
#define DEC_Clamped 0x00000400
#define DEC_Rounded 0x00000800
#define DEC_Subnormal 0x00001000
#define DEC_Underflow 0x00002000
#else
/* IEEE flags only */
#define DEC_Conversion_syntax 0x00000010
#define DEC_Division_by_zero 0x00000002
#define DEC_Division_impossible 0x00000010
#define DEC_Division_undefined 0x00000010
#define DEC_Insufficient_storage 0x00000010 /* [when malloc fails] */
#define DEC_Inexact 0x00000001
#define DEC_Invalid_context 0x00000010
#define DEC_Invalid_operation 0x00000010
#if DECSUBSET
#define DEC_Lost_digits 0x00000000
#endif
#define DEC_Overflow 0x00000008
#define DEC_Clamped 0x00000000
#define DEC_Rounded 0x00000000
#define DEC_Subnormal 0x00000000
#define DEC_Underflow 0x00000004
#endif
/* IEEE 754 groupings for the flags */
/* [DEC_Clamped, DEC_Lost_digits, DEC_Rounded, and DEC_Subnormal */
/* are not in IEEE 754] */
#define DEC_IEEE_754_Division_by_zero (DEC_Division_by_zero)
#if DECSUBSET
#define DEC_IEEE_754_Inexact (DEC_Inexact | DEC_Lost_digits)
#else
#define DEC_IEEE_754_Inexact (DEC_Inexact)
#endif
#define DEC_IEEE_754_Invalid_operation (DEC_Conversion_syntax | \
DEC_Division_impossible | \
DEC_Division_undefined | \
DEC_Insufficient_storage | \
DEC_Invalid_context | \
DEC_Invalid_operation)
#define DEC_IEEE_754_Overflow (DEC_Overflow)
#define DEC_IEEE_754_Underflow (DEC_Underflow)
/* flags which are normally errors (result is qNaN, infinite, or 0) */
#define DEC_Errors (DEC_IEEE_754_Division_by_zero | \
DEC_IEEE_754_Invalid_operation | \
DEC_IEEE_754_Overflow | DEC_IEEE_754_Underflow)
/* flags which cause a result to become qNaN */
#define DEC_NaNs DEC_IEEE_754_Invalid_operation
/* flags which are normally for information only (finite results) */
#if DECSUBSET
#define DEC_Information (DEC_Clamped | DEC_Rounded | DEC_Inexact \
| DEC_Lost_digits)
#else
#define DEC_Information (DEC_Clamped | DEC_Rounded | DEC_Inexact)
#endif
/* IEEE 854 names (for compatibility with older decNumber versions) */
#define DEC_IEEE_854_Division_by_zero DEC_IEEE_754_Division_by_zero
#define DEC_IEEE_854_Inexact DEC_IEEE_754_Inexact
#define DEC_IEEE_854_Invalid_operation DEC_IEEE_754_Invalid_operation
#define DEC_IEEE_854_Overflow DEC_IEEE_754_Overflow
#define DEC_IEEE_854_Underflow DEC_IEEE_754_Underflow
/* Name strings for the exceptional conditions */
#define DEC_Condition_CS "Conversion syntax"
#define DEC_Condition_DZ "Division by zero"
#define DEC_Condition_DI "Division impossible"
#define DEC_Condition_DU "Division undefined"
#define DEC_Condition_IE "Inexact"
#define DEC_Condition_IS "Insufficient storage"
#define DEC_Condition_IC "Invalid context"
#define DEC_Condition_IO "Invalid operation"
#if DECSUBSET
#define DEC_Condition_LD "Lost digits"
#endif
#define DEC_Condition_OV "Overflow"
#define DEC_Condition_PA "Clamped"
#define DEC_Condition_RO "Rounded"
#define DEC_Condition_SU "Subnormal"
#define DEC_Condition_UN "Underflow"
#define DEC_Condition_ZE "No status"
#define DEC_Condition_MU "Multiple status"
#define DEC_Condition_Length 21 /* length of the longest string, */
/* including terminator */
/* Initialization descriptors, used by decContextDefault */
#define DEC_INIT_BASE 0
#define DEC_INIT_DECIMAL32 32
#define DEC_INIT_DECIMAL64 64
#define DEC_INIT_DECIMAL128 128
/* Synonyms */
#define DEC_INIT_DECSINGLE DEC_INIT_DECIMAL32
#define DEC_INIT_DECDOUBLE DEC_INIT_DECIMAL64
#define DEC_INIT_DECQUAD DEC_INIT_DECIMAL128
/* decContext routines */
extern decContext * decContextClearStatus(decContext *, uint32_t);
extern decContext * decContextDefault(decContext *, int32_t);
extern enum rounding decContextGetRounding(decContext *);
extern uint32_t decContextGetStatus(decContext *);
extern decContext * decContextRestoreStatus(decContext *, uint32_t, uint32_t);
extern uint32_t decContextSaveStatus(decContext *, uint32_t);
extern decContext * decContextSetRounding(decContext *, enum rounding);
extern decContext * decContextSetStatus(decContext *, uint32_t);
extern decContext * decContextSetStatusFromString(decContext *, const char *);
extern decContext * decContextSetStatusFromStringQuiet(decContext *, const char *);
extern decContext * decContextSetStatusQuiet(decContext *, uint32_t);
extern const char * decContextStatusToString(const decContext *);
extern int32_t decContextTestEndian(uint8_t);
extern uint32_t decContextTestSavedStatus(uint32_t, uint32_t);
extern uint32_t decContextTestStatus(decContext *, uint32_t);
extern decContext * decContextZeroStatus(decContext *);
#endif

1185
extern/decNumber/decDPD.h vendored Normal file

File diff suppressed because it is too large Load Diff

140
extern/decNumber/decDouble.c vendored Normal file
View File

@ -0,0 +1,140 @@
/* ------------------------------------------------------------------ */
/* decDouble.c -- decDouble operations module */
/* ------------------------------------------------------------------ */
/* Copyright (c) IBM Corporation, 2000, 2010. All rights reserved. */
/* */
/* This software is made available under the terms of the */
/* ICU License -- ICU 1.8.1 and later. */
/* */
/* The description and User's Guide ("The decNumber C Library") for */
/* this software is included in the package as decNumber.pdf. This */
/* document is also available in HTML, together with specifications, */
/* testcases, and Web links, on the General Decimal Arithmetic page. */
/* */
/* Please send comments, suggestions, and corrections to the author: */
/* mfc@uk.ibm.com */
/* Mike Cowlishaw, IBM Fellow */
/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */
/* ------------------------------------------------------------------ */
/* This module comprises decDouble operations (including conversions) */
/* ------------------------------------------------------------------ */
#include "decContext.h" // public includes
#include "decDouble.h" // ..
/* Constant mappings for shared code */
#define DECPMAX DECDOUBLE_Pmax
#define DECEMIN DECDOUBLE_Emin
#define DECEMAX DECDOUBLE_Emax
#define DECEMAXD DECDOUBLE_EmaxD
#define DECBYTES DECDOUBLE_Bytes
#define DECSTRING DECDOUBLE_String
#define DECECONL DECDOUBLE_EconL
#define DECBIAS DECDOUBLE_Bias
#define DECLETS DECDOUBLE_Declets
#define DECQTINY (-DECDOUBLE_Bias)
// parameters of next-wider format
#define DECWBYTES DECQUAD_Bytes
#define DECWPMAX DECQUAD_Pmax
#define DECWECONL DECQUAD_EconL
#define DECWBIAS DECQUAD_Bias
/* Type and function mappings for shared code */
#define decFloat decDouble // Type name
#define decFloatWider decQuad // Type name
// Utilities and conversions (binary results, extractors, etc.)
#define decFloatFromBCD decDoubleFromBCD
#define decFloatFromInt32 decDoubleFromInt32
#define decFloatFromPacked decDoubleFromPacked
#define decFloatFromPackedChecked decDoubleFromPackedChecked
#define decFloatFromString decDoubleFromString
#define decFloatFromUInt32 decDoubleFromUInt32
#define decFloatFromWider decDoubleFromWider
#define decFloatGetCoefficient decDoubleGetCoefficient
#define decFloatGetExponent decDoubleGetExponent
#define decFloatSetCoefficient decDoubleSetCoefficient
#define decFloatSetExponent decDoubleSetExponent
#define decFloatShow decDoubleShow
#define decFloatToBCD decDoubleToBCD
#define decFloatToEngString decDoubleToEngString
#define decFloatToInt32 decDoubleToInt32
#define decFloatToInt32Exact decDoubleToInt32Exact
#define decFloatToPacked decDoubleToPacked
#define decFloatToString decDoubleToString
#define decFloatToUInt32 decDoubleToUInt32
#define decFloatToUInt32Exact decDoubleToUInt32Exact
#define decFloatToWider decDoubleToWider
#define decFloatZero decDoubleZero
// Computational (result is a decFloat)
#define decFloatAbs decDoubleAbs
#define decFloatAdd decDoubleAdd
#define decFloatAnd decDoubleAnd
#define decFloatDivide decDoubleDivide
#define decFloatDivideInteger decDoubleDivideInteger
#define decFloatFMA decDoubleFMA
#define decFloatInvert decDoubleInvert
#define decFloatLogB decDoubleLogB
#define decFloatMax decDoubleMax
#define decFloatMaxMag decDoubleMaxMag
#define decFloatMin decDoubleMin
#define decFloatMinMag decDoubleMinMag
#define decFloatMinus decDoubleMinus
#define decFloatMultiply decDoubleMultiply
#define decFloatNextMinus decDoubleNextMinus
#define decFloatNextPlus decDoubleNextPlus
#define decFloatNextToward decDoubleNextToward
#define decFloatOr decDoubleOr
#define decFloatPlus decDoublePlus
#define decFloatQuantize decDoubleQuantize
#define decFloatReduce decDoubleReduce
#define decFloatRemainder decDoubleRemainder
#define decFloatRemainderNear decDoubleRemainderNear
#define decFloatRotate decDoubleRotate
#define decFloatScaleB decDoubleScaleB
#define decFloatShift decDoubleShift
#define decFloatSubtract decDoubleSubtract
#define decFloatToIntegralValue decDoubleToIntegralValue
#define decFloatToIntegralExact decDoubleToIntegralExact
#define decFloatXor decDoubleXor
// Comparisons
#define decFloatCompare decDoubleCompare
#define decFloatCompareSignal decDoubleCompareSignal
#define decFloatCompareTotal decDoubleCompareTotal
#define decFloatCompareTotalMag decDoubleCompareTotalMag
// Copies
#define decFloatCanonical decDoubleCanonical
#define decFloatCopy decDoubleCopy
#define decFloatCopyAbs decDoubleCopyAbs
#define decFloatCopyNegate decDoubleCopyNegate
#define decFloatCopySign decDoubleCopySign
// Non-computational
#define decFloatClass decDoubleClass
#define decFloatClassString decDoubleClassString
#define decFloatDigits decDoubleDigits
#define decFloatIsCanonical decDoubleIsCanonical
#define decFloatIsFinite decDoubleIsFinite
#define decFloatIsInfinite decDoubleIsInfinite
#define decFloatIsInteger decDoubleIsInteger
#define decFloatIsLogical decDoubleIsLogical
#define decFloatIsNaN decDoubleIsNaN
#define decFloatIsNegative decDoubleIsNegative
#define decFloatIsNormal decDoubleIsNormal
#define decFloatIsPositive decDoubleIsPositive
#define decFloatIsSignaling decDoubleIsSignaling
#define decFloatIsSignalling decDoubleIsSignalling
#define decFloatIsSigned decDoubleIsSigned
#define decFloatIsSubnormal decDoubleIsSubnormal
#define decFloatIsZero decDoubleIsZero
#define decFloatRadix decDoubleRadix
#define decFloatSameQuantum decDoubleSameQuantum
#define decFloatVersion decDoubleVersion
#include "decNumberLocal.h" // local includes (need DECPMAX)
#include "decCommon.c" // non-arithmetic decFloat routines
#include "decBasic.c" // basic formats routines

155
extern/decNumber/decDouble.h vendored Normal file
View File

@ -0,0 +1,155 @@
/* ------------------------------------------------------------------ */
/* decDouble.h -- Decimal 64-bit format module header */
/* ------------------------------------------------------------------ */
/* Copyright (c) IBM Corporation, 2000, 2010. All rights reserved. */
/* */
/* This software is made available under the terms of the */
/* ICU License -- ICU 1.8.1 and later. */
/* */
/* The description and User's Guide ("The decNumber C Library") for */
/* this software is included in the package as decNumber.pdf. This */
/* document is also available in HTML, together with specifications, */
/* testcases, and Web links, on the General Decimal Arithmetic page. */
/* */
/* Please send comments, suggestions, and corrections to the author: */
/* mfc@uk.ibm.com */
/* Mike Cowlishaw, IBM Fellow */
/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */
/* ------------------------------------------------------------------ */
#if !defined(DECDOUBLE)
#define DECDOUBLE
#define DECDOUBLENAME "decimalDouble" /* Short name */
#define DECDOUBLETITLE "Decimal 64-bit datum" /* Verbose name */
#define DECDOUBLEAUTHOR "Mike Cowlishaw" /* Who to blame */
/* parameters for decDoubles */
#define DECDOUBLE_Bytes 8 /* length */
#define DECDOUBLE_Pmax 16 /* maximum precision (digits) */
#define DECDOUBLE_Emin -383 /* minimum adjusted exponent */
#define DECDOUBLE_Emax 384 /* maximum adjusted exponent */
#define DECDOUBLE_EmaxD 3 /* maximum exponent digits */
#define DECDOUBLE_Bias 398 /* bias for the exponent */
#define DECDOUBLE_String 25 /* maximum string length, +1 */
#define DECDOUBLE_EconL 8 /* exponent continuation length */
#define DECDOUBLE_Declets 5 /* count of declets */
/* highest biased exponent (Elimit-1) */
#define DECDOUBLE_Ehigh (DECDOUBLE_Emax + DECDOUBLE_Bias - (DECDOUBLE_Pmax-1))
/* Required includes */
#include "decContext.h"
#include "decQuad.h"
/* The decDouble decimal 64-bit type, accessible by all sizes */
typedef union {
uint8_t bytes[DECDOUBLE_Bytes]; /* fields: 1, 5, 8, 50 bits */
uint16_t shorts[DECDOUBLE_Bytes/2];
uint32_t words[DECDOUBLE_Bytes/4];
#if DECUSE64
uint64_t longs[DECDOUBLE_Bytes/8];
#endif
} decDouble;
/* ---------------------------------------------------------------- */
/* Routines -- implemented as decFloat routines in common files */
/* ---------------------------------------------------------------- */
/* Utilities and conversions, extractors, etc.) */
extern decDouble * decDoubleFromBCD(decDouble *, int32_t, const uint8_t *, int32_t);
extern decDouble * decDoubleFromInt32(decDouble *, int32_t);
extern decDouble * decDoubleFromPacked(decDouble *, int32_t, const uint8_t *);
extern decDouble * decDoubleFromPackedChecked(decDouble *, int32_t, const uint8_t *);
extern decDouble * decDoubleFromString(decDouble *, const char *, decContext *);
extern decDouble * decDoubleFromUInt32(decDouble *, uint32_t);
extern decDouble * decDoubleFromWider(decDouble *, const decQuad *, decContext *);
extern int32_t decDoubleGetCoefficient(const decDouble *, uint8_t *);
extern int32_t decDoubleGetExponent(const decDouble *);
extern decDouble * decDoubleSetCoefficient(decDouble *, const uint8_t *, int32_t);
extern decDouble * decDoubleSetExponent(decDouble *, decContext *, int32_t);
extern void decDoubleShow(const decDouble *, const char *);
extern int32_t decDoubleToBCD(const decDouble *, int32_t *, uint8_t *);
extern char * decDoubleToEngString(const decDouble *, char *);
extern int32_t decDoubleToInt32(const decDouble *, decContext *, enum rounding);
extern int32_t decDoubleToInt32Exact(const decDouble *, decContext *, enum rounding);
extern int32_t decDoubleToPacked(const decDouble *, int32_t *, uint8_t *);
extern char * decDoubleToString(const decDouble *, char *);
extern uint32_t decDoubleToUInt32(const decDouble *, decContext *, enum rounding);
extern uint32_t decDoubleToUInt32Exact(const decDouble *, decContext *, enum rounding);
extern decQuad * decDoubleToWider(const decDouble *, decQuad *);
extern decDouble * decDoubleZero(decDouble *);
/* Computational (result is a decDouble) */
extern decDouble * decDoubleAbs(decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleAdd(decDouble *, const decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleAnd(decDouble *, const decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleDivide(decDouble *, const decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleDivideInteger(decDouble *, const decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleFMA(decDouble *, const decDouble *, const decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleInvert(decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleLogB(decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleMax(decDouble *, const decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleMaxMag(decDouble *, const decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleMin(decDouble *, const decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleMinMag(decDouble *, const decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleMinus(decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleMultiply(decDouble *, const decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleNextMinus(decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleNextPlus(decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleNextToward(decDouble *, const decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleOr(decDouble *, const decDouble *, const decDouble *, decContext *);
extern decDouble * decDoublePlus(decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleQuantize(decDouble *, const decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleReduce(decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleRemainder(decDouble *, const decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleRemainderNear(decDouble *, const decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleRotate(decDouble *, const decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleScaleB(decDouble *, const decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleShift(decDouble *, const decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleSubtract(decDouble *, const decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleToIntegralValue(decDouble *, const decDouble *, decContext *, enum rounding);
extern decDouble * decDoubleToIntegralExact(decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleXor(decDouble *, const decDouble *, const decDouble *, decContext *);
/* Comparisons */
extern decDouble * decDoubleCompare(decDouble *, const decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleCompareSignal(decDouble *, const decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleCompareTotal(decDouble *, const decDouble *, const decDouble *);
extern decDouble * decDoubleCompareTotalMag(decDouble *, const decDouble *, const decDouble *);
/* Copies */
extern decDouble * decDoubleCanonical(decDouble *, const decDouble *);
extern decDouble * decDoubleCopy(decDouble *, const decDouble *);
extern decDouble * decDoubleCopyAbs(decDouble *, const decDouble *);
extern decDouble * decDoubleCopyNegate(decDouble *, const decDouble *);
extern decDouble * decDoubleCopySign(decDouble *, const decDouble *, const decDouble *);
/* Non-computational */
extern enum decClass decDoubleClass(const decDouble *);
extern const char * decDoubleClassString(const decDouble *);
extern uint32_t decDoubleDigits(const decDouble *);
extern uint32_t decDoubleIsCanonical(const decDouble *);
extern uint32_t decDoubleIsFinite(const decDouble *);
extern uint32_t decDoubleIsInfinite(const decDouble *);
extern uint32_t decDoubleIsInteger(const decDouble *);
extern uint32_t decDoubleIsLogical(const decDouble *);
extern uint32_t decDoubleIsNaN(const decDouble *);
extern uint32_t decDoubleIsNegative(const decDouble *);
extern uint32_t decDoubleIsNormal(const decDouble *);
extern uint32_t decDoubleIsPositive(const decDouble *);
extern uint32_t decDoubleIsSignaling(const decDouble *);
extern uint32_t decDoubleIsSignalling(const decDouble *);
extern uint32_t decDoubleIsSigned(const decDouble *);
extern uint32_t decDoubleIsSubnormal(const decDouble *);
extern uint32_t decDoubleIsZero(const decDouble *);
extern uint32_t decDoubleRadix(const decDouble *);
extern uint32_t decDoubleSameQuantum(const decDouble *, const decDouble *);
extern const char * decDoubleVersion(void);
/* decNumber conversions; these are implemented as macros so as not */
/* to force a dependency on decimal64 and decNumber in decDouble. */
/* decDoubleFromNumber returns a decimal64 * to avoid warnings. */
#define decDoubleToNumber(dq, dn) decimal64ToNumber((decimal64 *)(dq), dn)
#define decDoubleFromNumber(dq, dn, set) decimal64FromNumber((decimal64 *)(dq), dn, set)
#endif

8141
extern/decNumber/decNumber.c vendored Normal file

File diff suppressed because it is too large Load Diff

182
extern/decNumber/decNumber.h vendored Normal file
View File

@ -0,0 +1,182 @@
/* ------------------------------------------------------------------ */
/* Decimal Number arithmetic module header */
/* ------------------------------------------------------------------ */
/* Copyright (c) IBM Corporation, 2000, 2010. All rights reserved. */
/* */
/* This software is made available under the terms of the */
/* ICU License -- ICU 1.8.1 and later. */
/* */
/* The description and User's Guide ("The decNumber C Library") for */
/* this software is called decNumber.pdf. This document is */
/* available, together with arithmetic and format specifications, */
/* testcases, and Web links, on the General Decimal Arithmetic page. */
/* */
/* Please send comments, suggestions, and corrections to the author: */
/* mfc@uk.ibm.com */
/* Mike Cowlishaw, IBM Fellow */
/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */
/* ------------------------------------------------------------------ */
#if !defined(DECNUMBER)
#define DECNUMBER
#define DECNAME "decNumber" /* Short name */
#define DECFULLNAME "Decimal Number Module" /* Verbose name */
#define DECAUTHOR "Mike Cowlishaw" /* Who to blame */
#if !defined(DECCONTEXT)
#include "decContext.h"
#endif
/* Bit settings for decNumber.bits */
#define DECNEG 0x80 /* Sign; 1=negative, 0=positive or zero */
#define DECINF 0x40 /* 1=Infinity */
#define DECNAN 0x20 /* 1=NaN */
#define DECSNAN 0x10 /* 1=sNaN */
/* The remaining bits are reserved; they must be 0 */
#define DECSPECIAL (DECINF|DECNAN|DECSNAN) /* any special value */
/* Define the decNumber data structure. The size and shape of the */
/* units array in the structure is determined by the following */
/* constant. This must not be changed without recompiling the */
/* decNumber library modules. */
#define DECDPUN 3 /* DECimal Digits Per UNit [must be >0 */
/* and <10; 3 or powers of 2 are best]. */
/* DECNUMDIGITS is the default number of digits that can be held in */
/* the structure. If undefined, 1 is assumed and it is assumed */
/* that the structure will be immediately followed by extra space, */
/* as required. DECNUMDIGITS is always >0. */
#if !defined(DECNUMDIGITS)
#define DECNUMDIGITS 1
#endif
/* The size (integer data type) of each unit is determined by the */
/* number of digits it will hold. */
#if DECDPUN<=2
#define decNumberUnit uint8_t
#elif DECDPUN<=4
#define decNumberUnit uint16_t
#else
#define decNumberUnit uint32_t
#endif
/* The number of units needed is ceil(DECNUMDIGITS/DECDPUN) */
#define DECNUMUNITS ((DECNUMDIGITS+DECDPUN-1)/DECDPUN)
/* The data structure... */
typedef struct {
int32_t digits; /* Count of digits in the coefficient; >0 */
int32_t exponent; /* Unadjusted exponent, unbiased, in */
/* range: -1999999997 through 999999999 */
uint8_t bits; /* Indicator bits (see above) */
/* Coefficient, from least significant unit */
decNumberUnit lsu[DECNUMUNITS];
} decNumber;
/* Notes: */
/* 1. If digits is > DECDPUN then there will one or more */
/* decNumberUnits immediately following the first element of lsu.*/
/* These contain the remaining (more significant) digits of the */
/* number, and may be in the lsu array, or may be guaranteed by */
/* some other mechanism (such as being contained in another */
/* structure, or being overlaid on dynamically allocated */
/* storage). */
/* */
/* Each integer of the coefficient (except potentially the last) */
/* contains DECDPUN digits (e.g., a value in the range 0 through */
/* 99999999 if DECDPUN is 8, or 0 through 999 if DECDPUN is 3). */
/* */
/* 2. A decNumber converted to a string may need up to digits+14 */
/* characters. The worst cases (non-exponential and exponential */
/* formats) are -0.00000{9...}# and -9.{9...}E+999999999# */
/* (where # is '\0') */
/* ---------------------------------------------------------------- */
/* decNumber public functions and macros */
/* ---------------------------------------------------------------- */
/* Conversions */
decNumber * decNumberFromInt32(decNumber *, int32_t);
decNumber * decNumberFromUInt32(decNumber *, uint32_t);
decNumber * decNumberFromString(decNumber *, const char *, decContext *);
char * decNumberToString(const decNumber *, char *);
char * decNumberToEngString(const decNumber *, char *);
uint32_t decNumberToUInt32(const decNumber *, decContext *);
int32_t decNumberToInt32(const decNumber *, decContext *);
uint8_t * decNumberGetBCD(const decNumber *, uint8_t *);
decNumber * decNumberSetBCD(decNumber *, const uint8_t *, uint32_t);
/* Operators and elementary functions */
decNumber * decNumberAbs(decNumber *, const decNumber *, decContext *);
decNumber * decNumberAdd(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberAnd(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberCompare(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberCompareSignal(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberCompareTotal(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberCompareTotalMag(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberDivide(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberDivideInteger(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberExp(decNumber *, const decNumber *, decContext *);
decNumber * decNumberFMA(decNumber *, const decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberInvert(decNumber *, const decNumber *, decContext *);
decNumber * decNumberLn(decNumber *, const decNumber *, decContext *);
decNumber * decNumberLogB(decNumber *, const decNumber *, decContext *);
decNumber * decNumberLog10(decNumber *, const decNumber *, decContext *);
decNumber * decNumberMax(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberMaxMag(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberMin(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberMinMag(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberMinus(decNumber *, const decNumber *, decContext *);
decNumber * decNumberMultiply(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberNormalize(decNumber *, const decNumber *, decContext *);
decNumber * decNumberOr(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberPlus(decNumber *, const decNumber *, decContext *);
decNumber * decNumberPower(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberQuantize(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberReduce(decNumber *, const decNumber *, decContext *);
decNumber * decNumberRemainder(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberRemainderNear(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberRescale(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberRotate(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberSameQuantum(decNumber *, const decNumber *, const decNumber *);
decNumber * decNumberScaleB(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberShift(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberSquareRoot(decNumber *, const decNumber *, decContext *);
decNumber * decNumberSubtract(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberToIntegralExact(decNumber *, const decNumber *, decContext *);
decNumber * decNumberToIntegralValue(decNumber *, const decNumber *, decContext *);
decNumber * decNumberXor(decNumber *, const decNumber *, const decNumber *, decContext *);
/* Utilities */
enum decClass decNumberClass(const decNumber *, decContext *);
const char * decNumberClassToString(enum decClass);
decNumber * decNumberCopy(decNumber *, const decNumber *);
decNumber * decNumberCopyAbs(decNumber *, const decNumber *);
decNumber * decNumberCopyNegate(decNumber *, const decNumber *);
decNumber * decNumberCopySign(decNumber *, const decNumber *, const decNumber *);
decNumber * decNumberNextMinus(decNumber *, const decNumber *, decContext *);
decNumber * decNumberNextPlus(decNumber *, const decNumber *, decContext *);
decNumber * decNumberNextToward(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberTrim(decNumber *);
const char * decNumberVersion(void);
decNumber * decNumberZero(decNumber *);
/* Functions for testing decNumbers (normality depends on context) */
int32_t decNumberIsNormal(const decNumber *, decContext *);
int32_t decNumberIsSubnormal(const decNumber *, decContext *);
/* Macros for testing decNumber *dn */
#define decNumberIsCanonical(dn) (1) /* All decNumbers are saintly */
#define decNumberIsFinite(dn) (((dn)->bits&DECSPECIAL)==0)
#define decNumberIsInfinite(dn) (((dn)->bits&DECINF)!=0)
#define decNumberIsNaN(dn) (((dn)->bits&(DECNAN|DECSNAN))!=0)
#define decNumberIsNegative(dn) (((dn)->bits&DECNEG)!=0)
#define decNumberIsQNaN(dn) (((dn)->bits&(DECNAN))!=0)
#define decNumberIsSNaN(dn) (((dn)->bits&(DECSNAN))!=0)
#define decNumberIsSpecial(dn) (((dn)->bits&DECSPECIAL)!=0)
#define decNumberIsZero(dn) (*(dn)->lsu==0 \
&& (dn)->digits==1 \
&& (((dn)->bits&DECSPECIAL)==0))
#define decNumberRadix(dn) (10)
#endif

757
extern/decNumber/decNumberLocal.h vendored Normal file
View File

@ -0,0 +1,757 @@
/* ------------------------------------------------------------------ */
/* decNumber package local type, tuning, and macro definitions */
/* ------------------------------------------------------------------ */
/* Copyright (c) IBM Corporation, 2000, 2010. All rights reserved. */
/* */
/* This software is made available under the terms of the */
/* ICU License -- ICU 1.8.1 and later. */
/* */
/* The description and User's Guide ("The decNumber C Library") for */
/* this software is called decNumber.pdf. This document is */
/* available, together with arithmetic and format specifications, */
/* testcases, and Web links, on the General Decimal Arithmetic page. */
/* */
/* Please send comments, suggestions, and corrections to the author: */
/* mfc@uk.ibm.com */
/* Mike Cowlishaw, IBM Fellow */
/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */
/* ------------------------------------------------------------------ */
/* This header file is included by all modules in the decNumber */
/* library, and contains local type definitions, tuning parameters, */
/* etc. It should not need to be used by application programs. */
/* decNumber.h or one of decDouble (etc.) must be included first. */
/* ------------------------------------------------------------------ */
#if !defined(DECNUMBERLOC)
#define DECNUMBERLOC
#define DECVERSION "decNumber 3.68" /* Package Version [16 max.] */
#define DECNLAUTHOR "Mike Cowlishaw" /* Who to blame */
#include <stdlib.h> /* for abs */
#include <string.h> /* for memset, strcpy */
/* Conditional code flag -- set this to match hardware platform */
#if !defined(DECLITEND)
#define DECLITEND 1 /* 1=little-endian, 0=big-endian */
#endif
/* Conditional code flag -- set this to 1 for best performance */
#if !defined(DECUSE64)
#define DECUSE64 1 /* 1=use int64s, 0=int32 & smaller only */
#endif
/* Conditional code flag -- set this to 0 to exclude printf calls */
#if !defined(DECPRINT)
#define DECPRINT 1 /* 1=allow printf calls; 0=no printf */
#endif
/* Conditional check flags -- set these to 0 for best performance */
#if !defined(DECCHECK)
#define DECCHECK 0 /* 1 to enable robust checking */
#endif
#if !defined(DECALLOC)
#define DECALLOC 0 /* 1 to enable memory accounting */
#endif
#if !defined(DECTRACE)
#define DECTRACE 0 /* 1 to trace certain internals, etc. */
#endif
/* Tuning parameter for decNumber (arbitrary precision) module */
#if !defined(DECBUFFER)
#define DECBUFFER 36 /* Size basis for local buffers. This */
/* should be a common maximum precision */
/* rounded up to a multiple of 4; must */
/* be zero or positive. */
#endif
/* ---------------------------------------------------------------- */
/* Check parameter dependencies */
/* ---------------------------------------------------------------- */
#if DECCHECK & !DECPRINT
#error DECCHECK needs DECPRINT to be useful
#endif
#if DECALLOC & !DECPRINT
#error DECALLOC needs DECPRINT to be useful
#endif
#if DECTRACE & !DECPRINT
#error DECTRACE needs DECPRINT to be useful
#endif
/* ---------------------------------------------------------------- */
/* Definitions for all modules (general-purpose) */
/* ---------------------------------------------------------------- */
/* Local names for common types -- for safety, decNumber modules do */
/* not use int or long directly. */
#define Flag uint8_t
#define Byte int8_t
#define uByte uint8_t
#define Short int16_t
#define uShort uint16_t
#define Int int32_t
#define uInt uint32_t
#define Unit decNumberUnit
#if DECUSE64
#define Long int64_t
#define uLong uint64_t
#endif
/* Development-use definitions */
typedef long int LI; /* for printf arguments only */
#define DECNOINT 0 /* 1 to check no internal use of 'int' */
/* or stdint types */
#if DECNOINT
/* if these interfere with your C includes, do not set DECNOINT */
#define int ? /* enable to ensure that plain C 'int' */
#define long ?? /* .. or 'long' types are not used */
#endif
/* Shared lookup tables */
extern const uByte DECSTICKYTAB[10]; /* re-round digits if sticky */
extern const uInt DECPOWERS[10]; /* powers of ten table */
/* The following are included from decDPD.h */
extern const uShort DPD2BIN[1024]; /* DPD -> 0-999 */
extern const uShort BIN2DPD[1000]; /* 0-999 -> DPD */
extern const uInt DPD2BINK[1024]; /* DPD -> 0-999000 */
extern const uInt DPD2BINM[1024]; /* DPD -> 0-999000000 */
extern const uByte DPD2BCD8[4096]; /* DPD -> ddd + len */
extern const uByte BIN2BCD8[4000]; /* 0-999 -> ddd + len */
extern const uShort BCD2DPD[2458]; /* 0-0x999 -> DPD (0x999=2457)*/
/* LONGMUL32HI -- set w=(u*v)>>32, where w, u, and v are uInts */
/* (that is, sets w to be the high-order word of the 64-bit result; */
/* the low-order word is simply u*v.) */
/* This version is derived from Knuth via Hacker's Delight; */
/* it seems to optimize better than some others tried */
#define LONGMUL32HI(w, u, v) { \
uInt u0, u1, v0, v1, w0, w1, w2, t; \
u0=u & 0xffff; u1=u>>16; \
v0=v & 0xffff; v1=v>>16; \
w0=u0*v0; \
t=u1*v0 + (w0>>16); \
w1=t & 0xffff; w2=t>>16; \
w1=u0*v1 + w1; \
(w)=u1*v1 + w2 + (w1>>16);}
/* ROUNDUP -- round an integer up to a multiple of n */
#define ROUNDUP(i, n) ((((i)+(n)-1)/n)*n)
#define ROUNDUP4(i) (((i)+3)&~3) /* special for n=4 */
/* ROUNDDOWN -- round an integer down to a multiple of n */
#define ROUNDDOWN(i, n) (((i)/n)*n)
#define ROUNDDOWN4(i) ((i)&~3) /* special for n=4 */
/* References to multi-byte sequences under different sizes; these */
/* require locally declared variables, but do not violate strict */
/* aliasing or alignment (as did the UINTAT simple cast to uInt). */
/* Variables needed are uswork, uiwork, etc. [so do not use at same */
/* level in an expression, e.g., UBTOUI(x)==UBTOUI(y) may fail]. */
/* Return a uInt, etc., from bytes starting at a char* or uByte* */
#define UBTOUS(b) (memcpy((void *)&uswork, b, 2), uswork)
#define UBTOUI(b) (memcpy((void *)&uiwork, b, 4), uiwork)
/* Store a uInt, etc., into bytes starting at a char* or uByte*. */
/* Returns i, evaluated, for convenience; has to use uiwork because */
/* i may be an expression. */
#define UBFROMUS(b, i) (uswork=(i), memcpy(b, (void *)&uswork, 2), uswork)
#define UBFROMUI(b, i) (uiwork=(i), memcpy(b, (void *)&uiwork, 4), uiwork)
/* X10 and X100 -- multiply integer i by 10 or 100 */
/* [shifts are usually faster than multiply; could be conditional] */
#define X10(i) (((i)<<1)+((i)<<3))
#define X100(i) (((i)<<2)+((i)<<5)+((i)<<6))
/* MAXI and MINI -- general max & min (not in ANSI) for integers */
#define MAXI(x,y) ((x)<(y)?(y):(x))
#define MINI(x,y) ((x)>(y)?(y):(x))
/* Useful constants */
#define BILLION 1000000000 /* 10**9 */
/* CHARMASK: 0x30303030 for ASCII/UTF8; 0xF0F0F0F0 for EBCDIC */
#define CHARMASK ((((((((uInt)'0')<<8)+'0')<<8)+'0')<<8)+'0')
/* ---------------------------------------------------------------- */
/* Definitions for arbitary-precision modules (only valid after */
/* decNumber.h has been included) */
/* ---------------------------------------------------------------- */
/* Limits and constants */
#define DECNUMMAXP 999999999 /* maximum precision code can handle */
#define DECNUMMAXE 999999999 /* maximum adjusted exponent ditto */
#define DECNUMMINE -999999999 /* minimum adjusted exponent ditto */
#if (DECNUMMAXP != DEC_MAX_DIGITS)
#error Maximum digits mismatch
#endif
#if (DECNUMMAXE != DEC_MAX_EMAX)
#error Maximum exponent mismatch
#endif
#if (DECNUMMINE != DEC_MIN_EMIN)
#error Minimum exponent mismatch
#endif
/* Set DECDPUNMAX -- the maximum integer that fits in DECDPUN */
/* digits, and D2UTABLE -- the initializer for the D2U table */
#if DECDPUN==1
#define DECDPUNMAX 9
#define D2UTABLE {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17, \
18,19,20,21,22,23,24,25,26,27,28,29,30,31,32, \
33,34,35,36,37,38,39,40,41,42,43,44,45,46,47, \
48,49}
#elif DECDPUN==2
#define DECDPUNMAX 99
#define D2UTABLE {0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10, \
11,11,12,12,13,13,14,14,15,15,16,16,17,17,18, \
18,19,19,20,20,21,21,22,22,23,23,24,24,25}
#elif DECDPUN==3
#define DECDPUNMAX 999
#define D2UTABLE {0,1,1,1,2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7, \
8,8,8,9,9,9,10,10,10,11,11,11,12,12,12,13,13, \
13,14,14,14,15,15,15,16,16,16,17}
#elif DECDPUN==4
#define DECDPUNMAX 9999
#define D2UTABLE {0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,6, \
6,6,6,7,7,7,7,8,8,8,8,9,9,9,9,10,10,10,10,11, \
11,11,11,12,12,12,12,13}
#elif DECDPUN==5
#define DECDPUNMAX 99999
#define D2UTABLE {0,1,1,1,1,1,2,2,2,2,2,3,3,3,3,3,4,4,4,4,4,5, \
5,5,5,5,6,6,6,6,6,7,7,7,7,7,8,8,8,8,8,9,9,9, \
9,9,10,10,10,10}
#elif DECDPUN==6
#define DECDPUNMAX 999999
#define D2UTABLE {0,1,1,1,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,4,4,4, \
4,4,4,5,5,5,5,5,5,6,6,6,6,6,6,7,7,7,7,7,7,8, \
8,8,8,8,8,9}
#elif DECDPUN==7
#define DECDPUNMAX 9999999
#define D2UTABLE {0,1,1,1,1,1,1,1,2,2,2,2,2,2,2,3,3,3,3,3,3,3, \
4,4,4,4,4,4,4,5,5,5,5,5,5,5,6,6,6,6,6,6,6,7, \
7,7,7,7,7,7}
#elif DECDPUN==8
#define DECDPUNMAX 99999999
#define D2UTABLE {0,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3, \
3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,6,6,6, \
6,6,6,6,6,7}
#elif DECDPUN==9
#define DECDPUNMAX 999999999
#define D2UTABLE {0,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,3,3,3, \
3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5, \
5,5,6,6,6,6}
#elif defined(DECDPUN)
#error DECDPUN must be in the range 1-9
#endif
/* ----- Shared data (in decNumber.c) ----- */
/* Public lookup table used by the D2U macro (see below) */
#define DECMAXD2U 49
extern const uByte d2utable[DECMAXD2U+1];
/* ----- Macros ----- */
/* ISZERO -- return true if decNumber dn is a zero */
/* [performance-critical in some situations] */
#define ISZERO(dn) decNumberIsZero(dn) /* now just a local name */
/* D2U -- return the number of Units needed to hold d digits */
/* (runtime version, with table lookaside for small d) */
#if DECDPUN==8
#define D2U(d) ((unsigned)((d)<=DECMAXD2U?d2utable[d]:((d)+7)>>3))
#elif DECDPUN==4
#define D2U(d) ((unsigned)((d)<=DECMAXD2U?d2utable[d]:((d)+3)>>2))
#else
#define D2U(d) ((d)<=DECMAXD2U?d2utable[d]:((d)+DECDPUN-1)/DECDPUN)
#endif
/* SD2U -- static D2U macro (for compile-time calculation) */
#define SD2U(d) (((d)+DECDPUN-1)/DECDPUN)
/* MSUDIGITS -- returns digits in msu, from digits, calculated */
/* using D2U */
#define MSUDIGITS(d) ((d)-(D2U(d)-1)*DECDPUN)
/* D2N -- return the number of decNumber structs that would be */
/* needed to contain that number of digits (and the initial */
/* decNumber struct) safely. Note that one Unit is included in the */
/* initial structure. Used for allocating space that is aligned on */
/* a decNumber struct boundary. */
#define D2N(d) \
((((SD2U(d)-1)*sizeof(Unit))+sizeof(decNumber)*2-1)/sizeof(decNumber))
/* TODIGIT -- macro to remove the leading digit from the unsigned */
/* integer u at column cut (counting from the right, LSD=0) and */
/* place it as an ASCII character into the character pointed to by */
/* c. Note that cut must be <= 9, and the maximum value for u is */
/* 2,000,000,000 (as is needed for negative exponents of */
/* subnormals). The unsigned integer pow is used as a temporary */
/* variable. */
#define TODIGIT(u, cut, c, pow) { \
*(c)='0'; \
pow=DECPOWERS[cut]*2; \
if ((u)>pow) { \
pow*=4; \
if ((u)>=pow) {(u)-=pow; *(c)+=8;} \
pow/=2; \
if ((u)>=pow) {(u)-=pow; *(c)+=4;} \
pow/=2; \
} \
if ((u)>=pow) {(u)-=pow; *(c)+=2;} \
pow/=2; \
if ((u)>=pow) {(u)-=pow; *(c)+=1;} \
}
/* ---------------------------------------------------------------- */
/* Definitions for fixed-precision modules (only valid after */
/* decSingle.h, decDouble.h, or decQuad.h has been included) */
/* ---------------------------------------------------------------- */
/* bcdnum -- a structure describing a format-independent finite */
/* number, whose coefficient is a string of bcd8 uBytes */
typedef struct {
uByte *msd; /* -> most significant digit */
uByte *lsd; /* -> least ditto */
uInt sign; /* 0=positive, DECFLOAT_Sign=negative */
Int exponent; /* Unadjusted signed exponent (q), or */
/* DECFLOAT_NaN etc. for a special */
} bcdnum;
/* Test if exponent or bcdnum exponent must be a special, etc. */
#define EXPISSPECIAL(exp) ((exp)>=DECFLOAT_MinSp)
#define EXPISINF(exp) (exp==DECFLOAT_Inf)
#define EXPISNAN(exp) (exp==DECFLOAT_qNaN || exp==DECFLOAT_sNaN)
#define NUMISSPECIAL(num) (EXPISSPECIAL((num)->exponent))
/* Refer to a 32-bit word or byte in a decFloat (df) by big-endian */
/* (array) notation (the 0 word or byte contains the sign bit), */
/* automatically adjusting for endianness; similarly address a word */
/* in the next-wider format (decFloatWider, or dfw) */
#define DECWORDS (DECBYTES/4)
#define DECWWORDS (DECWBYTES/4)
#if DECLITEND
#define DFBYTE(df, off) ((df)->bytes[DECBYTES-1-(off)])
#define DFWORD(df, off) ((df)->words[DECWORDS-1-(off)])
#define DFWWORD(dfw, off) ((dfw)->words[DECWWORDS-1-(off)])
#else
#define DFBYTE(df, off) ((df)->bytes[off])
#define DFWORD(df, off) ((df)->words[off])
#define DFWWORD(dfw, off) ((dfw)->words[off])
#endif
/* Tests for sign or specials, directly on DECFLOATs */
#define DFISSIGNED(df) ((DFWORD(df, 0)&0x80000000)!=0)
#define DFISSPECIAL(df) ((DFWORD(df, 0)&0x78000000)==0x78000000)
#define DFISINF(df) ((DFWORD(df, 0)&0x7c000000)==0x78000000)
#define DFISNAN(df) ((DFWORD(df, 0)&0x7c000000)==0x7c000000)
#define DFISQNAN(df) ((DFWORD(df, 0)&0x7e000000)==0x7c000000)
#define DFISSNAN(df) ((DFWORD(df, 0)&0x7e000000)==0x7e000000)
/* Shared lookup tables */
extern const uInt DECCOMBMSD[64]; /* Combination field -> MSD */
extern const uInt DECCOMBFROM[48]; /* exp+msd -> Combination */
/* Private generic (utility) routine */
#if DECCHECK || DECTRACE
extern void decShowNum(const bcdnum *, const char *);
#endif
/* Format-dependent macros and constants */
#if defined(DECPMAX)
/* Useful constants */
#define DECPMAX9 (ROUNDUP(DECPMAX, 9)/9) /* 'Pmax' in 10**9s */
/* Top words for a zero */
#define SINGLEZERO 0x22500000
#define DOUBLEZERO 0x22380000
#define QUADZERO 0x22080000
/* [ZEROWORD is defined to be one of these in the DFISZERO macro] */
/* Format-dependent common tests: */
/* DFISZERO -- test for (any) zero */
/* DFISCCZERO -- test for coefficient continuation being zero */
/* DFISCC01 -- test for coefficient contains only 0s and 1s */
/* DFISINT -- test for finite and exponent q=0 */
/* DFISUINT01 -- test for sign=0, finite, exponent q=0, and */
/* MSD=0 or 1 */
/* ZEROWORD is also defined here. */
/* */
/* In DFISZERO the first test checks the least-significant word */
/* (most likely to be non-zero); the penultimate tests MSD and */
/* DPDs in the signword, and the final test excludes specials and */
/* MSD>7. DFISINT similarly has to allow for the two forms of */
/* MSD codes. DFISUINT01 only has to allow for one form of MSD */
/* code. */
#if DECPMAX==7
#define ZEROWORD SINGLEZERO
/* [test macros not needed except for Zero] */
#define DFISZERO(df) ((DFWORD(df, 0)&0x1c0fffff)==0 \
&& (DFWORD(df, 0)&0x60000000)!=0x60000000)
#elif DECPMAX==16
#define ZEROWORD DOUBLEZERO
#define DFISZERO(df) ((DFWORD(df, 1)==0 \
&& (DFWORD(df, 0)&0x1c03ffff)==0 \
&& (DFWORD(df, 0)&0x60000000)!=0x60000000))
#define DFISINT(df) ((DFWORD(df, 0)&0x63fc0000)==0x22380000 \
||(DFWORD(df, 0)&0x7bfc0000)==0x6a380000)
#define DFISUINT01(df) ((DFWORD(df, 0)&0xfbfc0000)==0x22380000)
#define DFISCCZERO(df) (DFWORD(df, 1)==0 \
&& (DFWORD(df, 0)&0x0003ffff)==0)
#define DFISCC01(df) ((DFWORD(df, 0)&~0xfffc9124)==0 \
&& (DFWORD(df, 1)&~0x49124491)==0)
#elif DECPMAX==34
#define ZEROWORD QUADZERO
#define DFISZERO(df) ((DFWORD(df, 3)==0 \
&& DFWORD(df, 2)==0 \
&& DFWORD(df, 1)==0 \
&& (DFWORD(df, 0)&0x1c003fff)==0 \
&& (DFWORD(df, 0)&0x60000000)!=0x60000000))
#define DFISINT(df) ((DFWORD(df, 0)&0x63ffc000)==0x22080000 \
||(DFWORD(df, 0)&0x7bffc000)==0x6a080000)
#define DFISUINT01(df) ((DFWORD(df, 0)&0xfbffc000)==0x22080000)
#define DFISCCZERO(df) (DFWORD(df, 3)==0 \
&& DFWORD(df, 2)==0 \
&& DFWORD(df, 1)==0 \
&& (DFWORD(df, 0)&0x00003fff)==0)
#define DFISCC01(df) ((DFWORD(df, 0)&~0xffffc912)==0 \
&& (DFWORD(df, 1)&~0x44912449)==0 \
&& (DFWORD(df, 2)&~0x12449124)==0 \
&& (DFWORD(df, 3)&~0x49124491)==0)
#endif
/* Macros to test if a certain 10 bits of a uInt or pair of uInts */
/* are a canonical declet [higher or lower bits are ignored]. */
/* declet is at offset 0 (from the right) in a uInt: */
#define CANONDPD(dpd) (((dpd)&0x300)==0 || ((dpd)&0x6e)!=0x6e)
/* declet is at offset k (a multiple of 2) in a uInt: */
#define CANONDPDOFF(dpd, k) (((dpd)&(0x300<<(k)))==0 \
|| ((dpd)&(((uInt)0x6e)<<(k)))!=(((uInt)0x6e)<<(k)))
/* declet is at offset k (a multiple of 2) in a pair of uInts: */
/* [the top 2 bits will always be in the more-significant uInt] */
#define CANONDPDTWO(hi, lo, k) (((hi)&(0x300>>(32-(k))))==0 \
|| ((hi)&(0x6e>>(32-(k))))!=(0x6e>>(32-(k))) \
|| ((lo)&(((uInt)0x6e)<<(k)))!=(((uInt)0x6e)<<(k)))
/* Macro to test whether a full-length (length DECPMAX) BCD8 */
/* coefficient, starting at uByte u, is all zeros */
/* Test just the LSWord first, then the remainder as a sequence */
/* of tests in order to avoid same-level use of UBTOUI */
#if DECPMAX==7
#define ISCOEFFZERO(u) ( \
UBTOUI((u)+DECPMAX-4)==0 \
&& UBTOUS((u)+DECPMAX-6)==0 \
&& *(u)==0)
#elif DECPMAX==16
#define ISCOEFFZERO(u) ( \
UBTOUI((u)+DECPMAX-4)==0 \
&& UBTOUI((u)+DECPMAX-8)==0 \
&& UBTOUI((u)+DECPMAX-12)==0 \
&& UBTOUI(u)==0)
#elif DECPMAX==34
#define ISCOEFFZERO(u) ( \
UBTOUI((u)+DECPMAX-4)==0 \
&& UBTOUI((u)+DECPMAX-8)==0 \
&& UBTOUI((u)+DECPMAX-12)==0 \
&& UBTOUI((u)+DECPMAX-16)==0 \
&& UBTOUI((u)+DECPMAX-20)==0 \
&& UBTOUI((u)+DECPMAX-24)==0 \
&& UBTOUI((u)+DECPMAX-28)==0 \
&& UBTOUI((u)+DECPMAX-32)==0 \
&& UBTOUS(u)==0)
#endif
/* Macros and masks for the sign, exponent continuation, and MSD */
/* Get the sign as DECFLOAT_Sign or 0 */
#define GETSIGN(df) (DFWORD(df, 0)&0x80000000)
/* Get the exponent continuation from a decFloat *df as an Int */
#define GETECON(df) ((Int)((DFWORD((df), 0)&0x03ffffff)>>(32-6-DECECONL)))
/* Ditto, from the next-wider format */
#define GETWECON(df) ((Int)((DFWWORD((df), 0)&0x03ffffff)>>(32-6-DECWECONL)))
/* Get the biased exponent similarly */
#define GETEXP(df) ((Int)(DECCOMBEXP[DFWORD((df), 0)>>26]+GETECON(df)))
/* Get the unbiased exponent similarly */
#define GETEXPUN(df) ((Int)GETEXP(df)-DECBIAS)
/* Get the MSD similarly (as uInt) */
#define GETMSD(df) (DECCOMBMSD[DFWORD((df), 0)>>26])
/* Compile-time computes of the exponent continuation field masks */
/* full exponent continuation field: */
#define ECONMASK ((0x03ffffff>>(32-6-DECECONL))<<(32-6-DECECONL))
/* same, not including its first digit (the qNaN/sNaN selector): */
#define ECONNANMASK ((0x01ffffff>>(32-6-DECECONL))<<(32-6-DECECONL))
/* Macros to decode the coefficient in a finite decFloat *df into */
/* a BCD string (uByte *bcdin) of length DECPMAX uBytes. */
/* In-line sequence to convert least significant 10 bits of uInt */
/* dpd to three BCD8 digits starting at uByte u. Note that an */
/* extra byte is written to the right of the three digits because */
/* four bytes are moved at a time for speed; the alternative */
/* macro moves exactly three bytes (usually slower). */
#define dpd2bcd8(u, dpd) memcpy(u, &DPD2BCD8[((dpd)&0x3ff)*4], 4)
#define dpd2bcd83(u, dpd) memcpy(u, &DPD2BCD8[((dpd)&0x3ff)*4], 3)
/* Decode the declets. After extracting each one, it is decoded */
/* to BCD8 using a table lookup (also used for variable-length */
/* decode). Each DPD decode is 3 bytes BCD8 plus a one-byte */
/* length which is not used, here). Fixed-length 4-byte moves */
/* are fast, however, almost everywhere, and so are used except */
/* for the final three bytes (to avoid overrun). The code below */
/* is 36 instructions for Doubles and about 70 for Quads, even */
/* on IA32. */
/* Two macros are defined for each format: */
/* GETCOEFF extracts the coefficient of the current format */
/* GETWCOEFF extracts the coefficient of the next-wider format. */
/* The latter is a copy of the next-wider GETCOEFF using DFWWORD. */
#if DECPMAX==7
#define GETCOEFF(df, bcd) { \
uInt sourhi=DFWORD(df, 0); \
*(bcd)=(uByte)DECCOMBMSD[sourhi>>26]; \
dpd2bcd8(bcd+1, sourhi>>10); \
dpd2bcd83(bcd+4, sourhi);}
#define GETWCOEFF(df, bcd) { \
uInt sourhi=DFWWORD(df, 0); \
uInt sourlo=DFWWORD(df, 1); \
*(bcd)=(uByte)DECCOMBMSD[sourhi>>26]; \
dpd2bcd8(bcd+1, sourhi>>8); \
dpd2bcd8(bcd+4, (sourhi<<2) | (sourlo>>30)); \
dpd2bcd8(bcd+7, sourlo>>20); \
dpd2bcd8(bcd+10, sourlo>>10); \
dpd2bcd83(bcd+13, sourlo);}
#elif DECPMAX==16
#define GETCOEFF(df, bcd) { \
uInt sourhi=DFWORD(df, 0); \
uInt sourlo=DFWORD(df, 1); \
*(bcd)=(uByte)DECCOMBMSD[sourhi>>26]; \
dpd2bcd8(bcd+1, sourhi>>8); \
dpd2bcd8(bcd+4, (sourhi<<2) | (sourlo>>30)); \
dpd2bcd8(bcd+7, sourlo>>20); \
dpd2bcd8(bcd+10, sourlo>>10); \
dpd2bcd83(bcd+13, sourlo);}
#define GETWCOEFF(df, bcd) { \
uInt sourhi=DFWWORD(df, 0); \
uInt sourmh=DFWWORD(df, 1); \
uInt sourml=DFWWORD(df, 2); \
uInt sourlo=DFWWORD(df, 3); \
*(bcd)=(uByte)DECCOMBMSD[sourhi>>26]; \
dpd2bcd8(bcd+1, sourhi>>4); \
dpd2bcd8(bcd+4, ((sourhi)<<6) | (sourmh>>26)); \
dpd2bcd8(bcd+7, sourmh>>16); \
dpd2bcd8(bcd+10, sourmh>>6); \
dpd2bcd8(bcd+13, ((sourmh)<<4) | (sourml>>28)); \
dpd2bcd8(bcd+16, sourml>>18); \
dpd2bcd8(bcd+19, sourml>>8); \
dpd2bcd8(bcd+22, ((sourml)<<2) | (sourlo>>30)); \
dpd2bcd8(bcd+25, sourlo>>20); \
dpd2bcd8(bcd+28, sourlo>>10); \
dpd2bcd83(bcd+31, sourlo);}
#elif DECPMAX==34
#define GETCOEFF(df, bcd) { \
uInt sourhi=DFWORD(df, 0); \
uInt sourmh=DFWORD(df, 1); \
uInt sourml=DFWORD(df, 2); \
uInt sourlo=DFWORD(df, 3); \
*(bcd)=(uByte)DECCOMBMSD[sourhi>>26]; \
dpd2bcd8(bcd+1, sourhi>>4); \
dpd2bcd8(bcd+4, ((sourhi)<<6) | (sourmh>>26)); \
dpd2bcd8(bcd+7, sourmh>>16); \
dpd2bcd8(bcd+10, sourmh>>6); \
dpd2bcd8(bcd+13, ((sourmh)<<4) | (sourml>>28)); \
dpd2bcd8(bcd+16, sourml>>18); \
dpd2bcd8(bcd+19, sourml>>8); \
dpd2bcd8(bcd+22, ((sourml)<<2) | (sourlo>>30)); \
dpd2bcd8(bcd+25, sourlo>>20); \
dpd2bcd8(bcd+28, sourlo>>10); \
dpd2bcd83(bcd+31, sourlo);}
#define GETWCOEFF(df, bcd) {??} /* [should never be used] */
#endif
/* Macros to decode the coefficient in a finite decFloat *df into */
/* a base-billion uInt array, with the least-significant */
/* 0-999999999 'digit' at offset 0. */
/* Decode the declets. After extracting each one, it is decoded */
/* to binary using a table lookup. Three tables are used; one */
/* the usual DPD to binary, the other two pre-multiplied by 1000 */
/* and 1000000 to avoid multiplication during decode. These */
/* tables can also be used for multiplying up the MSD as the DPD */
/* code for 0 through 9 is the identity. */
#define DPD2BIN0 DPD2BIN /* for prettier code */
#if DECPMAX==7
#define GETCOEFFBILL(df, buf) { \
uInt sourhi=DFWORD(df, 0); \
(buf)[0]=DPD2BIN0[sourhi&0x3ff] \
+DPD2BINK[(sourhi>>10)&0x3ff] \
+DPD2BINM[DECCOMBMSD[sourhi>>26]];}
#elif DECPMAX==16
#define GETCOEFFBILL(df, buf) { \
uInt sourhi, sourlo; \
sourlo=DFWORD(df, 1); \
(buf)[0]=DPD2BIN0[sourlo&0x3ff] \
+DPD2BINK[(sourlo>>10)&0x3ff] \
+DPD2BINM[(sourlo>>20)&0x3ff]; \
sourhi=DFWORD(df, 0); \
(buf)[1]=DPD2BIN0[((sourhi<<2) | (sourlo>>30))&0x3ff] \
+DPD2BINK[(sourhi>>8)&0x3ff] \
+DPD2BINM[DECCOMBMSD[sourhi>>26]];}
#elif DECPMAX==34
#define GETCOEFFBILL(df, buf) { \
uInt sourhi, sourmh, sourml, sourlo; \
sourlo=DFWORD(df, 3); \
(buf)[0]=DPD2BIN0[sourlo&0x3ff] \
+DPD2BINK[(sourlo>>10)&0x3ff] \
+DPD2BINM[(sourlo>>20)&0x3ff]; \
sourml=DFWORD(df, 2); \
(buf)[1]=DPD2BIN0[((sourml<<2) | (sourlo>>30))&0x3ff] \
+DPD2BINK[(sourml>>8)&0x3ff] \
+DPD2BINM[(sourml>>18)&0x3ff]; \
sourmh=DFWORD(df, 1); \
(buf)[2]=DPD2BIN0[((sourmh<<4) | (sourml>>28))&0x3ff] \
+DPD2BINK[(sourmh>>6)&0x3ff] \
+DPD2BINM[(sourmh>>16)&0x3ff]; \
sourhi=DFWORD(df, 0); \
(buf)[3]=DPD2BIN0[((sourhi<<6) | (sourmh>>26))&0x3ff] \
+DPD2BINK[(sourhi>>4)&0x3ff] \
+DPD2BINM[DECCOMBMSD[sourhi>>26]];}
#endif
/* Macros to decode the coefficient in a finite decFloat *df into */
/* a base-thousand uInt array (of size DECLETS+1, to allow for */
/* the MSD), with the least-significant 0-999 'digit' at offset 0.*/
/* Decode the declets. After extracting each one, it is decoded */
/* to binary using a table lookup. */
#if DECPMAX==7
#define GETCOEFFTHOU(df, buf) { \
uInt sourhi=DFWORD(df, 0); \
(buf)[0]=DPD2BIN[sourhi&0x3ff]; \
(buf)[1]=DPD2BIN[(sourhi>>10)&0x3ff]; \
(buf)[2]=DECCOMBMSD[sourhi>>26];}
#elif DECPMAX==16
#define GETCOEFFTHOU(df, buf) { \
uInt sourhi, sourlo; \
sourlo=DFWORD(df, 1); \
(buf)[0]=DPD2BIN[sourlo&0x3ff]; \
(buf)[1]=DPD2BIN[(sourlo>>10)&0x3ff]; \
(buf)[2]=DPD2BIN[(sourlo>>20)&0x3ff]; \
sourhi=DFWORD(df, 0); \
(buf)[3]=DPD2BIN[((sourhi<<2) | (sourlo>>30))&0x3ff]; \
(buf)[4]=DPD2BIN[(sourhi>>8)&0x3ff]; \
(buf)[5]=DECCOMBMSD[sourhi>>26];}
#elif DECPMAX==34
#define GETCOEFFTHOU(df, buf) { \
uInt sourhi, sourmh, sourml, sourlo; \
sourlo=DFWORD(df, 3); \
(buf)[0]=DPD2BIN[sourlo&0x3ff]; \
(buf)[1]=DPD2BIN[(sourlo>>10)&0x3ff]; \
(buf)[2]=DPD2BIN[(sourlo>>20)&0x3ff]; \
sourml=DFWORD(df, 2); \
(buf)[3]=DPD2BIN[((sourml<<2) | (sourlo>>30))&0x3ff]; \
(buf)[4]=DPD2BIN[(sourml>>8)&0x3ff]; \
(buf)[5]=DPD2BIN[(sourml>>18)&0x3ff]; \
sourmh=DFWORD(df, 1); \
(buf)[6]=DPD2BIN[((sourmh<<4) | (sourml>>28))&0x3ff]; \
(buf)[7]=DPD2BIN[(sourmh>>6)&0x3ff]; \
(buf)[8]=DPD2BIN[(sourmh>>16)&0x3ff]; \
sourhi=DFWORD(df, 0); \
(buf)[9]=DPD2BIN[((sourhi<<6) | (sourmh>>26))&0x3ff]; \
(buf)[10]=DPD2BIN[(sourhi>>4)&0x3ff]; \
(buf)[11]=DECCOMBMSD[sourhi>>26];}
#endif
/* Macros to decode the coefficient in a finite decFloat *df and */
/* add to a base-thousand uInt array (as for GETCOEFFTHOU). */
/* After the addition then most significant 'digit' in the array */
/* might have a value larger then 10 (with a maximum of 19). */
#if DECPMAX==7
#define ADDCOEFFTHOU(df, buf) { \
uInt sourhi=DFWORD(df, 0); \
(buf)[0]+=DPD2BIN[sourhi&0x3ff]; \
if (buf[0]>999) {buf[0]-=1000; buf[1]++;} \
(buf)[1]+=DPD2BIN[(sourhi>>10)&0x3ff]; \
if (buf[1]>999) {buf[1]-=1000; buf[2]++;} \
(buf)[2]+=DECCOMBMSD[sourhi>>26];}
#elif DECPMAX==16
#define ADDCOEFFTHOU(df, buf) { \
uInt sourhi, sourlo; \
sourlo=DFWORD(df, 1); \
(buf)[0]+=DPD2BIN[sourlo&0x3ff]; \
if (buf[0]>999) {buf[0]-=1000; buf[1]++;} \
(buf)[1]+=DPD2BIN[(sourlo>>10)&0x3ff]; \
if (buf[1]>999) {buf[1]-=1000; buf[2]++;} \
(buf)[2]+=DPD2BIN[(sourlo>>20)&0x3ff]; \
if (buf[2]>999) {buf[2]-=1000; buf[3]++;} \
sourhi=DFWORD(df, 0); \
(buf)[3]+=DPD2BIN[((sourhi<<2) | (sourlo>>30))&0x3ff]; \
if (buf[3]>999) {buf[3]-=1000; buf[4]++;} \
(buf)[4]+=DPD2BIN[(sourhi>>8)&0x3ff]; \
if (buf[4]>999) {buf[4]-=1000; buf[5]++;} \
(buf)[5]+=DECCOMBMSD[sourhi>>26];}
#elif DECPMAX==34
#define ADDCOEFFTHOU(df, buf) { \
uInt sourhi, sourmh, sourml, sourlo; \
sourlo=DFWORD(df, 3); \
(buf)[0]+=DPD2BIN[sourlo&0x3ff]; \
if (buf[0]>999) {buf[0]-=1000; buf[1]++;} \
(buf)[1]+=DPD2BIN[(sourlo>>10)&0x3ff]; \
if (buf[1]>999) {buf[1]-=1000; buf[2]++;} \
(buf)[2]+=DPD2BIN[(sourlo>>20)&0x3ff]; \
if (buf[2]>999) {buf[2]-=1000; buf[3]++;} \
sourml=DFWORD(df, 2); \
(buf)[3]+=DPD2BIN[((sourml<<2) | (sourlo>>30))&0x3ff]; \
if (buf[3]>999) {buf[3]-=1000; buf[4]++;} \
(buf)[4]+=DPD2BIN[(sourml>>8)&0x3ff]; \
if (buf[4]>999) {buf[4]-=1000; buf[5]++;} \
(buf)[5]+=DPD2BIN[(sourml>>18)&0x3ff]; \
if (buf[5]>999) {buf[5]-=1000; buf[6]++;} \
sourmh=DFWORD(df, 1); \
(buf)[6]+=DPD2BIN[((sourmh<<4) | (sourml>>28))&0x3ff]; \
if (buf[6]>999) {buf[6]-=1000; buf[7]++;} \
(buf)[7]+=DPD2BIN[(sourmh>>6)&0x3ff]; \
if (buf[7]>999) {buf[7]-=1000; buf[8]++;} \
(buf)[8]+=DPD2BIN[(sourmh>>16)&0x3ff]; \
if (buf[8]>999) {buf[8]-=1000; buf[9]++;} \
sourhi=DFWORD(df, 0); \
(buf)[9]+=DPD2BIN[((sourhi<<6) | (sourmh>>26))&0x3ff]; \
if (buf[9]>999) {buf[9]-=1000; buf[10]++;} \
(buf)[10]+=DPD2BIN[(sourhi>>4)&0x3ff]; \
if (buf[10]>999) {buf[10]-=1000; buf[11]++;} \
(buf)[11]+=DECCOMBMSD[sourhi>>26];}
#endif
/* Set a decFloat to the maximum positive finite number (Nmax) */
#if DECPMAX==7
#define DFSETNMAX(df) \
{DFWORD(df, 0)=0x77f3fcff;}
#elif DECPMAX==16
#define DFSETNMAX(df) \
{DFWORD(df, 0)=0x77fcff3f; \
DFWORD(df, 1)=0xcff3fcff;}
#elif DECPMAX==34
#define DFSETNMAX(df) \
{DFWORD(df, 0)=0x77ffcff3; \
DFWORD(df, 1)=0xfcff3fcf; \
DFWORD(df, 2)=0xf3fcff3f; \
DFWORD(df, 3)=0xcff3fcff;}
#endif
/* [end of format-dependent macros and constants] */
#endif
#else
#error decNumberLocal included more than once
#endif

220
extern/decNumber/decPacked.c vendored Normal file
View File

@ -0,0 +1,220 @@
/* ------------------------------------------------------------------ */
/* Packed Decimal conversion module */
/* ------------------------------------------------------------------ */
/* Copyright (c) IBM Corporation, 2000, 2002. All rights reserved. */
/* */
/* This software is made available under the terms of the */
/* ICU License -- ICU 1.8.1 and later. */
/* */
/* The description and User's Guide ("The decNumber C Library") for */
/* this software is called decNumber.pdf. This document is */
/* available, together with arithmetic and format specifications, */
/* testcases, and Web links, on the General Decimal Arithmetic page. */
/* */
/* Please send comments, suggestions, and corrections to the author: */
/* mfc@uk.ibm.com */
/* Mike Cowlishaw, IBM Fellow */
/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */
/* ------------------------------------------------------------------ */
/* This module comprises the routines for Packed Decimal format */
/* numbers. Conversions are supplied to and from decNumber, which in */
/* turn supports: */
/* conversions to and from string */
/* arithmetic routines */
/* utilities. */
/* Conversions from decNumber to and from densely packed decimal */
/* formats are provided by the decimal32 through decimal128 modules. */
/* ------------------------------------------------------------------ */
#include <string.h> // for NULL
#include "decNumber.h" // base number library
#include "decPacked.h" // packed decimal
#include "decNumberLocal.h" // decNumber local types, etc.
/* ------------------------------------------------------------------ */
/* decPackedFromNumber -- convert decNumber to BCD Packed Decimal */
/* */
/* bcd is the BCD bytes */
/* length is the length of the BCD array */
/* scale is the scale result */
/* dn is the decNumber */
/* returns bcd, or NULL if error */
/* */
/* The number is converted to a BCD packed decimal byte array, */
/* right aligned in the bcd array, whose length is indicated by the */
/* second parameter. The final 4-bit nibble in the array will be a */
/* sign nibble, C (1100) for + and D (1101) for -. Unused bytes and */
/* nibbles to the left of the number are set to 0. */
/* */
/* scale is set to the scale of the number (this is the exponent, */
/* negated). To force the number to a specified scale, first use the */
/* decNumberRescale routine, which will round and change the exponent */
/* as necessary. */
/* */
/* If there is an error (that is, the decNumber has too many digits */
/* to fit in length bytes, or it is a NaN or Infinity), NULL is */
/* returned and the bcd and scale results are unchanged. Otherwise */
/* bcd is returned. */
/* ------------------------------------------------------------------ */
uByte * decPackedFromNumber(uByte *bcd, Int length, Int *scale,
const decNumber *dn) {
const Unit *up=dn->lsu; // Unit array pointer
uByte obyte, *out; // current output byte, and where it goes
Int indigs=dn->digits; // digits processed
uInt cut=DECDPUN; // downcounter per Unit
uInt u=*up; // work
uInt nib; // ..
#if DECDPUN<=4
uInt temp; // ..
#endif
if (dn->digits>length*2-1 // too long ..
||(dn->bits & DECSPECIAL)) return NULL; // .. or special -- hopeless
if (dn->bits&DECNEG) obyte=DECPMINUS; // set the sign ..
else obyte=DECPPLUS;
*scale=-dn->exponent; // .. and scale
// loop from lowest (rightmost) byte
out=bcd+length-1; // -> final byte
for (; out>=bcd; out--) {
if (indigs>0) {
if (cut==0) {
up++;
u=*up;
cut=DECDPUN;
}
#if DECDPUN<=4
temp=(u*6554)>>16; // fast /10
nib=u-X10(temp);
u=temp;
#else
nib=u%10; // cannot use *6554 trick :-(
u=u/10;
#endif
obyte|=(nib<<4);
indigs--;
cut--;
}
*out=obyte;
obyte=0; // assume 0
if (indigs>0) {
if (cut==0) {
up++;
u=*up;
cut=DECDPUN;
}
#if DECDPUN<=4
temp=(u*6554)>>16; // as above
obyte=(uByte)(u-X10(temp));
u=temp;
#else
obyte=(uByte)(u%10);
u=u/10;
#endif
indigs--;
cut--;
}
} // loop
return bcd;
} // decPackedFromNumber
/* ------------------------------------------------------------------ */
/* decPackedToNumber -- convert BCD Packed Decimal to a decNumber */
/* */
/* bcd is the BCD bytes */
/* length is the length of the BCD array */
/* scale is the scale associated with the BCD integer */
/* dn is the decNumber [with space for length*2 digits] */
/* returns dn, or NULL if error */
/* */
/* The BCD packed decimal byte array, together with an associated */
/* scale, is converted to a decNumber. The BCD array is assumed full */
/* of digits, and must be ended by a 4-bit sign nibble in the least */
/* significant four bits of the final byte. */
/* */
/* The scale is used (negated) as the exponent of the decNumber. */
/* Note that zeros may have a sign and/or a scale. */
/* */
/* The decNumber structure is assumed to have sufficient space to */
/* hold the converted number (that is, up to length*2-1 digits), so */
/* no error is possible unless the adjusted exponent is out of range, */
/* no sign nibble was found, or a sign nibble was found before the */
/* final nibble. In these error cases, NULL is returned and the */
/* decNumber will be 0. */
/* ------------------------------------------------------------------ */
decNumber * decPackedToNumber(const uByte *bcd, Int length,
const Int *scale, decNumber *dn) {
const uByte *last=bcd+length-1; // -> last byte
const uByte *first; // -> first non-zero byte
uInt nib; // work nibble
Unit *up=dn->lsu; // output pointer
Int digits; // digits count
Int cut=0; // phase of output
decNumberZero(dn); // default result
last=&bcd[length-1];
nib=*last & 0x0f; // get the sign
if (nib==DECPMINUS || nib==DECPMINUSALT) dn->bits=DECNEG;
else if (nib<=9) return NULL; // not a sign nibble
// skip leading zero bytes [final byte is always non-zero, due to sign]
for (first=bcd; *first==0;) first++;
digits=(last-first)*2+1; // calculate digits ..
if ((*first & 0xf0)==0) digits--; // adjust for leading zero nibble
if (digits!=0) dn->digits=digits; // count of actual digits [if 0,
// leave as 1]
// check the adjusted exponent; note that scale could be unbounded
dn->exponent=-*scale; // set the exponent
if (*scale>=0) { // usual case
if ((dn->digits-*scale-1)<-DECNUMMAXE) { // underflow
decNumberZero(dn);
return NULL;}
}
else { // -ve scale; +ve exponent
// need to be careful to avoid wrap, here, also BADINT case
if ((*scale<-DECNUMMAXE) // overflow even without digits
|| ((dn->digits-*scale-1)>DECNUMMAXE)) { // overflow
decNumberZero(dn);
return NULL;}
}
if (digits==0) return dn; // result was zero
// copy the digits to the number's units, starting at the lsu
// [unrolled]
for (;;) { // forever
// left nibble first
nib=(unsigned)(*last & 0xf0)>>4;
// got a digit, in nib
if (nib>9) {decNumberZero(dn); return NULL;}
if (cut==0) *up=(Unit)nib;
else *up=(Unit)(*up+nib*DECPOWERS[cut]);
digits--;
if (digits==0) break; // got them all
cut++;
if (cut==DECDPUN) {
up++;
cut=0;
}
last--; // ready for next
nib=*last & 0x0f; // get right nibble
if (nib>9) {decNumberZero(dn); return NULL;}
// got a digit, in nib
if (cut==0) *up=(Unit)nib;
else *up=(Unit)(*up+nib*DECPOWERS[cut]);
digits--;
if (digits==0) break; // got them all
cut++;
if (cut==DECDPUN) {
up++;
cut=0;
}
} // forever
return dn;
} // decPackedToNumber

52
extern/decNumber/decPacked.h vendored Normal file
View File

@ -0,0 +1,52 @@
/* ------------------------------------------------------------------ */
/* Packed Decimal conversion module header */
/* ------------------------------------------------------------------ */
/* Copyright (c) IBM Corporation, 2000, 2005. All rights reserved. */
/* */
/* This software is made available under the terms of the */
/* ICU License -- ICU 1.8.1 and later. */
/* */
/* The description and User's Guide ("The decNumber C Library") for */
/* this software is called decNumber.pdf. This document is */
/* available, together with arithmetic and format specifications, */
/* testcases, and Web links, on the General Decimal Arithmetic page. */
/* */
/* Please send comments, suggestions, and corrections to the author: */
/* mfc@uk.ibm.com */
/* Mike Cowlishaw, IBM Fellow */
/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */
/* ------------------------------------------------------------------ */
#if !defined(DECPACKED)
#define DECPACKED
#define DECPNAME "decPacked" /* Short name */
#define DECPFULLNAME "Packed Decimal conversions" /* Verbose name */
#define DECPAUTHOR "Mike Cowlishaw" /* Who to blame */
#define DECPACKED_DefP 32 /* default precision */
#ifndef DECNUMDIGITS
#define DECNUMDIGITS DECPACKED_DefP /* size if not already defined*/
#endif
#include "decNumber.h" /* context and number library */
/* Sign nibble constants */
#if !defined(DECPPLUSALT)
#define DECPPLUSALT 0x0A /* alternate plus nibble */
#define DECPMINUSALT 0x0B /* alternate minus nibble */
#define DECPPLUS 0x0C /* preferred plus nibble */
#define DECPMINUS 0x0D /* preferred minus nibble */
#define DECPPLUSALT2 0x0E /* alternate plus nibble */
#define DECPUNSIGNED 0x0F /* alternate plus nibble (unsigned) */
#endif
/* ---------------------------------------------------------------- */
/* decPacked public routines */
/* ---------------------------------------------------------------- */
/* Conversions */
uint8_t * decPackedFromNumber(uint8_t *, int32_t, int32_t *,
const decNumber *);
decNumber * decPackedToNumber(const uint8_t *, int32_t, const int32_t *,
decNumber *);
#endif

135
extern/decNumber/decQuad.c vendored Normal file
View File

@ -0,0 +1,135 @@
/* ------------------------------------------------------------------ */
/* decQuad.c -- decQuad operations module */
/* ------------------------------------------------------------------ */
/* Copyright (c) IBM Corporation, 2000, 2010. All rights reserved. */
/* */
/* This software is made available under the terms of the */
/* ICU License -- ICU 1.8.1 and later. */
/* */
/* The description and User's Guide ("The decNumber C Library") for */
/* this software is included in the package as decNumber.pdf. This */
/* document is also available in HTML, together with specifications, */
/* testcases, and Web links, on the General Decimal Arithmetic page. */
/* */
/* Please send comments, suggestions, and corrections to the author: */
/* mfc@uk.ibm.com */
/* Mike Cowlishaw, IBM Fellow */
/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */
/* ------------------------------------------------------------------ */
/* This module comprises decQuad operations (including conversions) */
/* ------------------------------------------------------------------ */
/* Constant mappings for shared code */
#define DECPMAX DECQUAD_Pmax
#define DECEMIN DECQUAD_Emin
#define DECEMAX DECQUAD_Emax
#define DECEMAXD DECQUAD_EmaxD
#define DECBYTES DECQUAD_Bytes
#define DECSTRING DECQUAD_String
#define DECECONL DECQUAD_EconL
#define DECBIAS DECQUAD_Bias
#define DECLETS DECQUAD_Declets
#define DECQTINY (-DECQUAD_Bias)
/* Type and function mappings for shared code */
#define decFloat decQuad // Type name
// Utilities and conversions (binary results, extractors, etc.)
#define decFloatFromBCD decQuadFromBCD
#define decFloatFromInt32 decQuadFromInt32
#define decFloatFromPacked decQuadFromPacked
#define decFloatFromPackedChecked decQuadFromPackedChecked
#define decFloatFromString decQuadFromString
#define decFloatFromUInt32 decQuadFromUInt32
#define decFloatFromWider decQuadFromWider
#define decFloatGetCoefficient decQuadGetCoefficient
#define decFloatGetExponent decQuadGetExponent
#define decFloatSetCoefficient decQuadSetCoefficient
#define decFloatSetExponent decQuadSetExponent
#define decFloatShow decQuadShow
#define decFloatToBCD decQuadToBCD
#define decFloatToEngString decQuadToEngString
#define decFloatToInt32 decQuadToInt32
#define decFloatToInt32Exact decQuadToInt32Exact
#define decFloatToPacked decQuadToPacked
#define decFloatToString decQuadToString
#define decFloatToUInt32 decQuadToUInt32
#define decFloatToUInt32Exact decQuadToUInt32Exact
#define decFloatToWider decQuadToWider
#define decFloatZero decQuadZero
// Computational (result is a decFloat)
#define decFloatAbs decQuadAbs
#define decFloatAdd decQuadAdd
#define decFloatAnd decQuadAnd
#define decFloatDivide decQuadDivide
#define decFloatDivideInteger decQuadDivideInteger
#define decFloatFMA decQuadFMA
#define decFloatInvert decQuadInvert
#define decFloatLogB decQuadLogB
#define decFloatMax decQuadMax
#define decFloatMaxMag decQuadMaxMag
#define decFloatMin decQuadMin
#define decFloatMinMag decQuadMinMag
#define decFloatMinus decQuadMinus
#define decFloatMultiply decQuadMultiply
#define decFloatNextMinus decQuadNextMinus
#define decFloatNextPlus decQuadNextPlus
#define decFloatNextToward decQuadNextToward
#define decFloatOr decQuadOr
#define decFloatPlus decQuadPlus
#define decFloatQuantize decQuadQuantize
#define decFloatReduce decQuadReduce
#define decFloatRemainder decQuadRemainder
#define decFloatRemainderNear decQuadRemainderNear
#define decFloatRotate decQuadRotate
#define decFloatScaleB decQuadScaleB
#define decFloatShift decQuadShift
#define decFloatSubtract decQuadSubtract
#define decFloatToIntegralValue decQuadToIntegralValue
#define decFloatToIntegralExact decQuadToIntegralExact
#define decFloatXor decQuadXor
// Comparisons
#define decFloatCompare decQuadCompare
#define decFloatCompareSignal decQuadCompareSignal
#define decFloatCompareTotal decQuadCompareTotal
#define decFloatCompareTotalMag decQuadCompareTotalMag
// Copies
#define decFloatCanonical decQuadCanonical
#define decFloatCopy decQuadCopy
#define decFloatCopyAbs decQuadCopyAbs
#define decFloatCopyNegate decQuadCopyNegate
#define decFloatCopySign decQuadCopySign
// Non-computational
#define decFloatClass decQuadClass
#define decFloatClassString decQuadClassString
#define decFloatDigits decQuadDigits
#define decFloatIsCanonical decQuadIsCanonical
#define decFloatIsFinite decQuadIsFinite
#define decFloatIsInfinite decQuadIsInfinite
#define decFloatIsInteger decQuadIsInteger
#define decFloatIsLogical decQuadIsLogical
#define decFloatIsNaN decQuadIsNaN
#define decFloatIsNegative decQuadIsNegative
#define decFloatIsNormal decQuadIsNormal
#define decFloatIsPositive decQuadIsPositive
#define decFloatIsSignaling decQuadIsSignaling
#define decFloatIsSignalling decQuadIsSignalling
#define decFloatIsSigned decQuadIsSigned
#define decFloatIsSubnormal decQuadIsSubnormal
#define decFloatIsZero decQuadIsZero
#define decFloatRadix decQuadRadix
#define decFloatSameQuantum decQuadSameQuantum
#define decFloatVersion decQuadVersion
/* And now the code itself */
#include "decContext.h" // public includes
#include "decQuad.h" // ..
#include "decNumberLocal.h" // local includes (need DECPMAX)
#include "decCommon.c" // non-arithmetic decFloat routines
#include "decBasic.c" // basic formats routines

177
extern/decNumber/decQuad.h vendored Normal file
View File

@ -0,0 +1,177 @@
/* ------------------------------------------------------------------ */
/* decQuad.h -- Decimal 128-bit format module header */
/* ------------------------------------------------------------------ */
/* Copyright (c) IBM Corporation, 2000, 2010. All rights reserved. */
/* */
/* This software is made available under the terms of the */
/* ICU License -- ICU 1.8.1 and later. */
/* */
/* The description and User's Guide ("The decNumber C Library") for */
/* this software is included in the package as decNumber.pdf. This */
/* document is also available in HTML, together with specifications, */
/* testcases, and Web links, on the General Decimal Arithmetic page. */
/* */
/* Please send comments, suggestions, and corrections to the author: */
/* mfc@uk.ibm.com */
/* Mike Cowlishaw, IBM Fellow */
/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */
/* ------------------------------------------------------------------ */
/* This include file is always included by decSingle and decDouble, */
/* and therefore also holds useful constants used by all three. */
#if !defined(DECQUAD)
#define DECQUAD
#define DECQUADNAME "decimalQuad" /* Short name */
#define DECQUADTITLE "Decimal 128-bit datum" /* Verbose name */
#define DECQUADAUTHOR "Mike Cowlishaw" /* Who to blame */
/* parameters for decQuads */
#define DECQUAD_Bytes 16 /* length */
#define DECQUAD_Pmax 34 /* maximum precision (digits) */
#define DECQUAD_Emin -6143 /* minimum adjusted exponent */
#define DECQUAD_Emax 6144 /* maximum adjusted exponent */
#define DECQUAD_EmaxD 4 /* maximum exponent digits */
#define DECQUAD_Bias 6176 /* bias for the exponent */
#define DECQUAD_String 43 /* maximum string length, +1 */
#define DECQUAD_EconL 12 /* exponent continuation length */
#define DECQUAD_Declets 11 /* count of declets */
/* highest biased exponent (Elimit-1) */
#define DECQUAD_Ehigh (DECQUAD_Emax + DECQUAD_Bias - (DECQUAD_Pmax-1))
/* Required include */
#include "decContext.h"
/* The decQuad decimal 128-bit type, accessible by all sizes */
typedef union {
uint8_t bytes[DECQUAD_Bytes]; /* fields: 1, 5, 12, 110 bits */
uint16_t shorts[DECQUAD_Bytes/2];
uint32_t words[DECQUAD_Bytes/4];
#if DECUSE64
uint64_t longs[DECQUAD_Bytes/8];
#endif
} decQuad;
/* ---------------------------------------------------------------- */
/* Shared constants */
/* ---------------------------------------------------------------- */
/* sign and special values [top 32-bits; last two bits are don't-care
for Infinity on input, last bit don't-care for NaNs] */
#define DECFLOAT_Sign 0x80000000 /* 1 00000 00 Sign */
#define DECFLOAT_NaN 0x7c000000 /* 0 11111 00 NaN generic */
#define DECFLOAT_qNaN 0x7c000000 /* 0 11111 00 qNaN */
#define DECFLOAT_sNaN 0x7e000000 /* 0 11111 10 sNaN */
#define DECFLOAT_Inf 0x78000000 /* 0 11110 00 Infinity */
#define DECFLOAT_MinSp 0x78000000 /* minimum special value */
/* [specials are all >=MinSp] */
/* Sign nibble constants */
#if !defined(DECPPLUSALT)
#define DECPPLUSALT 0x0A /* alternate plus nibble */
#define DECPMINUSALT 0x0B /* alternate minus nibble */
#define DECPPLUS 0x0C /* preferred plus nibble */
#define DECPMINUS 0x0D /* preferred minus nibble */
#define DECPPLUSALT2 0x0E /* alternate plus nibble */
#define DECPUNSIGNED 0x0F /* alternate plus nibble (unsigned) */
#endif
/* ---------------------------------------------------------------- */
/* Routines -- implemented as decFloat routines in common files */
/* ---------------------------------------------------------------- */
/* Utilities and conversions, extractors, etc.) */
extern decQuad * decQuadFromBCD(decQuad *, int32_t, const uint8_t *, int32_t);
extern decQuad * decQuadFromInt32(decQuad *, int32_t);
extern decQuad * decQuadFromPacked(decQuad *, int32_t, const uint8_t *);
extern decQuad * decQuadFromPackedChecked(decQuad *, int32_t, const uint8_t *);
extern decQuad * decQuadFromString(decQuad *, const char *, decContext *);
extern decQuad * decQuadFromUInt32(decQuad *, uint32_t);
extern int32_t decQuadGetCoefficient(const decQuad *, uint8_t *);
extern int32_t decQuadGetExponent(const decQuad *);
extern decQuad * decQuadSetCoefficient(decQuad *, const uint8_t *, int32_t);
extern decQuad * decQuadSetExponent(decQuad *, decContext *, int32_t);
extern void decQuadShow(const decQuad *, const char *);
extern int32_t decQuadToBCD(const decQuad *, int32_t *, uint8_t *);
extern char * decQuadToEngString(const decQuad *, char *);
extern int32_t decQuadToInt32(const decQuad *, decContext *, enum rounding);
extern int32_t decQuadToInt32Exact(const decQuad *, decContext *, enum rounding);
extern int32_t decQuadToPacked(const decQuad *, int32_t *, uint8_t *);
extern char * decQuadToString(const decQuad *, char *);
extern uint32_t decQuadToUInt32(const decQuad *, decContext *, enum rounding);
extern uint32_t decQuadToUInt32Exact(const decQuad *, decContext *, enum rounding);
extern decQuad * decQuadZero(decQuad *);
/* Computational (result is a decQuad) */
extern decQuad * decQuadAbs(decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadAdd(decQuad *, const decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadAnd(decQuad *, const decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadDivide(decQuad *, const decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadDivideInteger(decQuad *, const decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadFMA(decQuad *, const decQuad *, const decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadInvert(decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadLogB(decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadMax(decQuad *, const decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadMaxMag(decQuad *, const decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadMin(decQuad *, const decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadMinMag(decQuad *, const decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadMinus(decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadMultiply(decQuad *, const decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadNextMinus(decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadNextPlus(decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadNextToward(decQuad *, const decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadOr(decQuad *, const decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadPlus(decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadQuantize(decQuad *, const decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadReduce(decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadRemainder(decQuad *, const decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadRemainderNear(decQuad *, const decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadRotate(decQuad *, const decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadScaleB(decQuad *, const decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadShift(decQuad *, const decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadSubtract(decQuad *, const decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadToIntegralValue(decQuad *, const decQuad *, decContext *, enum rounding);
extern decQuad * decQuadToIntegralExact(decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadXor(decQuad *, const decQuad *, const decQuad *, decContext *);
/* Comparisons */
extern decQuad * decQuadCompare(decQuad *, const decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadCompareSignal(decQuad *, const decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadCompareTotal(decQuad *, const decQuad *, const decQuad *);
extern decQuad * decQuadCompareTotalMag(decQuad *, const decQuad *, const decQuad *);
/* Copies */
extern decQuad * decQuadCanonical(decQuad *, const decQuad *);
extern decQuad * decQuadCopy(decQuad *, const decQuad *);
extern decQuad * decQuadCopyAbs(decQuad *, const decQuad *);
extern decQuad * decQuadCopyNegate(decQuad *, const decQuad *);
extern decQuad * decQuadCopySign(decQuad *, const decQuad *, const decQuad *);
/* Non-computational */
extern enum decClass decQuadClass(const decQuad *);
extern const char * decQuadClassString(const decQuad *);
extern uint32_t decQuadDigits(const decQuad *);
extern uint32_t decQuadIsCanonical(const decQuad *);
extern uint32_t decQuadIsFinite(const decQuad *);
extern uint32_t decQuadIsInteger(const decQuad *);
extern uint32_t decQuadIsLogical(const decQuad *);
extern uint32_t decQuadIsInfinite(const decQuad *);
extern uint32_t decQuadIsNaN(const decQuad *);
extern uint32_t decQuadIsNegative(const decQuad *);
extern uint32_t decQuadIsNormal(const decQuad *);
extern uint32_t decQuadIsPositive(const decQuad *);
extern uint32_t decQuadIsSignaling(const decQuad *);
extern uint32_t decQuadIsSignalling(const decQuad *);
extern uint32_t decQuadIsSigned(const decQuad *);
extern uint32_t decQuadIsSubnormal(const decQuad *);
extern uint32_t decQuadIsZero(const decQuad *);
extern uint32_t decQuadRadix(const decQuad *);
extern uint32_t decQuadSameQuantum(const decQuad *, const decQuad *);
extern const char * decQuadVersion(void);
/* decNumber conversions; these are implemented as macros so as not */
/* to force a dependency on decimal128 and decNumber in decQuad. */
/* decQuadFromNumber returns a decimal128 * to avoid warnings. */
#define decQuadToNumber(dq, dn) decimal128ToNumber((decimal128 *)(dq), dn)
#define decQuadFromNumber(dq, dn, set) decimal128FromNumber((decimal128 *)(dq), dn, set)
#endif

71
extern/decNumber/decSingle.c vendored Normal file
View File

@ -0,0 +1,71 @@
/* ------------------------------------------------------------------ */
/* decSingle.c -- decSingle operations module */
/* ------------------------------------------------------------------ */
/* Copyright (c) IBM Corporation, 2000, 2008. All rights reserved. */
/* */
/* This software is made available under the terms of the */
/* ICU License -- ICU 1.8.1 and later. */
/* */
/* The description and User's Guide ("The decNumber C Library") for */
/* this software is included in the package as decNumber.pdf. This */
/* document is also available in HTML, together with specifications, */
/* testcases, and Web links, on the General Decimal Arithmetic page. */
/* */
/* Please send comments, suggestions, and corrections to the author: */
/* mfc@uk.ibm.com */
/* Mike Cowlishaw, IBM Fellow */
/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */
/* ------------------------------------------------------------------ */
/* This module comprises decSingle operations (including conversions) */
/* ------------------------------------------------------------------ */
#include "decContext.h" // public includes
#include "decSingle.h" // public includes
/* Constant mappings for shared code */
#define DECPMAX DECSINGLE_Pmax
#define DECEMIN DECSINGLE_Emin
#define DECEMAX DECSINGLE_Emax
#define DECEMAXD DECSINGLE_EmaxD
#define DECBYTES DECSINGLE_Bytes
#define DECSTRING DECSINGLE_String
#define DECECONL DECSINGLE_EconL
#define DECBIAS DECSINGLE_Bias
#define DECLETS DECSINGLE_Declets
#define DECQTINY (-DECSINGLE_Bias)
// parameters of next-wider format
#define DECWBYTES DECDOUBLE_Bytes
#define DECWPMAX DECDOUBLE_Pmax
#define DECWECONL DECDOUBLE_EconL
#define DECWBIAS DECDOUBLE_Bias
/* Type and function mappings for shared code */
#define decFloat decSingle // Type name
#define decFloatWider decDouble // Type name
// Utility (binary results, extractors, etc.)
#define decFloatFromBCD decSingleFromBCD
#define decFloatFromPacked decSingleFromPacked
#define decFloatFromPackedChecked decSingleFromPackedChecked
#define decFloatFromString decSingleFromString
#define decFloatFromWider decSingleFromWider
#define decFloatGetCoefficient decSingleGetCoefficient
#define decFloatGetExponent decSingleGetExponent
#define decFloatSetCoefficient decSingleSetCoefficient
#define decFloatSetExponent decSingleSetExponent
#define decFloatShow decSingleShow
#define decFloatToBCD decSingleToBCD
#define decFloatToEngString decSingleToEngString
#define decFloatToPacked decSingleToPacked
#define decFloatToString decSingleToString
#define decFloatToWider decSingleToWider
#define decFloatZero decSingleZero
// Non-computational
#define decFloatRadix decSingleRadix
#define decFloatVersion decSingleVersion
#include "decNumberLocal.h" // local includes (need DECPMAX)
#include "decCommon.c" // non-basic decFloat routines
// [Do not include decBasic.c for decimal32]

86
extern/decNumber/decSingle.h vendored Normal file
View File

@ -0,0 +1,86 @@
/* ------------------------------------------------------------------ */
/* decSingle.h -- Decimal 32-bit format module header */
/* ------------------------------------------------------------------ */
/* Copyright (c) IBM Corporation, 2000, 2008. All rights reserved. */
/* */
/* This software is made available under the terms of the */
/* ICU License -- ICU 1.8.1 and later. */
/* */
/* The description and User's Guide ("The decNumber C Library") for */
/* this software is included in the package as decNumber.pdf. This */
/* document is also available in HTML, together with specifications, */
/* testcases, and Web links, on the General Decimal Arithmetic page. */
/* */
/* Please send comments, suggestions, and corrections to the author: */
/* mfc@uk.ibm.com */
/* Mike Cowlishaw, IBM Fellow */
/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */
/* ------------------------------------------------------------------ */
#if !defined(DECSINGLE)
#define DECSINGLE
#define DECSINGLENAME "decSingle" /* Short name */
#define DECSINGLETITLE "Decimal 32-bit datum" /* Verbose name */
#define DECSINGLEAUTHOR "Mike Cowlishaw" /* Who to blame */
/* parameters for decSingles */
#define DECSINGLE_Bytes 4 /* length */
#define DECSINGLE_Pmax 7 /* maximum precision (digits) */
#define DECSINGLE_Emin -95 /* minimum adjusted exponent */
#define DECSINGLE_Emax 96 /* maximum adjusted exponent */
#define DECSINGLE_EmaxD 3 /* maximum exponent digits */
#define DECSINGLE_Bias 101 /* bias for the exponent */
#define DECSINGLE_String 16 /* maximum string length, +1 */
#define DECSINGLE_EconL 6 /* exponent continuation length */
#define DECSINGLE_Declets 2 /* count of declets */
/* highest biased exponent (Elimit-1) */
#define DECSINGLE_Ehigh (DECSINGLE_Emax + DECSINGLE_Bias - (DECSINGLE_Pmax-1))
/* Required includes */
#include "decContext.h"
#include "decQuad.h"
#include "decDouble.h"
/* The decSingle decimal 32-bit type, accessible by all sizes */
typedef union {
uint8_t bytes[DECSINGLE_Bytes]; /* fields: 1, 5, 6, 20 bits */
uint16_t shorts[DECSINGLE_Bytes/2];
uint32_t words[DECSINGLE_Bytes/4];
} decSingle;
/* ---------------------------------------------------------------- */
/* Routines -- implemented as decFloat routines in common files */
/* ---------------------------------------------------------------- */
/* Utilities (binary argument(s) or result, extractors, etc.) */
extern decSingle * decSingleFromBCD(decSingle *, int32_t, const uint8_t *, int32_t);
extern decSingle * decSingleFromPacked(decSingle *, int32_t, const uint8_t *);
extern decSingle * decSingleFromPackedChecked(decSingle *, int32_t, const uint8_t *);
extern decSingle * decSingleFromString(decSingle *, const char *, decContext *);
extern decSingle * decSingleFromWider(decSingle *, const decDouble *, decContext *);
extern int32_t decSingleGetCoefficient(const decSingle *, uint8_t *);
extern int32_t decSingleGetExponent(const decSingle *);
extern decSingle * decSingleSetCoefficient(decSingle *, const uint8_t *, int32_t);
extern decSingle * decSingleSetExponent(decSingle *, decContext *, int32_t);
extern void decSingleShow(const decSingle *, const char *);
extern int32_t decSingleToBCD(const decSingle *, int32_t *, uint8_t *);
extern char * decSingleToEngString(const decSingle *, char *);
extern int32_t decSingleToPacked(const decSingle *, int32_t *, uint8_t *);
extern char * decSingleToString(const decSingle *, char *);
extern decDouble * decSingleToWider(const decSingle *, decDouble *);
extern decSingle * decSingleZero(decSingle *);
/* (No Arithmetic routines for decSingle) */
/* Non-computational */
extern uint32_t decSingleRadix(const decSingle *);
extern const char * decSingleVersion(void);
/* decNumber conversions; these are implemented as macros so as not */
/* to force a dependency on decimal32 and decNumber in decSingle. */
/* decSingleFromNumber returns a decimal32 * to avoid warnings. */
#define decSingleToNumber(dq, dn) decimal32ToNumber((decimal32 *)(dq), dn)
#define decSingleFromNumber(dq, dn, set) decimal32FromNumber((decimal32 *)(dq), dn, set)
#endif

553
extern/decNumber/decimal128.c vendored Normal file
View File

@ -0,0 +1,553 @@
/* ------------------------------------------------------------------ */
/* Decimal 128-bit format module */
/* ------------------------------------------------------------------ */
/* Copyright (c) IBM Corporation, 2000, 2008. All rights reserved. */
/* */
/* This software is made available under the terms of the */
/* ICU License -- ICU 1.8.1 and later. */
/* */
/* The description and User's Guide ("The decNumber C Library") for */
/* this software is called decNumber.pdf. This document is */
/* available, together with arithmetic and format specifications, */
/* testcases, and Web links, on the General Decimal Arithmetic page. */
/* */
/* Please send comments, suggestions, and corrections to the author: */
/* mfc@uk.ibm.com */
/* Mike Cowlishaw, IBM Fellow */
/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */
/* ------------------------------------------------------------------ */
/* This module comprises the routines for decimal128 format numbers. */
/* Conversions are supplied to and from decNumber and String. */
/* */
/* This is used when decNumber provides operations, either for all */
/* operations or as a proxy between decNumber and decSingle. */
/* */
/* Error handling is the same as decNumber (qv.). */
/* ------------------------------------------------------------------ */
#include <string.h> // [for memset/memcpy]
#include <stdio.h> // [for printf]
#define DECNUMDIGITS 34 // make decNumbers with space for 34
#include "decNumber.h" // base number library
#include "decNumberLocal.h" // decNumber local types, etc.
#include "decimal128.h" // our primary include
/* Utility routines and tables [in decimal64.c] */
// DPD2BIN and the reverse are renamed to prevent link-time conflict
// if decQuad is also built in the same executable
#define DPD2BIN DPD2BINx
#define BIN2DPD BIN2DPDx
extern const uInt COMBEXP[32], COMBMSD[32];
extern const uShort DPD2BIN[1024];
extern const uShort BIN2DPD[1000]; // [not used]
extern const uByte BIN2CHAR[4001];
extern void decDigitsFromDPD(decNumber *, const uInt *, Int);
extern void decDigitsToDPD(const decNumber *, uInt *, Int);
#if DECTRACE || DECCHECK
void decimal128Show(const decimal128 *); // for debug
extern void decNumberShow(const decNumber *); // ..
#endif
/* Useful macro */
// Clear a structure (e.g., a decNumber)
#define DEC_clear(d) memset(d, 0, sizeof(*d))
/* ------------------------------------------------------------------ */
/* decimal128FromNumber -- convert decNumber to decimal128 */
/* */
/* ds is the target decimal128 */
/* dn is the source number (assumed valid) */
/* set is the context, used only for reporting errors */
/* */
/* The set argument is used only for status reporting and for the */
/* rounding mode (used if the coefficient is more than DECIMAL128_Pmax*/
/* digits or an overflow is detected). If the exponent is out of the */
/* valid range then Overflow or Underflow will be raised. */
/* After Underflow a subnormal result is possible. */
/* */
/* DEC_Clamped is set if the number has to be 'folded down' to fit, */
/* by reducing its exponent and multiplying the coefficient by a */
/* power of ten, or if the exponent on a zero had to be clamped. */
/* ------------------------------------------------------------------ */
decimal128 * decimal128FromNumber(decimal128 *d128, const decNumber *dn,
decContext *set) {
uInt status=0; // status accumulator
Int ae; // adjusted exponent
decNumber dw; // work
decContext dc; // ..
uInt comb, exp; // ..
uInt uiwork; // for macros
uInt targar[4]={0,0,0,0}; // target 128-bit
#define targhi targar[3] // name the word with the sign
#define targmh targar[2] // name the words
#define targml targar[1] // ..
#define targlo targar[0] // ..
// If the number has too many digits, or the exponent could be
// out of range then reduce the number under the appropriate
// constraints. This could push the number to Infinity or zero,
// so this check and rounding must be done before generating the
// decimal128]
ae=dn->exponent+dn->digits-1; // [0 if special]
if (dn->digits>DECIMAL128_Pmax // too many digits
|| ae>DECIMAL128_Emax // likely overflow
|| ae<DECIMAL128_Emin) { // likely underflow
decContextDefault(&dc, DEC_INIT_DECIMAL128); // [no traps]
dc.round=set->round; // use supplied rounding
decNumberPlus(&dw, dn, &dc); // (round and check)
// [this changes -0 to 0, so enforce the sign...]
dw.bits|=dn->bits&DECNEG;
status=dc.status; // save status
dn=&dw; // use the work number
} // maybe out of range
if (dn->bits&DECSPECIAL) { // a special value
if (dn->bits&DECINF) targhi=DECIMAL_Inf<<24;
else { // sNaN or qNaN
if ((*dn->lsu!=0 || dn->digits>1) // non-zero coefficient
&& (dn->digits<DECIMAL128_Pmax)) { // coefficient fits
decDigitsToDPD(dn, targar, 0);
}
if (dn->bits&DECNAN) targhi|=DECIMAL_NaN<<24;
else targhi|=DECIMAL_sNaN<<24;
} // a NaN
} // special
else { // is finite
if (decNumberIsZero(dn)) { // is a zero
// set and clamp exponent
if (dn->exponent<-DECIMAL128_Bias) {
exp=0; // low clamp
status|=DEC_Clamped;
}
else {
exp=dn->exponent+DECIMAL128_Bias; // bias exponent
if (exp>DECIMAL128_Ehigh) { // top clamp
exp=DECIMAL128_Ehigh;
status|=DEC_Clamped;
}
}
comb=(exp>>9) & 0x18; // msd=0, exp top 2 bits ..
}
else { // non-zero finite number
uInt msd; // work
Int pad=0; // coefficient pad digits
// the dn is known to fit, but it may need to be padded
exp=(uInt)(dn->exponent+DECIMAL128_Bias); // bias exponent
if (exp>DECIMAL128_Ehigh) { // fold-down case
pad=exp-DECIMAL128_Ehigh;
exp=DECIMAL128_Ehigh; // [to maximum]
status|=DEC_Clamped;
}
// [fastpath for common case is not a win, here]
decDigitsToDPD(dn, targar, pad);
// save and clear the top digit
msd=targhi>>14;
targhi&=0x00003fff;
// create the combination field
if (msd>=8) comb=0x18 | ((exp>>11) & 0x06) | (msd & 0x01);
else comb=((exp>>9) & 0x18) | msd;
}
targhi|=comb<<26; // add combination field ..
targhi|=(exp&0xfff)<<14; // .. and exponent continuation
} // finite
if (dn->bits&DECNEG) targhi|=0x80000000; // add sign bit
// now write to storage; this is endian
if (DECLITEND) {
// lo -> hi
UBFROMUI(d128->bytes, targlo);
UBFROMUI(d128->bytes+4, targml);
UBFROMUI(d128->bytes+8, targmh);
UBFROMUI(d128->bytes+12, targhi);
}
else {
// hi -> lo
UBFROMUI(d128->bytes, targhi);
UBFROMUI(d128->bytes+4, targmh);
UBFROMUI(d128->bytes+8, targml);
UBFROMUI(d128->bytes+12, targlo);
}
if (status!=0) decContextSetStatus(set, status); // pass on status
// decimal128Show(d128);
return d128;
} // decimal128FromNumber
/* ------------------------------------------------------------------ */
/* decimal128ToNumber -- convert decimal128 to decNumber */
/* d128 is the source decimal128 */
/* dn is the target number, with appropriate space */
/* No error is possible. */
/* ------------------------------------------------------------------ */
decNumber * decimal128ToNumber(const decimal128 *d128, decNumber *dn) {
uInt msd; // coefficient MSD
uInt exp; // exponent top two bits
uInt comb; // combination field
Int need; // work
uInt uiwork; // for macros
uInt sourar[4]; // source 128-bit
#define sourhi sourar[3] // name the word with the sign
#define sourmh sourar[2] // and the mid-high word
#define sourml sourar[1] // and the mod-low word
#define sourlo sourar[0] // and the lowest word
// load source from storage; this is endian
if (DECLITEND) {
sourlo=UBTOUI(d128->bytes ); // directly load the low int
sourml=UBTOUI(d128->bytes+4 ); // then the mid-low
sourmh=UBTOUI(d128->bytes+8 ); // then the mid-high
sourhi=UBTOUI(d128->bytes+12); // then the high int
}
else {
sourhi=UBTOUI(d128->bytes ); // directly load the high int
sourmh=UBTOUI(d128->bytes+4 ); // then the mid-high
sourml=UBTOUI(d128->bytes+8 ); // then the mid-low
sourlo=UBTOUI(d128->bytes+12); // then the low int
}
comb=(sourhi>>26)&0x1f; // combination field
decNumberZero(dn); // clean number
if (sourhi&0x80000000) dn->bits=DECNEG; // set sign if negative
msd=COMBMSD[comb]; // decode the combination field
exp=COMBEXP[comb]; // ..
if (exp==3) { // is a special
if (msd==0) {
dn->bits|=DECINF;
return dn; // no coefficient needed
}
else if (sourhi&0x02000000) dn->bits|=DECSNAN;
else dn->bits|=DECNAN;
msd=0; // no top digit
}
else { // is a finite number
dn->exponent=(exp<<12)+((sourhi>>14)&0xfff)-DECIMAL128_Bias; // unbiased
}
// get the coefficient
sourhi&=0x00003fff; // clean coefficient continuation
if (msd) { // non-zero msd
sourhi|=msd<<14; // prefix to coefficient
need=12; // process 12 declets
}
else { // msd=0
if (sourhi) need=11; // declets to process
else if (sourmh) need=10;
else if (sourml) need=7;
else if (sourlo) need=4;
else return dn; // easy: coefficient is 0
} //msd=0
decDigitsFromDPD(dn, sourar, need); // process declets
// decNumberShow(dn);
return dn;
} // decimal128ToNumber
/* ------------------------------------------------------------------ */
/* to-scientific-string -- conversion to numeric string */
/* to-engineering-string -- conversion to numeric string */
/* */
/* decimal128ToString(d128, string); */
/* decimal128ToEngString(d128, string); */
/* */
/* d128 is the decimal128 format number to convert */
/* string is the string where the result will be laid out */
/* */
/* string must be at least 24 characters */
/* */
/* No error is possible, and no status can be set. */
/* ------------------------------------------------------------------ */
char * decimal128ToEngString(const decimal128 *d128, char *string){
decNumber dn; // work
decimal128ToNumber(d128, &dn);
decNumberToEngString(&dn, string);
return string;
} // decimal128ToEngString
char * decimal128ToString(const decimal128 *d128, char *string){
uInt msd; // coefficient MSD
Int exp; // exponent top two bits or full
uInt comb; // combination field
char *cstart; // coefficient start
char *c; // output pointer in string
const uByte *u; // work
char *s, *t; // .. (source, target)
Int dpd; // ..
Int pre, e; // ..
uInt uiwork; // for macros
uInt sourar[4]; // source 128-bit
#define sourhi sourar[3] // name the word with the sign
#define sourmh sourar[2] // and the mid-high word
#define sourml sourar[1] // and the mod-low word
#define sourlo sourar[0] // and the lowest word
// load source from storage; this is endian
if (DECLITEND) {
sourlo=UBTOUI(d128->bytes ); // directly load the low int
sourml=UBTOUI(d128->bytes+4 ); // then the mid-low
sourmh=UBTOUI(d128->bytes+8 ); // then the mid-high
sourhi=UBTOUI(d128->bytes+12); // then the high int
}
else {
sourhi=UBTOUI(d128->bytes ); // directly load the high int
sourmh=UBTOUI(d128->bytes+4 ); // then the mid-high
sourml=UBTOUI(d128->bytes+8 ); // then the mid-low
sourlo=UBTOUI(d128->bytes+12); // then the low int
}
c=string; // where result will go
if (((Int)sourhi)<0) *c++='-'; // handle sign
comb=(sourhi>>26)&0x1f; // combination field
msd=COMBMSD[comb]; // decode the combination field
exp=COMBEXP[comb]; // ..
if (exp==3) {
if (msd==0) { // infinity
strcpy(c, "Inf");
strcpy(c+3, "inity");
return string; // easy
}
if (sourhi&0x02000000) *c++='s'; // sNaN
strcpy(c, "NaN"); // complete word
c+=3; // step past
if (sourlo==0 && sourml==0 && sourmh==0
&& (sourhi&0x0003ffff)==0) return string; // zero payload
// otherwise drop through to add integer; set correct exp
exp=0; msd=0; // setup for following code
}
else exp=(exp<<12)+((sourhi>>14)&0xfff)-DECIMAL128_Bias; // unbiased
// convert 34 digits of significand to characters
cstart=c; // save start of coefficient
if (msd) *c++='0'+(char)msd; // non-zero most significant digit
// Now decode the declets. After extracting each one, it is
// decoded to binary and then to a 4-char sequence by table lookup;
// the 4-chars are a 1-char length (significant digits, except 000
// has length 0). This allows us to left-align the first declet
// with non-zero content, then remaining ones are full 3-char
// length. We use fixed-length memcpys because variable-length
// causes a subroutine call in GCC. (These are length 4 for speed
// and are safe because the array has an extra terminator byte.)
#define dpd2char u=&BIN2CHAR[DPD2BIN[dpd]*4]; \
if (c!=cstart) {memcpy(c, u+1, 4); c+=3;} \
else if (*u) {memcpy(c, u+4-*u, 4); c+=*u;}
dpd=(sourhi>>4)&0x3ff; // declet 1
dpd2char;
dpd=((sourhi&0xf)<<6) | (sourmh>>26); // declet 2
dpd2char;
dpd=(sourmh>>16)&0x3ff; // declet 3
dpd2char;
dpd=(sourmh>>6)&0x3ff; // declet 4
dpd2char;
dpd=((sourmh&0x3f)<<4) | (sourml>>28); // declet 5
dpd2char;
dpd=(sourml>>18)&0x3ff; // declet 6
dpd2char;
dpd=(sourml>>8)&0x3ff; // declet 7
dpd2char;
dpd=((sourml&0xff)<<2) | (sourlo>>30); // declet 8
dpd2char;
dpd=(sourlo>>20)&0x3ff; // declet 9
dpd2char;
dpd=(sourlo>>10)&0x3ff; // declet 10
dpd2char;
dpd=(sourlo)&0x3ff; // declet 11
dpd2char;
if (c==cstart) *c++='0'; // all zeros -- make 0
if (exp==0) { // integer or NaN case -- easy
*c='\0'; // terminate
return string;
}
/* non-0 exponent */
e=0; // assume no E
pre=c-cstart+exp;
// [here, pre-exp is the digits count (==1 for zero)]
if (exp>0 || pre<-5) { // need exponential form
e=pre-1; // calculate E value
pre=1; // assume one digit before '.'
} // exponential form
/* modify the coefficient, adding 0s, '.', and E+nn as needed */
s=c-1; // source (LSD)
if (pre>0) { // ddd.ddd (plain), perhaps with E
char *dotat=cstart+pre;
if (dotat<c) { // if embedded dot needed...
t=c; // target
for (; s>=dotat; s--, t--) *t=*s; // open the gap; leave t at gap
*t='.'; // insert the dot
c++; // length increased by one
}
// finally add the E-part, if needed; it will never be 0, and has
// a maximum length of 4 digits
if (e!=0) {
*c++='E'; // starts with E
*c++='+'; // assume positive
if (e<0) {
*(c-1)='-'; // oops, need '-'
e=-e; // uInt, please
}
if (e<1000) { // 3 (or fewer) digits case
u=&BIN2CHAR[e*4]; // -> length byte
memcpy(c, u+4-*u, 4); // copy fixed 4 characters [is safe]
c+=*u; // bump pointer appropriately
}
else { // 4-digits
Int thou=((e>>3)*1049)>>17; // e/1000
Int rem=e-(1000*thou); // e%1000
*c++='0'+(char)thou;
u=&BIN2CHAR[rem*4]; // -> length byte
memcpy(c, u+1, 4); // copy fixed 3+1 characters [is safe]
c+=3; // bump pointer, always 3 digits
}
}
*c='\0'; // add terminator
//printf("res %s\n", string);
return string;
} // pre>0
/* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (can never have E) */
t=c+1-pre;
*(t+1)='\0'; // can add terminator now
for (; s>=cstart; s--, t--) *t=*s; // shift whole coefficient right
c=cstart;
*c++='0'; // always starts with 0.
*c++='.';
for (; pre<0; pre++) *c++='0'; // add any 0's after '.'
//printf("res %s\n", string);
return string;
} // decimal128ToString
/* ------------------------------------------------------------------ */
/* to-number -- conversion from numeric string */
/* */
/* decimal128FromString(result, string, set); */
/* */
/* result is the decimal128 format number which gets the result of */
/* the conversion */
/* *string is the character string which should contain a valid */
/* number (which may be a special value) */
/* set is the context */
/* */
/* The context is supplied to this routine is used for error handling */
/* (setting of status and traps) and for the rounding mode, only. */
/* If an error occurs, the result will be a valid decimal128 NaN. */
/* ------------------------------------------------------------------ */
decimal128 * decimal128FromString(decimal128 *result, const char *string,
decContext *set) {
decContext dc; // work
decNumber dn; // ..
decContextDefault(&dc, DEC_INIT_DECIMAL128); // no traps, please
dc.round=set->round; // use supplied rounding
decNumberFromString(&dn, string, &dc); // will round if needed
decimal128FromNumber(result, &dn, &dc);
if (dc.status!=0) { // something happened
decContextSetStatus(set, dc.status); // .. pass it on
}
return result;
} // decimal128FromString
/* ------------------------------------------------------------------ */
/* decimal128IsCanonical -- test whether encoding is canonical */
/* d128 is the source decimal128 */
/* returns 1 if the encoding of d128 is canonical, 0 otherwise */
/* No error is possible. */
/* ------------------------------------------------------------------ */
uInt decimal128IsCanonical(const decimal128 *d128) {
decNumber dn; // work
decimal128 canon; // ..
decContext dc; // ..
decContextDefault(&dc, DEC_INIT_DECIMAL128);
decimal128ToNumber(d128, &dn);
decimal128FromNumber(&canon, &dn, &dc);// canon will now be canonical
return memcmp(d128, &canon, DECIMAL128_Bytes)==0;
} // decimal128IsCanonical
/* ------------------------------------------------------------------ */
/* decimal128Canonical -- copy an encoding, ensuring it is canonical */
/* d128 is the source decimal128 */
/* result is the target (may be the same decimal128) */
/* returns result */
/* No error is possible. */
/* ------------------------------------------------------------------ */
decimal128 * decimal128Canonical(decimal128 *result, const decimal128 *d128) {
decNumber dn; // work
decContext dc; // ..
decContextDefault(&dc, DEC_INIT_DECIMAL128);
decimal128ToNumber(d128, &dn);
decimal128FromNumber(result, &dn, &dc);// result will now be canonical
return result;
} // decimal128Canonical
#if DECTRACE || DECCHECK
/* Macros for accessing decimal128 fields. These assume the argument
is a reference (pointer) to the decimal128 structure, and the
decimal128 is in network byte order (big-endian) */
// Get sign
#define decimal128Sign(d) ((unsigned)(d)->bytes[0]>>7)
// Get combination field
#define decimal128Comb(d) (((d)->bytes[0] & 0x7c)>>2)
// Get exponent continuation [does not remove bias]
#define decimal128ExpCon(d) ((((d)->bytes[0] & 0x03)<<10) \
| ((unsigned)(d)->bytes[1]<<2) \
| ((unsigned)(d)->bytes[2]>>6))
// Set sign [this assumes sign previously 0]
#define decimal128SetSign(d, b) { \
(d)->bytes[0]|=((unsigned)(b)<<7);}
// Set exponent continuation [does not apply bias]
// This assumes range has been checked and exponent previously 0;
// type of exponent must be unsigned
#define decimal128SetExpCon(d, e) { \
(d)->bytes[0]|=(uByte)((e)>>10); \
(d)->bytes[1] =(uByte)(((e)&0x3fc)>>2); \
(d)->bytes[2]|=(uByte)(((e)&0x03)<<6);}
/* ------------------------------------------------------------------ */
/* decimal128Show -- display a decimal128 in hexadecimal [debug aid] */
/* d128 -- the number to show */
/* ------------------------------------------------------------------ */
// Also shows sign/cob/expconfields extracted
void decimal128Show(const decimal128 *d128) {
char buf[DECIMAL128_Bytes*2+1];
Int i, j=0;
if (DECLITEND) {
for (i=0; i<DECIMAL128_Bytes; i++, j+=2) {
sprintf(&buf[j], "%02x", d128->bytes[15-i]);
}
printf(" D128> %s [S:%d Cb:%02x Ec:%02x] LittleEndian\n", buf,
d128->bytes[15]>>7, (d128->bytes[15]>>2)&0x1f,
((d128->bytes[15]&0x3)<<10)|(d128->bytes[14]<<2)|
(d128->bytes[13]>>6));
}
else {
for (i=0; i<DECIMAL128_Bytes; i++, j+=2) {
sprintf(&buf[j], "%02x", d128->bytes[i]);
}
printf(" D128> %s [S:%d Cb:%02x Ec:%02x] BigEndian\n", buf,
decimal128Sign(d128), decimal128Comb(d128),
decimal128ExpCon(d128));
}
} // decimal128Show
#endif

81
extern/decNumber/decimal128.h vendored Normal file
View File

@ -0,0 +1,81 @@
/* ------------------------------------------------------------------ */
/* Decimal 128-bit format module header */
/* ------------------------------------------------------------------ */
/* Copyright (c) IBM Corporation, 2000, 2005. All rights reserved. */
/* */
/* This software is made available under the terms of the */
/* ICU License -- ICU 1.8.1 and later. */
/* */
/* The description and User's Guide ("The decNumber C Library") for */
/* this software is called decNumber.pdf. This document is */
/* available, together with arithmetic and format specifications, */
/* testcases, and Web links, on the General Decimal Arithmetic page. */
/* */
/* Please send comments, suggestions, and corrections to the author: */
/* mfc@uk.ibm.com */
/* Mike Cowlishaw, IBM Fellow */
/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */
/* ------------------------------------------------------------------ */
#if !defined(DECIMAL128)
#define DECIMAL128
#define DEC128NAME "decimal128" /* Short name */
#define DEC128FULLNAME "Decimal 128-bit Number" /* Verbose name */
#define DEC128AUTHOR "Mike Cowlishaw" /* Who to blame */
/* parameters for decimal128s */
#define DECIMAL128_Bytes 16 /* length */
#define DECIMAL128_Pmax 34 /* maximum precision (digits) */
#define DECIMAL128_Emax 6144 /* maximum adjusted exponent */
#define DECIMAL128_Emin -6143 /* minimum adjusted exponent */
#define DECIMAL128_Bias 6176 /* bias for the exponent */
#define DECIMAL128_String 43 /* maximum string length, +1 */
#define DECIMAL128_EconL 12 /* exp. continuation length */
/* highest biased exponent (Elimit-1) */
#define DECIMAL128_Ehigh (DECIMAL128_Emax+DECIMAL128_Bias-DECIMAL128_Pmax+1)
/* check enough digits, if pre-defined */
#if defined(DECNUMDIGITS)
#if (DECNUMDIGITS<DECIMAL128_Pmax)
#error decimal128.h needs pre-defined DECNUMDIGITS>=34 for safe use
#endif
#endif
#ifndef DECNUMDIGITS
#define DECNUMDIGITS DECIMAL128_Pmax /* size if not already defined*/
#endif
#ifndef DECNUMBER
#include "decNumber.h" /* context and number library */
#endif
/* Decimal 128-bit type, accessible by bytes */
typedef struct {
uint8_t bytes[DECIMAL128_Bytes]; /* decimal128: 1, 5, 12, 110 bits*/
} decimal128;
/* special values [top byte excluding sign bit; last two bits are */
/* don't-care for Infinity on input, last bit don't-care for NaN] */
#if !defined(DECIMAL_NaN)
#define DECIMAL_NaN 0x7c /* 0 11111 00 NaN */
#define DECIMAL_sNaN 0x7e /* 0 11111 10 sNaN */
#define DECIMAL_Inf 0x78 /* 0 11110 00 Infinity */
#endif
/* ---------------------------------------------------------------- */
/* Routines */
/* ---------------------------------------------------------------- */
/* String conversions */
decimal128 * decimal128FromString(decimal128 *, const char *, decContext *);
char * decimal128ToString(const decimal128 *, char *);
char * decimal128ToEngString(const decimal128 *, char *);
/* decNumber conversions */
decimal128 * decimal128FromNumber(decimal128 *, const decNumber *,
decContext *);
decNumber * decimal128ToNumber(const decimal128 *, decNumber *);
/* Format-dependent utilities */
uint32_t decimal128IsCanonical(const decimal128 *);
decimal128 * decimal128Canonical(decimal128 *, const decimal128 *);
#endif

476
extern/decNumber/decimal32.c vendored Normal file
View File

@ -0,0 +1,476 @@
/* ------------------------------------------------------------------ */
/* Decimal 32-bit format module */
/* ------------------------------------------------------------------ */
/* Copyright (c) IBM Corporation, 2000, 2008. All rights reserved. */
/* */
/* This software is made available under the terms of the */
/* ICU License -- ICU 1.8.1 and later. */
/* */
/* The description and User's Guide ("The decNumber C Library") for */
/* this software is called decNumber.pdf. This document is */
/* available, together with arithmetic and format specifications, */
/* testcases, and Web links, on the General Decimal Arithmetic page. */
/* */
/* Please send comments, suggestions, and corrections to the author: */
/* mfc@uk.ibm.com */
/* Mike Cowlishaw, IBM Fellow */
/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */
/* ------------------------------------------------------------------ */
/* This module comprises the routines for decimal32 format numbers. */
/* Conversions are supplied to and from decNumber and String. */
/* */
/* This is used when decNumber provides operations, either for all */
/* operations or as a proxy between decNumber and decSingle. */
/* */
/* Error handling is the same as decNumber (qv.). */
/* ------------------------------------------------------------------ */
#include <string.h> // [for memset/memcpy]
#include <stdio.h> // [for printf]
#define DECNUMDIGITS 7 // make decNumbers with space for 7
#include "decNumber.h" // base number library
#include "decNumberLocal.h" // decNumber local types, etc.
#include "decimal32.h" // our primary include
/* Utility tables and routines [in decimal64.c] */
// DPD2BIN and the reverse are renamed to prevent link-time conflict
// if decQuad is also built in the same executable
#define DPD2BIN DPD2BINx
#define BIN2DPD BIN2DPDx
extern const uInt COMBEXP[32], COMBMSD[32];
extern const uShort DPD2BIN[1024];
extern const uShort BIN2DPD[1000];
extern const uByte BIN2CHAR[4001];
extern void decDigitsToDPD(const decNumber *, uInt *, Int);
extern void decDigitsFromDPD(decNumber *, const uInt *, Int);
#if DECTRACE || DECCHECK
void decimal32Show(const decimal32 *); // for debug
extern void decNumberShow(const decNumber *); // ..
#endif
/* Useful macro */
// Clear a structure (e.g., a decNumber)
#define DEC_clear(d) memset(d, 0, sizeof(*d))
/* ------------------------------------------------------------------ */
/* decimal32FromNumber -- convert decNumber to decimal32 */
/* */
/* ds is the target decimal32 */
/* dn is the source number (assumed valid) */
/* set is the context, used only for reporting errors */
/* */
/* The set argument is used only for status reporting and for the */
/* rounding mode (used if the coefficient is more than DECIMAL32_Pmax */
/* digits or an overflow is detected). If the exponent is out of the */
/* valid range then Overflow or Underflow will be raised. */
/* After Underflow a subnormal result is possible. */
/* */
/* DEC_Clamped is set if the number has to be 'folded down' to fit, */
/* by reducing its exponent and multiplying the coefficient by a */
/* power of ten, or if the exponent on a zero had to be clamped. */
/* ------------------------------------------------------------------ */
decimal32 * decimal32FromNumber(decimal32 *d32, const decNumber *dn,
decContext *set) {
uInt status=0; // status accumulator
Int ae; // adjusted exponent
decNumber dw; // work
decContext dc; // ..
uInt comb, exp; // ..
uInt uiwork; // for macros
uInt targ=0; // target 32-bit
// If the number has too many digits, or the exponent could be
// out of range then reduce the number under the appropriate
// constraints. This could push the number to Infinity or zero,
// so this check and rounding must be done before generating the
// decimal32]
ae=dn->exponent+dn->digits-1; // [0 if special]
if (dn->digits>DECIMAL32_Pmax // too many digits
|| ae>DECIMAL32_Emax // likely overflow
|| ae<DECIMAL32_Emin) { // likely underflow
decContextDefault(&dc, DEC_INIT_DECIMAL32); // [no traps]
dc.round=set->round; // use supplied rounding
decNumberPlus(&dw, dn, &dc); // (round and check)
// [this changes -0 to 0, so enforce the sign...]
dw.bits|=dn->bits&DECNEG;
status=dc.status; // save status
dn=&dw; // use the work number
} // maybe out of range
if (dn->bits&DECSPECIAL) { // a special value
if (dn->bits&DECINF) targ=DECIMAL_Inf<<24;
else { // sNaN or qNaN
if ((*dn->lsu!=0 || dn->digits>1) // non-zero coefficient
&& (dn->digits<DECIMAL32_Pmax)) { // coefficient fits
decDigitsToDPD(dn, &targ, 0);
}
if (dn->bits&DECNAN) targ|=DECIMAL_NaN<<24;
else targ|=DECIMAL_sNaN<<24;
} // a NaN
} // special
else { // is finite
if (decNumberIsZero(dn)) { // is a zero
// set and clamp exponent
if (dn->exponent<-DECIMAL32_Bias) {
exp=0; // low clamp
status|=DEC_Clamped;
}
else {
exp=dn->exponent+DECIMAL32_Bias; // bias exponent
if (exp>DECIMAL32_Ehigh) { // top clamp
exp=DECIMAL32_Ehigh;
status|=DEC_Clamped;
}
}
comb=(exp>>3) & 0x18; // msd=0, exp top 2 bits ..
}
else { // non-zero finite number
uInt msd; // work
Int pad=0; // coefficient pad digits
// the dn is known to fit, but it may need to be padded
exp=(uInt)(dn->exponent+DECIMAL32_Bias); // bias exponent
if (exp>DECIMAL32_Ehigh) { // fold-down case
pad=exp-DECIMAL32_Ehigh;
exp=DECIMAL32_Ehigh; // [to maximum]
status|=DEC_Clamped;
}
// fastpath common case
if (DECDPUN==3 && pad==0) {
targ=BIN2DPD[dn->lsu[0]];
if (dn->digits>3) targ|=(uInt)(BIN2DPD[dn->lsu[1]])<<10;
msd=(dn->digits==7 ? dn->lsu[2] : 0);
}
else { // general case
decDigitsToDPD(dn, &targ, pad);
// save and clear the top digit
msd=targ>>20;
targ&=0x000fffff;
}
// create the combination field
if (msd>=8) comb=0x18 | ((exp>>5) & 0x06) | (msd & 0x01);
else comb=((exp>>3) & 0x18) | msd;
}
targ|=comb<<26; // add combination field ..
targ|=(exp&0x3f)<<20; // .. and exponent continuation
} // finite
if (dn->bits&DECNEG) targ|=0x80000000; // add sign bit
// now write to storage; this is endian
UBFROMUI(d32->bytes, targ); // directly store the int
if (status!=0) decContextSetStatus(set, status); // pass on status
// decimal32Show(d32);
return d32;
} // decimal32FromNumber
/* ------------------------------------------------------------------ */
/* decimal32ToNumber -- convert decimal32 to decNumber */
/* d32 is the source decimal32 */
/* dn is the target number, with appropriate space */
/* No error is possible. */
/* ------------------------------------------------------------------ */
decNumber * decimal32ToNumber(const decimal32 *d32, decNumber *dn) {
uInt msd; // coefficient MSD
uInt exp; // exponent top two bits
uInt comb; // combination field
uInt sour; // source 32-bit
uInt uiwork; // for macros
// load source from storage; this is endian
sour=UBTOUI(d32->bytes); // directly load the int
comb=(sour>>26)&0x1f; // combination field
decNumberZero(dn); // clean number
if (sour&0x80000000) dn->bits=DECNEG; // set sign if negative
msd=COMBMSD[comb]; // decode the combination field
exp=COMBEXP[comb]; // ..
if (exp==3) { // is a special
if (msd==0) {
dn->bits|=DECINF;
return dn; // no coefficient needed
}
else if (sour&0x02000000) dn->bits|=DECSNAN;
else dn->bits|=DECNAN;
msd=0; // no top digit
}
else { // is a finite number
dn->exponent=(exp<<6)+((sour>>20)&0x3f)-DECIMAL32_Bias; // unbiased
}
// get the coefficient
sour&=0x000fffff; // clean coefficient continuation
if (msd) { // non-zero msd
sour|=msd<<20; // prefix to coefficient
decDigitsFromDPD(dn, &sour, 3); // process 3 declets
return dn;
}
// msd=0
if (!sour) return dn; // easy: coefficient is 0
if (sour&0x000ffc00) // need 2 declets?
decDigitsFromDPD(dn, &sour, 2); // process 2 declets
else
decDigitsFromDPD(dn, &sour, 1); // process 1 declet
return dn;
} // decimal32ToNumber
/* ------------------------------------------------------------------ */
/* to-scientific-string -- conversion to numeric string */
/* to-engineering-string -- conversion to numeric string */
/* */
/* decimal32ToString(d32, string); */
/* decimal32ToEngString(d32, string); */
/* */
/* d32 is the decimal32 format number to convert */
/* string is the string where the result will be laid out */
/* */
/* string must be at least 24 characters */
/* */
/* No error is possible, and no status can be set. */
/* ------------------------------------------------------------------ */
char * decimal32ToEngString(const decimal32 *d32, char *string){
decNumber dn; // work
decimal32ToNumber(d32, &dn);
decNumberToEngString(&dn, string);
return string;
} // decimal32ToEngString
char * decimal32ToString(const decimal32 *d32, char *string){
uInt msd; // coefficient MSD
Int exp; // exponent top two bits or full
uInt comb; // combination field
char *cstart; // coefficient start
char *c; // output pointer in string
const uByte *u; // work
char *s, *t; // .. (source, target)
Int dpd; // ..
Int pre, e; // ..
uInt uiwork; // for macros
uInt sour; // source 32-bit
// load source from storage; this is endian
sour=UBTOUI(d32->bytes); // directly load the int
c=string; // where result will go
if (((Int)sour)<0) *c++='-'; // handle sign
comb=(sour>>26)&0x1f; // combination field
msd=COMBMSD[comb]; // decode the combination field
exp=COMBEXP[comb]; // ..
if (exp==3) {
if (msd==0) { // infinity
strcpy(c, "Inf");
strcpy(c+3, "inity");
return string; // easy
}
if (sour&0x02000000) *c++='s'; // sNaN
strcpy(c, "NaN"); // complete word
c+=3; // step past
if ((sour&0x000fffff)==0) return string; // zero payload
// otherwise drop through to add integer; set correct exp
exp=0; msd=0; // setup for following code
}
else exp=(exp<<6)+((sour>>20)&0x3f)-DECIMAL32_Bias; // unbiased
// convert 7 digits of significand to characters
cstart=c; // save start of coefficient
if (msd) *c++='0'+(char)msd; // non-zero most significant digit
// Now decode the declets. After extracting each one, it is
// decoded to binary and then to a 4-char sequence by table lookup;
// the 4-chars are a 1-char length (significant digits, except 000
// has length 0). This allows us to left-align the first declet
// with non-zero content, then remaining ones are full 3-char
// length. We use fixed-length memcpys because variable-length
// causes a subroutine call in GCC. (These are length 4 for speed
// and are safe because the array has an extra terminator byte.)
#define dpd2char u=&BIN2CHAR[DPD2BIN[dpd]*4]; \
if (c!=cstart) {memcpy(c, u+1, 4); c+=3;} \
else if (*u) {memcpy(c, u+4-*u, 4); c+=*u;}
dpd=(sour>>10)&0x3ff; // declet 1
dpd2char;
dpd=(sour)&0x3ff; // declet 2
dpd2char;
if (c==cstart) *c++='0'; // all zeros -- make 0
if (exp==0) { // integer or NaN case -- easy
*c='\0'; // terminate
return string;
}
/* non-0 exponent */
e=0; // assume no E
pre=c-cstart+exp;
// [here, pre-exp is the digits count (==1 for zero)]
if (exp>0 || pre<-5) { // need exponential form
e=pre-1; // calculate E value
pre=1; // assume one digit before '.'
} // exponential form
/* modify the coefficient, adding 0s, '.', and E+nn as needed */
s=c-1; // source (LSD)
if (pre>0) { // ddd.ddd (plain), perhaps with E
char *dotat=cstart+pre;
if (dotat<c) { // if embedded dot needed...
t=c; // target
for (; s>=dotat; s--, t--) *t=*s; // open the gap; leave t at gap
*t='.'; // insert the dot
c++; // length increased by one
}
// finally add the E-part, if needed; it will never be 0, and has
// a maximum length of 3 digits (E-101 case)
if (e!=0) {
*c++='E'; // starts with E
*c++='+'; // assume positive
if (e<0) {
*(c-1)='-'; // oops, need '-'
e=-e; // uInt, please
}
u=&BIN2CHAR[e*4]; // -> length byte
memcpy(c, u+4-*u, 4); // copy fixed 4 characters [is safe]
c+=*u; // bump pointer appropriately
}
*c='\0'; // add terminator
//printf("res %s\n", string);
return string;
} // pre>0
/* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (can never have E) */
t=c+1-pre;
*(t+1)='\0'; // can add terminator now
for (; s>=cstart; s--, t--) *t=*s; // shift whole coefficient right
c=cstart;
*c++='0'; // always starts with 0.
*c++='.';
for (; pre<0; pre++) *c++='0'; // add any 0's after '.'
//printf("res %s\n", string);
return string;
} // decimal32ToString
/* ------------------------------------------------------------------ */
/* to-number -- conversion from numeric string */
/* */
/* decimal32FromString(result, string, set); */
/* */
/* result is the decimal32 format number which gets the result of */
/* the conversion */
/* *string is the character string which should contain a valid */
/* number (which may be a special value) */
/* set is the context */
/* */
/* The context is supplied to this routine is used for error handling */
/* (setting of status and traps) and for the rounding mode, only. */
/* If an error occurs, the result will be a valid decimal32 NaN. */
/* ------------------------------------------------------------------ */
decimal32 * decimal32FromString(decimal32 *result, const char *string,
decContext *set) {
decContext dc; // work
decNumber dn; // ..
decContextDefault(&dc, DEC_INIT_DECIMAL32); // no traps, please
dc.round=set->round; // use supplied rounding
decNumberFromString(&dn, string, &dc); // will round if needed
decimal32FromNumber(result, &dn, &dc);
if (dc.status!=0) { // something happened
decContextSetStatus(set, dc.status); // .. pass it on
}
return result;
} // decimal32FromString
/* ------------------------------------------------------------------ */
/* decimal32IsCanonical -- test whether encoding is canonical */
/* d32 is the source decimal32 */
/* returns 1 if the encoding of d32 is canonical, 0 otherwise */
/* No error is possible. */
/* ------------------------------------------------------------------ */
uInt decimal32IsCanonical(const decimal32 *d32) {
decNumber dn; // work
decimal32 canon; // ..
decContext dc; // ..
decContextDefault(&dc, DEC_INIT_DECIMAL32);
decimal32ToNumber(d32, &dn);
decimal32FromNumber(&canon, &dn, &dc);// canon will now be canonical
return memcmp(d32, &canon, DECIMAL32_Bytes)==0;
} // decimal32IsCanonical
/* ------------------------------------------------------------------ */
/* decimal32Canonical -- copy an encoding, ensuring it is canonical */
/* d32 is the source decimal32 */
/* result is the target (may be the same decimal32) */
/* returns result */
/* No error is possible. */
/* ------------------------------------------------------------------ */
decimal32 * decimal32Canonical(decimal32 *result, const decimal32 *d32) {
decNumber dn; // work
decContext dc; // ..
decContextDefault(&dc, DEC_INIT_DECIMAL32);
decimal32ToNumber(d32, &dn);
decimal32FromNumber(result, &dn, &dc);// result will now be canonical
return result;
} // decimal32Canonical
#if DECTRACE || DECCHECK
/* Macros for accessing decimal32 fields. These assume the argument
is a reference (pointer) to the decimal32 structure, and the
decimal32 is in network byte order (big-endian) */
// Get sign
#define decimal32Sign(d) ((unsigned)(d)->bytes[0]>>7)
// Get combination field
#define decimal32Comb(d) (((d)->bytes[0] & 0x7c)>>2)
// Get exponent continuation [does not remove bias]
#define decimal32ExpCon(d) ((((d)->bytes[0] & 0x03)<<4) \
| ((unsigned)(d)->bytes[1]>>4))
// Set sign [this assumes sign previously 0]
#define decimal32SetSign(d, b) { \
(d)->bytes[0]|=((unsigned)(b)<<7);}
// Set exponent continuation [does not apply bias]
// This assumes range has been checked and exponent previously 0;
// type of exponent must be unsigned
#define decimal32SetExpCon(d, e) { \
(d)->bytes[0]|=(uByte)((e)>>4); \
(d)->bytes[1]|=(uByte)(((e)&0x0F)<<4);}
/* ------------------------------------------------------------------ */
/* decimal32Show -- display a decimal32 in hexadecimal [debug aid] */
/* d32 -- the number to show */
/* ------------------------------------------------------------------ */
// Also shows sign/cob/expconfields extracted - valid bigendian only
void decimal32Show(const decimal32 *d32) {
char buf[DECIMAL32_Bytes*2+1];
Int i, j=0;
if (DECLITEND) {
for (i=0; i<DECIMAL32_Bytes; i++, j+=2) {
sprintf(&buf[j], "%02x", d32->bytes[3-i]);
}
printf(" D32> %s [S:%d Cb:%02x Ec:%02x] LittleEndian\n", buf,
d32->bytes[3]>>7, (d32->bytes[3]>>2)&0x1f,
((d32->bytes[3]&0x3)<<4)| (d32->bytes[2]>>4));
}
else {
for (i=0; i<DECIMAL32_Bytes; i++, j+=2) {
sprintf(&buf[j], "%02x", d32->bytes[i]);
}
printf(" D32> %s [S:%d Cb:%02x Ec:%02x] BigEndian\n", buf,
decimal32Sign(d32), decimal32Comb(d32), decimal32ExpCon(d32));
}
} // decimal32Show
#endif

81
extern/decNumber/decimal32.h vendored Normal file
View File

@ -0,0 +1,81 @@
/* ------------------------------------------------------------------ */
/* Decimal 32-bit format module header */
/* ------------------------------------------------------------------ */
/* Copyright (c) IBM Corporation, 2000, 2006. All rights reserved. */
/* */
/* This software is made available under the terms of the */
/* ICU License -- ICU 1.8.1 and later. */
/* */
/* The description and User's Guide ("The decNumber C Library") for */
/* this software is called decNumber.pdf. This document is */
/* available, together with arithmetic and format specifications, */
/* testcases, and Web links, on the General Decimal Arithmetic page. */
/* */
/* Please send comments, suggestions, and corrections to the author: */
/* mfc@uk.ibm.com */
/* Mike Cowlishaw, IBM Fellow */
/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */
/* ------------------------------------------------------------------ */
#if !defined(DECIMAL32)
#define DECIMAL32
#define DEC32NAME "decimal32" /* Short name */
#define DEC32FULLNAME "Decimal 32-bit Number" /* Verbose name */
#define DEC32AUTHOR "Mike Cowlishaw" /* Who to blame */
/* parameters for decimal32s */
#define DECIMAL32_Bytes 4 /* length */
#define DECIMAL32_Pmax 7 /* maximum precision (digits) */
#define DECIMAL32_Emax 96 /* maximum adjusted exponent */
#define DECIMAL32_Emin -95 /* minimum adjusted exponent */
#define DECIMAL32_Bias 101 /* bias for the exponent */
#define DECIMAL32_String 15 /* maximum string length, +1 */
#define DECIMAL32_EconL 6 /* exp. continuation length */
/* highest biased exponent (Elimit-1) */
#define DECIMAL32_Ehigh (DECIMAL32_Emax+DECIMAL32_Bias-DECIMAL32_Pmax+1)
/* check enough digits, if pre-defined */
#if defined(DECNUMDIGITS)
#if (DECNUMDIGITS<DECIMAL32_Pmax)
#error decimal32.h needs pre-defined DECNUMDIGITS>=7 for safe use
#endif
#endif
#ifndef DECNUMDIGITS
#define DECNUMDIGITS DECIMAL32_Pmax /* size if not already defined*/
#endif
#ifndef DECNUMBER
#include "decNumber.h" /* context and number library */
#endif
/* Decimal 32-bit type, accessible by bytes */
typedef struct {
uint8_t bytes[DECIMAL32_Bytes]; /* decimal32: 1, 5, 6, 20 bits*/
} decimal32;
/* special values [top byte excluding sign bit; last two bits are */
/* don't-care for Infinity on input, last bit don't-care for NaN] */
#if !defined(DECIMAL_NaN)
#define DECIMAL_NaN 0x7c /* 0 11111 00 NaN */
#define DECIMAL_sNaN 0x7e /* 0 11111 10 sNaN */
#define DECIMAL_Inf 0x78 /* 0 11110 00 Infinity */
#endif
/* ---------------------------------------------------------------- */
/* Routines */
/* ---------------------------------------------------------------- */
/* String conversions */
decimal32 * decimal32FromString(decimal32 *, const char *, decContext *);
char * decimal32ToString(const decimal32 *, char *);
char * decimal32ToEngString(const decimal32 *, char *);
/* decNumber conversions */
decimal32 * decimal32FromNumber(decimal32 *, const decNumber *,
decContext *);
decNumber * decimal32ToNumber(const decimal32 *, decNumber *);
/* Format-dependent utilities */
uint32_t decimal32IsCanonical(const decimal32 *);
decimal32 * decimal32Canonical(decimal32 *, const decimal32 *);
#endif

839
extern/decNumber/decimal64.c vendored Normal file
View File

@ -0,0 +1,839 @@
/* ------------------------------------------------------------------ */
/* Decimal 64-bit format module */
/* ------------------------------------------------------------------ */
/* Copyright (c) IBM Corporation, 2000, 2009. All rights reserved. */
/* */
/* This software is made available under the terms of the */
/* ICU License -- ICU 1.8.1 and later. */
/* */
/* The description and User's Guide ("The decNumber C Library") for */
/* this software is called decNumber.pdf. This document is */
/* available, together with arithmetic and format specifications, */
/* testcases, and Web links, on the General Decimal Arithmetic page. */
/* */
/* Please send comments, suggestions, and corrections to the author: */
/* mfc@uk.ibm.com */
/* Mike Cowlishaw, IBM Fellow */
/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */
/* ------------------------------------------------------------------ */
/* This module comprises the routines for decimal64 format numbers. */
/* Conversions are supplied to and from decNumber and String. */
/* */
/* This is used when decNumber provides operations, either for all */
/* operations or as a proxy between decNumber and decSingle. */
/* */
/* Error handling is the same as decNumber (qv.). */
/* ------------------------------------------------------------------ */
#include <string.h> // [for memset/memcpy]
#include <stdio.h> // [for printf]
#define DECNUMDIGITS 16 // make decNumbers with space for 16
#include "decNumber.h" // base number library
#include "decNumberLocal.h" // decNumber local types, etc.
#include "decimal64.h" // our primary include
/* Utility routines and tables [in decimal64.c]; externs for C++ */
// DPD2BIN and the reverse are renamed to prevent link-time conflict
// if decQuad is also built in the same executable
#define DPD2BIN DPD2BINx
#define BIN2DPD BIN2DPDx
extern const uInt COMBEXP[32], COMBMSD[32];
extern const uShort DPD2BIN[1024];
extern const uShort BIN2DPD[1000];
extern const uByte BIN2CHAR[4001];
extern void decDigitsFromDPD(decNumber *, const uInt *, Int);
extern void decDigitsToDPD(const decNumber *, uInt *, Int);
#if DECTRACE || DECCHECK
void decimal64Show(const decimal64 *); // for debug
extern void decNumberShow(const decNumber *); // ..
#endif
/* Useful macro */
// Clear a structure (e.g., a decNumber)
#define DEC_clear(d) memset(d, 0, sizeof(*d))
/* define and include the tables to use for conversions */
#define DEC_BIN2CHAR 1
#define DEC_DPD2BIN 1
#define DEC_BIN2DPD 1 // used for all sizes
#include "decDPD.h" // lookup tables
/* ------------------------------------------------------------------ */
/* decimal64FromNumber -- convert decNumber to decimal64 */
/* */
/* ds is the target decimal64 */
/* dn is the source number (assumed valid) */
/* set is the context, used only for reporting errors */
/* */
/* The set argument is used only for status reporting and for the */
/* rounding mode (used if the coefficient is more than DECIMAL64_Pmax */
/* digits or an overflow is detected). If the exponent is out of the */
/* valid range then Overflow or Underflow will be raised. */
/* After Underflow a subnormal result is possible. */
/* */
/* DEC_Clamped is set if the number has to be 'folded down' to fit, */
/* by reducing its exponent and multiplying the coefficient by a */
/* power of ten, or if the exponent on a zero had to be clamped. */
/* ------------------------------------------------------------------ */
decimal64 * decimal64FromNumber(decimal64 *d64, const decNumber *dn,
decContext *set) {
uInt status=0; // status accumulator
Int ae; // adjusted exponent
decNumber dw; // work
decContext dc; // ..
uInt comb, exp; // ..
uInt uiwork; // for macros
uInt targar[2]={0, 0}; // target 64-bit
#define targhi targar[1] // name the word with the sign
#define targlo targar[0] // and the other
// If the number has too many digits, or the exponent could be
// out of range then reduce the number under the appropriate
// constraints. This could push the number to Infinity or zero,
// so this check and rounding must be done before generating the
// decimal64]
ae=dn->exponent+dn->digits-1; // [0 if special]
if (dn->digits>DECIMAL64_Pmax // too many digits
|| ae>DECIMAL64_Emax // likely overflow
|| ae<DECIMAL64_Emin) { // likely underflow
decContextDefault(&dc, DEC_INIT_DECIMAL64); // [no traps]
dc.round=set->round; // use supplied rounding
decNumberPlus(&dw, dn, &dc); // (round and check)
// [this changes -0 to 0, so enforce the sign...]
dw.bits|=dn->bits&DECNEG;
status=dc.status; // save status
dn=&dw; // use the work number
} // maybe out of range
if (dn->bits&DECSPECIAL) { // a special value
if (dn->bits&DECINF) targhi=DECIMAL_Inf<<24;
else { // sNaN or qNaN
if ((*dn->lsu!=0 || dn->digits>1) // non-zero coefficient
&& (dn->digits<DECIMAL64_Pmax)) { // coefficient fits
decDigitsToDPD(dn, targar, 0);
}
if (dn->bits&DECNAN) targhi|=DECIMAL_NaN<<24;
else targhi|=DECIMAL_sNaN<<24;
} // a NaN
} // special
else { // is finite
if (decNumberIsZero(dn)) { // is a zero
// set and clamp exponent
if (dn->exponent<-DECIMAL64_Bias) {
exp=0; // low clamp
status|=DEC_Clamped;
}
else {
exp=dn->exponent+DECIMAL64_Bias; // bias exponent
if (exp>DECIMAL64_Ehigh) { // top clamp
exp=DECIMAL64_Ehigh;
status|=DEC_Clamped;
}
}
comb=(exp>>5) & 0x18; // msd=0, exp top 2 bits ..
}
else { // non-zero finite number
uInt msd; // work
Int pad=0; // coefficient pad digits
// the dn is known to fit, but it may need to be padded
exp=(uInt)(dn->exponent+DECIMAL64_Bias); // bias exponent
if (exp>DECIMAL64_Ehigh) { // fold-down case
pad=exp-DECIMAL64_Ehigh;
exp=DECIMAL64_Ehigh; // [to maximum]
status|=DEC_Clamped;
}
// fastpath common case
if (DECDPUN==3 && pad==0) {
uInt dpd[6]={0,0,0,0,0,0};
uInt i;
Int d=dn->digits;
for (i=0; d>0; i++, d-=3) dpd[i]=BIN2DPD[dn->lsu[i]];
targlo =dpd[0];
targlo|=dpd[1]<<10;
targlo|=dpd[2]<<20;
if (dn->digits>6) {
targlo|=dpd[3]<<30;
targhi =dpd[3]>>2;
targhi|=dpd[4]<<8;
}
msd=dpd[5]; // [did not really need conversion]
}
else { // general case
decDigitsToDPD(dn, targar, pad);
// save and clear the top digit
msd=targhi>>18;
targhi&=0x0003ffff;
}
// create the combination field
if (msd>=8) comb=0x18 | ((exp>>7) & 0x06) | (msd & 0x01);
else comb=((exp>>5) & 0x18) | msd;
}
targhi|=comb<<26; // add combination field ..
targhi|=(exp&0xff)<<18; // .. and exponent continuation
} // finite
if (dn->bits&DECNEG) targhi|=0x80000000; // add sign bit
// now write to storage; this is now always endian
if (DECLITEND) {
// lo int then hi
UBFROMUI(d64->bytes, targar[0]);
UBFROMUI(d64->bytes+4, targar[1]);
}
else {
// hi int then lo
UBFROMUI(d64->bytes, targar[1]);
UBFROMUI(d64->bytes+4, targar[0]);
}
if (status!=0) decContextSetStatus(set, status); // pass on status
// decimal64Show(d64);
return d64;
} // decimal64FromNumber
/* ------------------------------------------------------------------ */
/* decimal64ToNumber -- convert decimal64 to decNumber */
/* d64 is the source decimal64 */
/* dn is the target number, with appropriate space */
/* No error is possible. */
/* ------------------------------------------------------------------ */
decNumber * decimal64ToNumber(const decimal64 *d64, decNumber *dn) {
uInt msd; // coefficient MSD
uInt exp; // exponent top two bits
uInt comb; // combination field
Int need; // work
uInt uiwork; // for macros
uInt sourar[2]; // source 64-bit
#define sourhi sourar[1] // name the word with the sign
#define sourlo sourar[0] // and the lower word
// load source from storage; this is endian
if (DECLITEND) {
sourlo=UBTOUI(d64->bytes ); // directly load the low int
sourhi=UBTOUI(d64->bytes+4); // then the high int
}
else {
sourhi=UBTOUI(d64->bytes ); // directly load the high int
sourlo=UBTOUI(d64->bytes+4); // then the low int
}
comb=(sourhi>>26)&0x1f; // combination field
decNumberZero(dn); // clean number
if (sourhi&0x80000000) dn->bits=DECNEG; // set sign if negative
msd=COMBMSD[comb]; // decode the combination field
exp=COMBEXP[comb]; // ..
if (exp==3) { // is a special
if (msd==0) {
dn->bits|=DECINF;
return dn; // no coefficient needed
}
else if (sourhi&0x02000000) dn->bits|=DECSNAN;
else dn->bits|=DECNAN;
msd=0; // no top digit
}
else { // is a finite number
dn->exponent=(exp<<8)+((sourhi>>18)&0xff)-DECIMAL64_Bias; // unbiased
}
// get the coefficient
sourhi&=0x0003ffff; // clean coefficient continuation
if (msd) { // non-zero msd
sourhi|=msd<<18; // prefix to coefficient
need=6; // process 6 declets
}
else { // msd=0
if (!sourhi) { // top word 0
if (!sourlo) return dn; // easy: coefficient is 0
need=3; // process at least 3 declets
if (sourlo&0xc0000000) need++; // process 4 declets
// [could reduce some more, here]
}
else { // some bits in top word, msd=0
need=4; // process at least 4 declets
if (sourhi&0x0003ff00) need++; // top declet!=0, process 5
}
} //msd=0
decDigitsFromDPD(dn, sourar, need); // process declets
return dn;
} // decimal64ToNumber
/* ------------------------------------------------------------------ */
/* to-scientific-string -- conversion to numeric string */
/* to-engineering-string -- conversion to numeric string */
/* */
/* decimal64ToString(d64, string); */
/* decimal64ToEngString(d64, string); */
/* */
/* d64 is the decimal64 format number to convert */
/* string is the string where the result will be laid out */
/* */
/* string must be at least 24 characters */
/* */
/* No error is possible, and no status can be set. */
/* ------------------------------------------------------------------ */
char * decimal64ToEngString(const decimal64 *d64, char *string){
decNumber dn; // work
decimal64ToNumber(d64, &dn);
decNumberToEngString(&dn, string);
return string;
} // decimal64ToEngString
char * decimal64ToString(const decimal64 *d64, char *string){
uInt msd; // coefficient MSD
Int exp; // exponent top two bits or full
uInt comb; // combination field
char *cstart; // coefficient start
char *c; // output pointer in string
const uByte *u; // work
char *s, *t; // .. (source, target)
Int dpd; // ..
Int pre, e; // ..
uInt uiwork; // for macros
uInt sourar[2]; // source 64-bit
#define sourhi sourar[1] // name the word with the sign
#define sourlo sourar[0] // and the lower word
// load source from storage; this is endian
if (DECLITEND) {
sourlo=UBTOUI(d64->bytes ); // directly load the low int
sourhi=UBTOUI(d64->bytes+4); // then the high int
}
else {
sourhi=UBTOUI(d64->bytes ); // directly load the high int
sourlo=UBTOUI(d64->bytes+4); // then the low int
}
c=string; // where result will go
if (((Int)sourhi)<0) *c++='-'; // handle sign
comb=(sourhi>>26)&0x1f; // combination field
msd=COMBMSD[comb]; // decode the combination field
exp=COMBEXP[comb]; // ..
if (exp==3) {
if (msd==0) { // infinity
strcpy(c, "Inf");
strcpy(c+3, "inity");
return string; // easy
}
if (sourhi&0x02000000) *c++='s'; // sNaN
strcpy(c, "NaN"); // complete word
c+=3; // step past
if (sourlo==0 && (sourhi&0x0003ffff)==0) return string; // zero payload
// otherwise drop through to add integer; set correct exp
exp=0; msd=0; // setup for following code
}
else exp=(exp<<8)+((sourhi>>18)&0xff)-DECIMAL64_Bias;
// convert 16 digits of significand to characters
cstart=c; // save start of coefficient
if (msd) *c++='0'+(char)msd; // non-zero most significant digit
// Now decode the declets. After extracting each one, it is
// decoded to binary and then to a 4-char sequence by table lookup;
// the 4-chars are a 1-char length (significant digits, except 000
// has length 0). This allows us to left-align the first declet
// with non-zero content, then remaining ones are full 3-char
// length. We use fixed-length memcpys because variable-length
// causes a subroutine call in GCC. (These are length 4 for speed
// and are safe because the array has an extra terminator byte.)
#define dpd2char u=&BIN2CHAR[DPD2BIN[dpd]*4]; \
if (c!=cstart) {memcpy(c, u+1, 4); c+=3;} \
else if (*u) {memcpy(c, u+4-*u, 4); c+=*u;}
dpd=(sourhi>>8)&0x3ff; // declet 1
dpd2char;
dpd=((sourhi&0xff)<<2) | (sourlo>>30); // declet 2
dpd2char;
dpd=(sourlo>>20)&0x3ff; // declet 3
dpd2char;
dpd=(sourlo>>10)&0x3ff; // declet 4
dpd2char;
dpd=(sourlo)&0x3ff; // declet 5
dpd2char;
if (c==cstart) *c++='0'; // all zeros -- make 0
if (exp==0) { // integer or NaN case -- easy
*c='\0'; // terminate
return string;
}
/* non-0 exponent */
e=0; // assume no E
pre=c-cstart+exp;
// [here, pre-exp is the digits count (==1 for zero)]
if (exp>0 || pre<-5) { // need exponential form
e=pre-1; // calculate E value
pre=1; // assume one digit before '.'
} // exponential form
/* modify the coefficient, adding 0s, '.', and E+nn as needed */
s=c-1; // source (LSD)
if (pre>0) { // ddd.ddd (plain), perhaps with E
char *dotat=cstart+pre;
if (dotat<c) { // if embedded dot needed...
t=c; // target
for (; s>=dotat; s--, t--) *t=*s; // open the gap; leave t at gap
*t='.'; // insert the dot
c++; // length increased by one
}
// finally add the E-part, if needed; it will never be 0, and has
// a maximum length of 3 digits
if (e!=0) {
*c++='E'; // starts with E
*c++='+'; // assume positive
if (e<0) {
*(c-1)='-'; // oops, need '-'
e=-e; // uInt, please
}
u=&BIN2CHAR[e*4]; // -> length byte
memcpy(c, u+4-*u, 4); // copy fixed 4 characters [is safe]
c+=*u; // bump pointer appropriately
}
*c='\0'; // add terminator
//printf("res %s\n", string);
return string;
} // pre>0
/* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (can never have E) */
t=c+1-pre;
*(t+1)='\0'; // can add terminator now
for (; s>=cstart; s--, t--) *t=*s; // shift whole coefficient right
c=cstart;
*c++='0'; // always starts with 0.
*c++='.';
for (; pre<0; pre++) *c++='0'; // add any 0's after '.'
//printf("res %s\n", string);
return string;
} // decimal64ToString
/* ------------------------------------------------------------------ */
/* to-number -- conversion from numeric string */
/* */
/* decimal64FromString(result, string, set); */
/* */
/* result is the decimal64 format number which gets the result of */
/* the conversion */
/* *string is the character string which should contain a valid */
/* number (which may be a special value) */
/* set is the context */
/* */
/* The context is supplied to this routine is used for error handling */
/* (setting of status and traps) and for the rounding mode, only. */
/* If an error occurs, the result will be a valid decimal64 NaN. */
/* ------------------------------------------------------------------ */
decimal64 * decimal64FromString(decimal64 *result, const char *string,
decContext *set) {
decContext dc; // work
decNumber dn; // ..
decContextDefault(&dc, DEC_INIT_DECIMAL64); // no traps, please
dc.round=set->round; // use supplied rounding
decNumberFromString(&dn, string, &dc); // will round if needed
decimal64FromNumber(result, &dn, &dc);
if (dc.status!=0) { // something happened
decContextSetStatus(set, dc.status); // .. pass it on
}
return result;
} // decimal64FromString
/* ------------------------------------------------------------------ */
/* decimal64IsCanonical -- test whether encoding is canonical */
/* d64 is the source decimal64 */
/* returns 1 if the encoding of d64 is canonical, 0 otherwise */
/* No error is possible. */
/* ------------------------------------------------------------------ */
uInt decimal64IsCanonical(const decimal64 *d64) {
decNumber dn; // work
decimal64 canon; // ..
decContext dc; // ..
decContextDefault(&dc, DEC_INIT_DECIMAL64);
decimal64ToNumber(d64, &dn);
decimal64FromNumber(&canon, &dn, &dc);// canon will now be canonical
return memcmp(d64, &canon, DECIMAL64_Bytes)==0;
} // decimal64IsCanonical
/* ------------------------------------------------------------------ */
/* decimal64Canonical -- copy an encoding, ensuring it is canonical */
/* d64 is the source decimal64 */
/* result is the target (may be the same decimal64) */
/* returns result */
/* No error is possible. */
/* ------------------------------------------------------------------ */
decimal64 * decimal64Canonical(decimal64 *result, const decimal64 *d64) {
decNumber dn; // work
decContext dc; // ..
decContextDefault(&dc, DEC_INIT_DECIMAL64);
decimal64ToNumber(d64, &dn);
decimal64FromNumber(result, &dn, &dc);// result will now be canonical
return result;
} // decimal64Canonical
#if DECTRACE || DECCHECK
/* Macros for accessing decimal64 fields. These assume the
argument is a reference (pointer) to the decimal64 structure,
and the decimal64 is in network byte order (big-endian) */
// Get sign
#define decimal64Sign(d) ((unsigned)(d)->bytes[0]>>7)
// Get combination field
#define decimal64Comb(d) (((d)->bytes[0] & 0x7c)>>2)
// Get exponent continuation [does not remove bias]
#define decimal64ExpCon(d) ((((d)->bytes[0] & 0x03)<<6) \
| ((unsigned)(d)->bytes[1]>>2))
// Set sign [this assumes sign previously 0]
#define decimal64SetSign(d, b) { \
(d)->bytes[0]|=((unsigned)(b)<<7);}
// Set exponent continuation [does not apply bias]
// This assumes range has been checked and exponent previously 0;
// type of exponent must be unsigned
#define decimal64SetExpCon(d, e) { \
(d)->bytes[0]|=(uByte)((e)>>6); \
(d)->bytes[1]|=(uByte)(((e)&0x3F)<<2);}
/* ------------------------------------------------------------------ */
/* decimal64Show -- display a decimal64 in hexadecimal [debug aid] */
/* d64 -- the number to show */
/* ------------------------------------------------------------------ */
// Also shows sign/cob/expconfields extracted
void decimal64Show(const decimal64 *d64) {
char buf[DECIMAL64_Bytes*2+1];
Int i, j=0;
if (DECLITEND) {
for (i=0; i<DECIMAL64_Bytes; i++, j+=2) {
sprintf(&buf[j], "%02x", d64->bytes[7-i]);
}
printf(" D64> %s [S:%d Cb:%02x Ec:%02x] LittleEndian\n", buf,
d64->bytes[7]>>7, (d64->bytes[7]>>2)&0x1f,
((d64->bytes[7]&0x3)<<6)| (d64->bytes[6]>>2));
}
else { // big-endian
for (i=0; i<DECIMAL64_Bytes; i++, j+=2) {
sprintf(&buf[j], "%02x", d64->bytes[i]);
}
printf(" D64> %s [S:%d Cb:%02x Ec:%02x] BigEndian\n", buf,
decimal64Sign(d64), decimal64Comb(d64), decimal64ExpCon(d64));
}
} // decimal64Show
#endif
/* ================================================================== */
/* Shared utility routines and tables */
/* ================================================================== */
// define and include the conversion tables to use for shared code
#if DECDPUN==3
#define DEC_DPD2BIN 1
#else
#define DEC_DPD2BCD 1
#endif
#include "decDPD.h" // lookup tables
// The maximum number of decNumberUnits needed for a working copy of
// the units array is the ceiling of digits/DECDPUN, where digits is
// the maximum number of digits in any of the formats for which this
// is used. decimal128.h must not be included in this module, so, as
// a very special case, that number is defined as a literal here.
#define DECMAX754 34
#define DECMAXUNITS ((DECMAX754+DECDPUN-1)/DECDPUN)
/* ------------------------------------------------------------------ */
/* Combination field lookup tables (uInts to save measurable work) */
/* */
/* COMBEXP - 2-bit most-significant-bits of exponent */
/* [11 if an Infinity or NaN] */
/* COMBMSD - 4-bit most-significant-digit */
/* [0=Infinity, 1=NaN if COMBEXP=11] */
/* */
/* Both are indexed by the 5-bit combination field (0-31) */
/* ------------------------------------------------------------------ */
const uInt COMBEXP[32]={0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1,
2, 2, 2, 2, 2, 2, 2, 2,
0, 0, 1, 1, 2, 2, 3, 3};
const uInt COMBMSD[32]={0, 1, 2, 3, 4, 5, 6, 7,
0, 1, 2, 3, 4, 5, 6, 7,
0, 1, 2, 3, 4, 5, 6, 7,
8, 9, 8, 9, 8, 9, 0, 1};
/* ------------------------------------------------------------------ */
/* decDigitsToDPD -- pack coefficient into DPD form */
/* */
/* dn is the source number (assumed valid, max DECMAX754 digits) */
/* targ is 1, 2, or 4-element uInt array, which the caller must */
/* have cleared to zeros */
/* shift is the number of 0 digits to add on the right (normally 0) */
/* */
/* The coefficient must be known small enough to fit. The full */
/* coefficient is copied, including the leading 'odd' digit. This */
/* digit is retrieved and packed into the combination field by the */
/* caller. */
/* */
/* The target uInts are altered only as necessary to receive the */
/* digits of the decNumber. When more than one uInt is needed, they */
/* are filled from left to right (that is, the uInt at offset 0 will */
/* end up with the least-significant digits). */
/* */
/* shift is used for 'fold-down' padding. */
/* */
/* No error is possible. */
/* ------------------------------------------------------------------ */
#if DECDPUN<=4
// Constant multipliers for divide-by-power-of five using reciprocal
// multiply, after removing powers of 2 by shifting, and final shift
// of 17 [we only need up to **4]
static const uInt multies[]={131073, 26215, 5243, 1049, 210};
// QUOT10 -- macro to return the quotient of unit u divided by 10**n
#define QUOT10(u, n) ((((uInt)(u)>>(n))*multies[n])>>17)
#endif
void decDigitsToDPD(const decNumber *dn, uInt *targ, Int shift) {
Int cut; // work
Int n; // output bunch counter
Int digits=dn->digits; // digit countdown
uInt dpd; // densely packed decimal value
uInt bin; // binary value 0-999
uInt *uout=targ; // -> current output uInt
uInt uoff=0; // -> current output offset [from right]
const Unit *inu=dn->lsu; // -> current input unit
Unit uar[DECMAXUNITS]; // working copy of units, iff shifted
#if DECDPUN!=3 // not fast path
Unit in; // current unit
#endif
if (shift!=0) { // shift towards most significant required
// shift the units array to the left by pad digits and copy
// [this code is a special case of decShiftToMost, which could
// be used instead if exposed and the array were copied first]
const Unit *source; // ..
Unit *target, *first; // ..
uInt next=0; // work
source=dn->lsu+D2U(digits)-1; // where msu comes from
target=uar+D2U(digits)-1+D2U(shift);// where upper part of first cut goes
cut=DECDPUN-MSUDIGITS(shift); // where to slice
if (cut==0) { // unit-boundary case
for (; source>=dn->lsu; source--, target--) *target=*source;
}
else {
first=uar+D2U(digits+shift)-1; // where msu will end up
for (; source>=dn->lsu; source--, target--) {
// split the source Unit and accumulate remainder for next
#if DECDPUN<=4
uInt quot=QUOT10(*source, cut);
uInt rem=*source-quot*DECPOWERS[cut];
next+=quot;
#else
uInt rem=*source%DECPOWERS[cut];
next+=*source/DECPOWERS[cut];
#endif
if (target<=first) *target=(Unit)next; // write to target iff valid
next=rem*DECPOWERS[DECDPUN-cut]; // save remainder for next Unit
}
} // shift-move
// propagate remainder to one below and clear the rest
for (; target>=uar; target--) {
*target=(Unit)next;
next=0;
}
digits+=shift; // add count (shift) of zeros added
inu=uar; // use units in working array
}
/* now densely pack the coefficient into DPD declets */
#if DECDPUN!=3 // not fast path
in=*inu; // current unit
cut=0; // at lowest digit
bin=0; // [keep compiler quiet]
#endif
for(n=0; digits>0; n++) { // each output bunch
#if DECDPUN==3 // fast path, 3-at-a-time
bin=*inu; // 3 digits ready for convert
digits-=3; // [may go negative]
inu++; // may need another
#else // must collect digit-by-digit
Unit dig; // current digit
Int j; // digit-in-declet count
for (j=0; j<3; j++) {
#if DECDPUN<=4
Unit temp=(Unit)((uInt)(in*6554)>>16);
dig=(Unit)(in-X10(temp));
in=temp;
#else
dig=in%10;
in=in/10;
#endif
if (j==0) bin=dig;
else if (j==1) bin+=X10(dig);
else /* j==2 */ bin+=X100(dig);
digits--;
if (digits==0) break; // [also protects *inu below]
cut++;
if (cut==DECDPUN) {inu++; in=*inu; cut=0;}
}
#endif
// here there are 3 digits in bin, or have used all input digits
dpd=BIN2DPD[bin];
// write declet to uInt array
*uout|=dpd<<uoff;
uoff+=10;
if (uoff<32) continue; // no uInt boundary cross
uout++;
uoff-=32;
*uout|=dpd>>(10-uoff); // collect top bits
} // n declets
return;
} // decDigitsToDPD
/* ------------------------------------------------------------------ */
/* decDigitsFromDPD -- unpack a format's coefficient */
/* */
/* dn is the target number, with 7, 16, or 34-digit space. */
/* sour is a 1, 2, or 4-element uInt array containing only declets */
/* declets is the number of (right-aligned) declets in sour to */
/* be processed. This may be 1 more than the obvious number in */
/* a format, as any top digit is prefixed to the coefficient */
/* continuation field. It also may be as small as 1, as the */
/* caller may pre-process leading zero declets. */
/* */
/* When doing the 'extra declet' case care is taken to avoid writing */
/* extra digits when there are leading zeros, as these could overflow */
/* the units array when DECDPUN is not 3. */
/* */
/* The target uInts are used only as necessary to process declets */
/* declets into the decNumber. When more than one uInt is needed, */
/* they are used from left to right (that is, the uInt at offset 0 */
/* provides the least-significant digits). */
/* */
/* dn->digits is set, but not the sign or exponent. */
/* No error is possible [the redundant 888 codes are allowed]. */
/* ------------------------------------------------------------------ */
void decDigitsFromDPD(decNumber *dn, const uInt *sour, Int declets) {
uInt dpd; // collector for 10 bits
Int n; // counter
Unit *uout=dn->lsu; // -> current output unit
Unit *last=uout; // will be unit containing msd
const uInt *uin=sour; // -> current input uInt
uInt uoff=0; // -> current input offset [from right]
#if DECDPUN!=3
uInt bcd; // BCD result
uInt nibble; // work
Unit out=0; // accumulator
Int cut=0; // power of ten in current unit
#endif
#if DECDPUN>4
uInt const *pow; // work
#endif
// Expand the densely-packed integer, right to left
for (n=declets-1; n>=0; n--) { // count down declets of 10 bits
dpd=*uin>>uoff;
uoff+=10;
if (uoff>32) { // crossed uInt boundary
uin++;
uoff-=32; // [if using this code for wider, check this]
dpd|=*uin<<(10-uoff); // get waiting bits
}
dpd&=0x3ff; // clear uninteresting bits
#if DECDPUN==3
if (dpd==0) *uout=0;
else {
*uout=DPD2BIN[dpd]; // convert 10 bits to binary 0-999
last=uout; // record most significant unit
}
uout++;
} // n
#else // DECDPUN!=3
if (dpd==0) { // fastpath [e.g., leading zeros]
// write out three 0 digits (nibbles); out may have digit(s)
cut++;
if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;}
if (n==0) break; // [as below, works even if MSD=0]
cut++;
if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;}
cut++;
if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;}
continue;
}
bcd=DPD2BCD[dpd]; // convert 10 bits to 12 bits BCD
// now accumulate the 3 BCD nibbles into units
nibble=bcd & 0x00f;
if (nibble) out=(Unit)(out+nibble*DECPOWERS[cut]);
cut++;
if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;}
bcd>>=4;
// if this is the last declet and the remaining nibbles in bcd
// are 00 then process no more nibbles, because this could be
// the 'odd' MSD declet and writing any more Units would then
// overflow the unit array
if (n==0 && !bcd) break;
nibble=bcd & 0x00f;
if (nibble) out=(Unit)(out+nibble*DECPOWERS[cut]);
cut++;
if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;}
bcd>>=4;
nibble=bcd & 0x00f;
if (nibble) out=(Unit)(out+nibble*DECPOWERS[cut]);
cut++;
if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;}
} // n
if (cut!=0) { // some more left over
*uout=out; // write out final unit
if (out) last=uout; // and note if non-zero
}
#endif
// here, last points to the most significant unit with digits;
// inspect it to get the final digits count -- this is essentially
// the same code as decGetDigits in decNumber.c
dn->digits=(last-dn->lsu)*DECDPUN+1; // floor of digits, plus
// must be at least 1 digit
#if DECDPUN>1
if (*last<10) return; // common odd digit or 0
dn->digits++; // must be 2 at least
#if DECDPUN>2
if (*last<100) return; // 10-99
dn->digits++; // must be 3 at least
#if DECDPUN>3
if (*last<1000) return; // 100-999
dn->digits++; // must be 4 at least
#if DECDPUN>4
for (pow=&DECPOWERS[4]; *last>=*pow; pow++) dn->digits++;
#endif
#endif
#endif
#endif
return;
} //decDigitsFromDPD

83
extern/decNumber/decimal64.h vendored Normal file
View File

@ -0,0 +1,83 @@
/* ------------------------------------------------------------------ */
/* Decimal 64-bit format module header */
/* ------------------------------------------------------------------ */
/* Copyright (c) IBM Corporation, 2000, 2005. All rights reserved. */
/* */
/* This software is made available under the terms of the */
/* ICU License -- ICU 1.8.1 and later. */
/* */
/* The description and User's Guide ("The decNumber C Library") for */
/* this software is called decNumber.pdf. This document is */
/* available, together with arithmetic and format specifications, */
/* testcases, and Web links, on the General Decimal Arithmetic page. */
/* */
/* Please send comments, suggestions, and corrections to the author: */
/* mfc@uk.ibm.com */
/* Mike Cowlishaw, IBM Fellow */
/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */
/* ------------------------------------------------------------------ */
#if !defined(DECIMAL64)
#define DECIMAL64
#define DEC64NAME "decimal64" /* Short name */
#define DEC64FULLNAME "Decimal 64-bit Number" /* Verbose name */
#define DEC64AUTHOR "Mike Cowlishaw" /* Who to blame */
/* parameters for decimal64s */
#define DECIMAL64_Bytes 8 /* length */
#define DECIMAL64_Pmax 16 /* maximum precision (digits) */
#define DECIMAL64_Emax 384 /* maximum adjusted exponent */
#define DECIMAL64_Emin -383 /* minimum adjusted exponent */
#define DECIMAL64_Bias 398 /* bias for the exponent */
#define DECIMAL64_String 24 /* maximum string length, +1 */
#define DECIMAL64_EconL 8 /* exp. continuation length */
/* highest biased exponent (Elimit-1) */
#define DECIMAL64_Ehigh (DECIMAL64_Emax+DECIMAL64_Bias-DECIMAL64_Pmax+1)
/* check enough digits, if pre-defined */
#if defined(DECNUMDIGITS)
#if (DECNUMDIGITS<DECIMAL64_Pmax)
#error decimal64.h needs pre-defined DECNUMDIGITS>=16 for safe use
#endif
#endif
#ifndef DECNUMDIGITS
#define DECNUMDIGITS DECIMAL64_Pmax /* size if not already defined*/
#endif
#ifndef DECNUMBER
#include "decNumber.h" /* context and number library */
#endif
/* Decimal 64-bit type, accessible by bytes */
typedef struct {
uint8_t bytes[DECIMAL64_Bytes]; /* decimal64: 1, 5, 8, 50 bits*/
} decimal64;
/* special values [top byte excluding sign bit; last two bits are */
/* don't-care for Infinity on input, last bit don't-care for NaN] */
#if !defined(DECIMAL_NaN)
#define DECIMAL_NaN 0x7c /* 0 11111 00 NaN */
#define DECIMAL_sNaN 0x7e /* 0 11111 10 sNaN */
#define DECIMAL_Inf 0x78 /* 0 11110 00 Infinity */
#endif
/* ---------------------------------------------------------------- */
/* Routines */
/* ---------------------------------------------------------------- */
/* String conversions */
decimal64 * decimal64FromString(decimal64 *, const char *, decContext *);
char * decimal64ToString(const decimal64 *, char *);
char * decimal64ToEngString(const decimal64 *, char *);
/* decNumber conversions */
decimal64 * decimal64FromNumber(decimal64 *, const decNumber *,
decContext *);
decNumber * decimal64ToNumber(const decimal64 *, decNumber *);
/* Format-dependent utilities */
uint32_t decimal64IsCanonical(const decimal64 *);
decimal64 * decimal64Canonical(decimal64 *, const decimal64 *);
#endif

BIN
extern/decNumber/decnumber.pdf vendored Normal file

Binary file not shown.

View File

@ -0,0 +1,28 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.31101.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "decNumber", "decNumber_MSVC12.vcxproj", "{BE4D2DDC-59A0-4CD7-848E-231E13785335}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{BE4D2DDC-59A0-4CD7-848E-231E13785335}.Debug|Win32.ActiveCfg = Debug|Win32
{BE4D2DDC-59A0-4CD7-848E-231E13785335}.Debug|Win32.Build.0 = Debug|Win32
{BE4D2DDC-59A0-4CD7-848E-231E13785335}.Debug|x64.ActiveCfg = Debug|x64
{BE4D2DDC-59A0-4CD7-848E-231E13785335}.Debug|x64.Build.0 = Debug|x64
{BE4D2DDC-59A0-4CD7-848E-231E13785335}.Release|Win32.ActiveCfg = Release|Win32
{BE4D2DDC-59A0-4CD7-848E-231E13785335}.Release|Win32.Build.0 = Release|Win32
{BE4D2DDC-59A0-4CD7-848E-231E13785335}.Release|x64.ActiveCfg = Release|x64
{BE4D2DDC-59A0-4CD7-848E-231E13785335}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,267 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\decBasic.c">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\decCommon.c">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\decContext.c" />
<ClCompile Include="..\decDouble.c" />
<ClCompile Include="..\decimal128.c" />
<ClCompile Include="..\decimal32.c" />
<ClCompile Include="..\decimal64.c" />
<ClCompile Include="..\decNumber.c" />
<ClCompile Include="..\decPacked.c" />
<ClCompile Include="..\decQuad.c" />
<ClCompile Include="..\decSingle.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\decContext.h" />
<ClInclude Include="..\decDouble.h" />
<ClInclude Include="..\decDPD.h" />
<ClInclude Include="..\decimal128.h" />
<ClInclude Include="..\decimal32.h" />
<ClInclude Include="..\decimal64.h" />
<ClInclude Include="..\decNumber.h" />
<ClInclude Include="..\decNumberLocal.h" />
<ClInclude Include="..\decPacked.h" />
<ClInclude Include="..\decQuad.h" />
<ClInclude Include="..\decSingle.h" />
</ItemGroup>
<ItemGroup>
<Text Include="..\readme.txt" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectName>decNumber</ProjectName>
<ProjectGuid>{BE4D2DDC-59A0-4CD7-848E-231E13785335}</ProjectGuid>
<RootNamespace>decNumber</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v120_xp</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v120_xp</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\lib\$(Platform)\$(Configuration)\</OutDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\lib\$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\temp\$(Platform)\$(Configuration)\</IntDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\temp\$(Platform)\$(Configuration)\</IntDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\lib\$(Platform)\$(Configuration)\</OutDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\lib\$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\temp\$(Platform)\$(Configuration)\</IntDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\temp\$(Platform)\$(Configuration)\</IntDir>
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
<TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">decnumber</TargetName>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">decnumber</TargetName>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">decnumber</TargetName>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">decnumber</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeaderOutputFile>
</PrecompiledHeaderOutputFile>
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
<ObjectFileName>$(IntDir)</ObjectFileName>
<ProgramDataBaseFileName>$(IntDir)</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<PrecompiledHeaderFile>
</PrecompiledHeaderFile>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x0409</Culture>
</ResourceCompile>
<Lib>
<OutputFile>$(OutDir)\$(TargetFileName)</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
</Lib>
<Bscmake>
<SuppressStartupBanner>true</SuppressStartupBanner>
<OutputFile>.\Debug/libtommath.bsc</OutputFile>
</Bscmake>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeaderOutputFile>
</PrecompiledHeaderOutputFile>
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
<ObjectFileName>$(IntDir)</ObjectFileName>
<ProgramDataBaseFileName>$(IntDir)</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<PrecompiledHeaderFile>
</PrecompiledHeaderFile>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x0409</Culture>
</ResourceCompile>
<Lib>
<OutputFile>$(OutDir)\$(TargetFileName)</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
</Lib>
<Bscmake>
<SuppressStartupBanner>true</SuppressStartupBanner>
<OutputFile>.\Debug/libtommath.bsc</OutputFile>
</Bscmake>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeaderOutputFile>
</PrecompiledHeaderOutputFile>
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
<ObjectFileName>$(IntDir)</ObjectFileName>
<ProgramDataBaseFileName>$(IntDir)</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
<PrecompiledHeaderFile>
</PrecompiledHeaderFile>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x0409</Culture>
</ResourceCompile>
<Lib>
<OutputFile>$(OutDir)\$(TargetFileName)</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
</Lib>
<Bscmake>
<SuppressStartupBanner>true</SuppressStartupBanner>
<OutputFile>.\Release/libtommath.bsc</OutputFile>
</Bscmake>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeaderOutputFile>
</PrecompiledHeaderOutputFile>
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
<ObjectFileName>$(IntDir)</ObjectFileName>
<ProgramDataBaseFileName>$(IntDir)</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
<PrecompiledHeaderFile>
</PrecompiledHeaderFile>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x0409</Culture>
</ResourceCompile>
<Lib>
<OutputFile>$(OutDir)\$(TargetFileName)</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
</Lib>
<Bscmake>
<SuppressStartupBanner>true</SuppressStartupBanner>
<OutputFile>.\Release/libtommath.bsc</OutputFile>
</Bscmake>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="..\decBasic.c">
<Filter>Source files</Filter>
</ClCompile>
<ClCompile Include="..\decCommon.c">
<Filter>Source files</Filter>
</ClCompile>
<ClCompile Include="..\decContext.c">
<Filter>Source files</Filter>
</ClCompile>
<ClCompile Include="..\decDouble.c">
<Filter>Source files</Filter>
</ClCompile>
<ClCompile Include="..\decimal32.c">
<Filter>Source files</Filter>
</ClCompile>
<ClCompile Include="..\decimal64.c">
<Filter>Source files</Filter>
</ClCompile>
<ClCompile Include="..\decimal128.c">
<Filter>Source files</Filter>
</ClCompile>
<ClCompile Include="..\decNumber.c">
<Filter>Source files</Filter>
</ClCompile>
<ClCompile Include="..\decPacked.c">
<Filter>Source files</Filter>
</ClCompile>
<ClCompile Include="..\decSingle.c">
<Filter>Source files</Filter>
</ClCompile>
<ClCompile Include="..\decQuad.c">
<Filter>Source files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\decContext.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="..\decDouble.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="..\decDPD.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="..\decimal32.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="..\decimal64.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="..\decimal128.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="..\decNumber.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="..\decNumberLocal.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="..\decPacked.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="..\decQuad.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="..\decSingle.h">
<Filter>Header files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Text Include="..\readme.txt" />
</ItemGroup>
<ItemGroup>
<Filter Include="Source files">
<UniqueIdentifier>{638ba91b-1def-4094-a692-752b2ce6f461}</UniqueIdentifier>
</Filter>
<Filter Include="Header files">
<UniqueIdentifier>{ffbb5d93-e379-40ba-ab58-c62e9e20c810}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>

81
extern/decNumber/readme.txt vendored Normal file
View File

@ -0,0 +1,81 @@
This is the readme.txt for the decNumber package. It includes
instructions for compiling and testing the package; please read them.
---------------------------------------------------------------------
decNumber is distributed in two forms; as a complete package from
the International Components for Unicode (ICU) site (under an as-is
license), or as a collection of Open Source files from the GCC source
repository (under the GPL license).
If you are using the GCC files, you can obtain the documentation, the
example files mentioned below, and this readme from the General
Decimal Arithmetic web page -- http://speleotrove.com/decimal/ (the
URL for the open source files is also linked from there).
The ICU package
---------------
The ICU package includes the files:
* readme.txt (this file)
* ICU-license.html
* decNumber.pdf (documentation)
* The .c and .h file for each module in the package (see the
decNumber documentation), together with other included files.
* The .c files for each of the examples (example1.c through
example8.c).
The ICU package is made available under the terms of the ICU License
(ICU 1.8.1 and later) included in the package as ICU-license.html.
Your use of that package indicates your acceptance of the terms and
conditions of that Agreement.
To use and check decNumber
--------------------------
Please read the appropriate license and documentation before using
this package. If you are upgrading an existing use of decNumber
(with version <= 3.37) please read the Changes Appendix for later
versions -- you may need to change the DECLITEND flag.
1. Compile and link example1.c, decNumber.c, and decContext.c
For instance, use:
gcc -o example1 example1.c decNumber.c decContext.c
Note: If your compiler does not provide stdint.h or if your C
compiler does not handle line comments (// ...), then see the
User's Guide section in the documentation for further information
(including a sample minimal stdint.h).
The use of compiler optimization is strongly recommended (e.g.,
-O3 for GCC or /O2 for Visual Studio).
2. Run example1 with two numeric arguments, for example:
example1 1.23 1.27
this should display:
1.23 + 1.27 => 2.50
3. Similarly, try the other examples, at will.
Examples 2->4 require three files to be compiled, like Example 1.
Example 5 requires decimal64.c in addition to the core modules.
Example 6 requires decPacked.c in addition to the core modules.
Example 7 requires only example7.c decContext.c and decQuad.c
Example 8 requires example8.c, decContext.c, and decQuad.c, plus
decNumber.c, decimal128.c, and decimal64.c (the latter
for shared tables and code)

View File

@ -1686,6 +1686,18 @@ C --
PARAMETER (GDS__overriding_user_invalid = 335545136)
INTEGER*4 GDS__overriding_system_missing
PARAMETER (GDS__overriding_system_missing = 335545137)
INTEGER*4 GDS__decprecision_err
PARAMETER (GDS__decprecision_err = 335545138)
INTEGER*4 GDS__decfloat_divide_by_zero
PARAMETER (GDS__decfloat_divide_by_zero = 335545139)
INTEGER*4 GDS__decfloat_inexact_result
PARAMETER (GDS__decfloat_inexact_result = 335545140)
INTEGER*4 GDS__decfloat_invalid_operation
PARAMETER (GDS__decfloat_invalid_operation = 335545141)
INTEGER*4 GDS__decfloat_overflow
PARAMETER (GDS__decfloat_overflow = 335545142)
INTEGER*4 GDS__decfloat_underflow
PARAMETER (GDS__decfloat_underflow = 335545143)
INTEGER*4 GDS__gfix_db_name
PARAMETER (GDS__gfix_db_name = 335740929)
INTEGER*4 GDS__gfix_invalid_sw

View File

@ -1681,6 +1681,18 @@ const
gds_overriding_user_invalid = 335545136;
isc_overriding_system_missing = 335545137;
gds_overriding_system_missing = 335545137;
isc_decprecision_err = 335545138;
gds_decprecision_err = 335545138;
isc_decfloat_divide_by_zero = 335545139;
gds_decfloat_divide_by_zero = 335545139;
isc_decfloat_inexact_result = 335545140;
gds_decfloat_inexact_result = 335545140;
isc_decfloat_invalid_operation = 335545141;
gds_decfloat_invalid_operation = 335545141;
isc_decfloat_overflow = 335545142;
gds_decfloat_overflow = 335545142;
isc_decfloat_underflow = 335545143;
gds_decfloat_underflow = 335545143;
isc_gfix_db_name = 335740929;
gds_gfix_db_name = 335740929;
isc_gfix_invalid_sw = 335740930;

View File

@ -233,6 +233,7 @@ public:
Firebird::ClumpletWriter dpb(Firebird::ClumpletReader::dpbList, MAX_DPB_SIZE);
dpb.insertByte(isc_dpb_sec_attach, TRUE);
dpb.insertString(isc_dpb_config, EMBEDDED_PROVIDERS, fb_strlen(EMBEDDED_PROVIDERS));
unsigned int authBlockSize;
const unsigned char* authBlock = logonInfo->authBlock(&authBlockSize);

View File

@ -141,8 +141,7 @@ int SrpServer::authenticate(CheckStatusWrapper* status, IServerBlock* sb, IWrite
ClumpletWriter dpb(ClumpletReader::dpbList, MAX_DPB_SIZE);
dpb.insertByte(isc_dpb_sec_attach, TRUE);
dpb.insertString(isc_dpb_user_name, DBA_USER_NAME, fb_strlen(DBA_USER_NAME));
const char* providers = "Providers=" CURRENT_ENGINE;
dpb.insertString(isc_dpb_config, providers, fb_strlen(providers));
dpb.insertString(isc_dpb_config, EMBEDDED_PROVIDERS, fb_strlen(EMBEDDED_PROVIDERS));
att = p->attachDatabase(status, secDbName, dpb.getBufferLength(), dpb.getBuffer());
check(status);
HANDSHAKE_DEBUG(fprintf(stderr, "Srv SRP: attached sec db %s\n", secDbName));

View File

@ -131,6 +131,7 @@ void SecurityDatabaseManagement::start(Firebird::CheckStatusWrapper* st, Firebir
Firebird::ClumpletWriter dpb(Firebird::ClumpletReader::dpbList, MAX_DPB_SIZE);
dpb.insertByte(isc_dpb_sec_attach, TRUE);
dpb.insertString(isc_dpb_config, EMBEDDED_PROVIDERS, fb_strlen(EMBEDDED_PROVIDERS));
unsigned int authBlockSize;
const unsigned char* authBlock = logonInfo->authBlock(&authBlockSize);
@ -226,6 +227,15 @@ int SecurityDatabaseManagement::release()
}
#define STR_STORE(to, from) fb_utils::copy_terminate(to, from, sizeof(to))
#define STR_VSTORE(to, from) string2vary(&to, from, sizeof(to))
static void string2vary(void* to, Firebird::string& from, size_t to_size)
{
size_t len = MIN(to_size - sizeof(USHORT), from.size());
paramvary* v = reinterpret_cast<paramvary*>(to);
v->vary_length = len;
memcpy(v->vary_string, from.c_str(), len);
}
int SecurityDatabaseManagement::execute(Firebird::CheckStatusWrapper* st, Firebird::IUser* user,
Firebird::IListUsers* callback)
@ -370,7 +380,7 @@ int SecurityDatabaseManagement::execute(Firebird::CheckStatusWrapper* st, Firebi
{
ENC_crypt(encrypted1, sizeof encrypted1, user->password()->get(), LEGACY_PASSWORD_SALT);
LegacyHash::hash(encrypted2, user->userName()->get(), &encrypted1[2]);
STR_STORE(U.PLG$PASSWD, encrypted2.c_str());
STR_VSTORE(U.PLG$PASSWD, encrypted2);
U.PLG$PASSWD.NULL = ISC_FALSE;
}
else
@ -455,7 +465,7 @@ int SecurityDatabaseManagement::execute(Firebird::CheckStatusWrapper* st, Firebi
{
ENC_crypt(encrypted1, sizeof encrypted1, user->password()->get(), LEGACY_PASSWORD_SALT);
LegacyHash::hash(encrypted2, user->userName()->get(), &encrypted1[2]);
STR_STORE(U.PLG$PASSWD, encrypted2.c_str());
STR_VSTORE(U.PLG$PASSWD, encrypted2);
U.PLG$PASSWD.NULL = ISC_FALSE;
}
else if (user->password()->specified())

View File

@ -293,8 +293,7 @@ void SecurityDatabase::prepare()
dpb.insertString(isc_dpb_trusted_auth, DBA_USER_NAME, fb_strlen(DBA_USER_NAME));
// Do not use other providers except current engine
const char* providers = "Providers=" CURRENT_ENGINE;
dpb.insertString(isc_dpb_config, providers, fb_strlen(providers));
dpb.insertString(isc_dpb_config, EMBEDDED_PROVIDERS, fb_strlen(EMBEDDED_PROVIDERS));
isc_db_handle tempHandle = 0;
isc_attach_database(status, 0, secureDbName, &tempHandle,

View File

@ -1618,13 +1618,21 @@ void put_data(burp_rel* relation)
add_byte(blr, field->fld_type);
break;
case blr_dec64:
case blr_dec128:
alignment = type_alignments[dtype];
add_byte(blr, field->fld_type);
break;
default:
BURP_error_redirect(NULL, 26, SafeArg() << field->fld_type);
// msg 26 datatype %ld not understood
break;
}
if (alignment)
offset = FB_ALIGN(offset, alignment);
field->fld_offset = offset;
field->fld_parameter = count++;
offset += length;

View File

@ -136,24 +136,34 @@ ULONG CAN_encode_decode(burp_rel* relation, lstring* buffer, UCHAR* data, bool_t
break;
case dtype_short:
if (!xdr_short(xdrs, (SSHORT *) p))
if (!xdr_short(xdrs, (SSHORT*) p))
return FALSE;
break;
case dtype_long:
case dtype_sql_time:
case dtype_sql_date:
if (!xdr_long(xdrs, (SLONG *) p))
if (!xdr_long(xdrs, (SLONG*) p))
return FALSE;
break;
case dtype_real:
if (!xdr_float(xdrs, (float *) p))
if (!xdr_float(xdrs, (float*) p))
return FALSE;
break;
case dtype_double:
if (!xdr_double(xdrs, (double *) p))
if (!xdr_double(xdrs, (double*) p))
return FALSE;
break;
case dtype_dec64:
if (!xdr_dec64(xdrs, (Firebird::Decimal64*) p))
return FALSE;
break;
case dtype_dec128:
if (!xdr_dec128(xdrs, (Firebird::Decimal128*) p))
return FALSE;
break;

View File

@ -2805,6 +2805,8 @@ rec_type get_data(BurpGlobals* tdgbl, burp_rel* relation, bool skip_relation)
case blr_timestamp:
case blr_sql_time:
case blr_sql_date:
case blr_dec64:
case blr_dec128:
add_byte(blr, field->fld_type);
break;
@ -7327,8 +7329,8 @@ bool get_relation(BurpGlobals* tdgbl)
*
*
**************************************/
SLONG rel_flags = 0, sys_flag = 0, type = 0;
bool rel_flags_null = true, type_null = true;
SLONG rel_flags = 0, sys_flag = fb_sysflag_user, type = rel_persistent;
bool rel_flags_null = true;
ISC_QUAD view_blr = isc_blob_null, view_src = isc_blob_null,
rel_desc = isc_blob_null, ext_desc = isc_blob_null;
bool view_blr_null = true, view_src_null = true, rel_desc_null = true,
@ -7344,6 +7346,24 @@ bool get_relation(BurpGlobals* tdgbl)
ext_file_name[0] = '\0';
bool ext_file_name_null = true;
// Before starting to restore relations, commit everything that was restored
// prior to this point. This ensures that no pending error can later affect
// other metadata being restored.
if (!tdgbl->relations)
{
BURP_verbose (68);
// msg 68 committing meta data
COMMIT
ON_ERROR
general_on_error ();
END_ERROR;
EXEC SQL SET TRANSACTION NO_AUTO_UNDO;
if (gds_status[1])
EXEC SQL SET TRANSACTION;
}
// Pick up relation attributes
burp_rel* relation = (burp_rel*) BURP_alloc_zero (sizeof(burp_rel));
@ -7446,10 +7466,7 @@ bool get_relation(BurpGlobals* tdgbl)
case att_relation_type:
if (tdgbl->RESTORE_format >= 8)
{
type_null = false;
type = get_int32(tdgbl);
}
else
bad_attribute(scan_next_attr, attribute, 111);
break;
@ -7488,7 +7505,7 @@ bool get_relation(BurpGlobals* tdgbl)
X.RDB$RUNTIME.NULL = TRUE;
X.RDB$EXTERNAL_DESCRIPTION.NULL = ext_desc_null;
X.RDB$EXTERNAL_FILE.NULL = ext_file_name_null;
X.RDB$RELATION_TYPE.NULL = type_null;
X.RDB$RELATION_TYPE.NULL = FALSE;
X.RDB$SQL_SECURITY.NULL = sql_security_null;
X.RDB$SYSTEM_FLAG = (USHORT) sys_flag;

View File

@ -31,6 +31,7 @@
#define JRD_CHARSET_H
#include "CsConvert.h"
#include "IntlUtil.h"
namespace Jrd {
@ -42,8 +43,7 @@ public:
public:
static void clear(charset* cs)
{
if (cs->charset_fn_destroy)
cs->charset_fn_destroy(cs);
Firebird::IntlUtil::finiCharset(cs);
delete cs;
}
};
@ -116,8 +116,7 @@ public:
void destroy()
{
if (cs->charset_fn_destroy)
cs->charset_fn_destroy(cs);
Firebird::IntlUtil::finiCharset(cs);
}
const UCHAR* getSqlMatchAny() const { return sqlMatchAny; }

986
src/common/DecFloat.cpp Normal file
View File

@ -0,0 +1,986 @@
/*
* PROGRAM: Decimal 64 & 128 type.
* MODULE: DecFloat.cpp
* DESCRIPTION: Floating point with decimal exponent.
*
* 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) 2016 Alex Peshkov <peshkoff at mail dot ru>
* and all contributors signed below.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
*
*
*/
#include "firebird.h"
#include "DecFloat.h"
#include "StatusArg.h"
#include "gen/iberror.h"
extern "C"
{
#include "../../extern/decNumber/decimal128.h"
#include "../../extern/decNumber/decimal64.h"
#include "../../extern/decNumber/decNumber.h"
}
#include <stdlib.h>
#include <string.h>
#include <float.h>
using namespace Firebird;
namespace {
struct Dec2fb
{
USHORT decError;
ISC_STATUS fbError;
};
Dec2fb dec2fb[] = {
{ DEC_IEEE_754_Division_by_zero, isc_decfloat_divide_by_zero },
{ DEC_IEEE_754_Inexact, isc_decfloat_inexact_result },
{ DEC_IEEE_754_Invalid_operation, isc_decfloat_invalid_operation },
{ DEC_IEEE_754_Overflow, isc_decfloat_overflow },
{ DEC_IEEE_754_Underflow, isc_decfloat_underflow },
{ 0, 0 }
};
class DecimalContext : public decContext
{
public:
DecimalContext(const Decimal64*, DecimalStatus ds)
: decSt(ds)
{
init(DEC_INIT_DECIMAL64);
}
DecimalContext(const Decimal128*, DecimalStatus ds)
: decSt(ds)
{
init(DEC_INIT_DECIMAL128);
}
~DecimalContext() NOEXCEPT_ARG(false)
{
// Typically exceptions should better be not thrown from destructors.
// But in our case there should never be any exception raised inside
// Decimal64/128 functions - C library never throw, i.e. dtor will
// be never called due to exception processing.
// Therefore checking status in destructor is safe.
checkForExceptions();
}
void checkForExceptions()
{
USHORT unmaskedExceptions = decSt.decExtFlag & decContextGetStatus(this);
if (!unmaskedExceptions)
return;
decContextZeroStatus(this);
for (Dec2fb* e = dec2fb; e->decError; ++e)
{
// Arg::Gds(isc_arith_except) as first vector element ?
if (e->decError & unmaskedExceptions)
Arg::Gds(e->fbError).raise();
}
}
private:
DecimalStatus decSt;
void init(int kind)
{
decContextDefault(this, kind);
fb_assert(decSt.roundingMode < USHORT(DEC_ROUND_MAX));
enum rounding rMode = rounding(decSt.roundingMode);
decContextSetRounding(this, rMode);
traps = 0; // do not raise SIGFPE
}
};
CDecimal128 dmax(DBL_MAX, DecimalStatus(0)), dmin(-DBL_MAX, DecimalStatus(0));
CDecimal128 i64max(MAX_SINT64, DecimalStatus(0)), i64min(MIN_SINT64, DecimalStatus(0));
unsigned digits(const unsigned pMax, unsigned char* const coeff, int& exp)
{
for (unsigned i = 0; i < pMax; ++i)
{
if (coeff[i])
{
if (i)
{
memmove(coeff, &coeff[i], pMax - i);
memset(&coeff[pMax - i], 0, i);
exp -= i;
}
i = pMax - i;
while (!coeff[i - 1])
{
fb_assert(i > 0);
--i;
}
return i;
}
}
return 0;
}
void make(ULONG* key,
const unsigned pMax, const int bias, const unsigned decSize,
unsigned char* coeff, int sign, int exp)
{
// normalize coeff & exponent
unsigned dig = digits(pMax, coeff, exp);
// exponent bias and sign
if (!dig)
{
exp = 0;
sign = 0;
}
else
{
exp += (bias + 2);
if (sign)
exp = -exp;
}
*key++ = exp;
// convert to SLONG
fb_assert(pMax / 9 < decSize / sizeof(int));
memset(key, 0, decSize);
for (unsigned i = 0; i < pMax; ++i)
{
unsigned c = i / 9;
key[c] *= 10;
key[c] += (sign ? 9 - coeff[i] : coeff[i]);
}
}
void grab(ULONG* key,
const unsigned pMax, const int bias, const unsigned decSize,
unsigned char* bcd, int& sign, int& exp)
{
exp = *key++;
sign = 0;
// parse exp
if (exp < 0)
{
sign = DECFLOAT_Sign;
exp = -exp;
}
if (exp != 0)
exp -= (bias + 2);
// convert from SLONG
for (int i = pMax; i--;)
{
int c = i / 9;
bcd[i] = key[c] % 10;
key[c] /= 10;
if (sign)
bcd[i] = 9 - bcd[i];
}
// normalize
for (unsigned i = pMax; i--; )
{
if (bcd[i])
{
if (i < pMax - 1)
{
memmove(&bcd[pMax - 1 - i], bcd, i + 1);
memset(bcd, 0, pMax - 1 - i);
exp += (pMax - 1 - i);
}
break;
}
}
}
} // anonymous namespace
namespace Firebird {
void Decimal64::setScale(DecimalStatus decSt, int scale)
{
if (scale)
{
DecimalContext context(this, decSt);
scale += decDoubleGetExponent(&dec);
decDoubleSetExponent(&dec, &context, scale);
}
}
#if SIZEOF_LONG < 8
Decimal64 Decimal64::set(int value, DecimalStatus decSt, int scale)
{
return set(SLONG(value), decSt, scale);
}
#endif
Decimal64 Decimal64::set(SLONG value, DecimalStatus decSt, int scale)
{
decDoubleFromInt32(&dec, value);
setScale(decSt, -scale);
return *this;
}
Decimal64 Decimal64::set(SINT64 value, DecimalStatus decSt, int scale)
{
{
char s[30]; // for sure enough for int64
sprintf(s, "%" SQUADFORMAT, value);
DecimalContext context(this, decSt);
decDoubleFromString(&dec, s, &context);
}
setScale(decSt, -scale);
return *this;
}
Decimal64 Decimal64::set(const char* value, DecimalStatus decSt)
{
DecimalContext context(this, decSt);
decDoubleFromString(&dec, value, &context);
return *this;
}
Decimal64 Decimal64::set(double value, DecimalStatus decSt)
{
char s[50];
sprintf(s, "%.016e", value);
DecimalContext context(this, decSt);
decDoubleFromString(&dec, s, &context);
return *this;
}
void Decimal64::toString(DecimalStatus decSt, unsigned length, char* to) const
{
DecimalContext context(this, decSt);
if (length)
{
--length;
char s[IDecFloat16::STRING_SIZE];
memset(s, 0, sizeof(s));
decDoubleToString(&dec, s);
if (strlen(s) > length)
decContextSetStatus(&context, DEC_Invalid_operation);
else
length = strlen(s);
memcpy(to, s, length + 1);
}
else
decContextSetStatus(&context, DEC_Invalid_operation);
}
void Decimal64::toString(string& to) const
{
to.grow(IDecFloat16::STRING_SIZE);
toString(DecimalStatus(0), to.length(), to.begin()); // provide long enough string, i.e. no traps
to.recalculate_length();
}
UCHAR* Decimal64::getBytes()
{
return dec.bytes;
}
Decimal64 Decimal64::abs() const
{
Decimal64 rc;
decDoubleCopyAbs(&rc.dec, &dec);
return rc;
}
Decimal64 Decimal64::ceil(DecimalStatus decSt) const
{
DecimalContext context(this, decSt);
Decimal64 rc;
decDoubleToIntegralValue(&rc.dec, &dec, &context, DEC_ROUND_CEILING);
return rc;
}
Decimal64 Decimal64::floor(DecimalStatus decSt) const
{
DecimalContext context(this, decSt);
Decimal64 rc;
decDoubleToIntegralValue(&rc.dec, &dec, &context, DEC_ROUND_FLOOR);
return rc;
}
int Decimal64::compare(DecimalStatus decSt, Decimal64 tgt) const
{
DecimalContext context(this, decSt);
decDouble r;
decDoubleCompare(&r, &dec, &tgt.dec, &context);
return decDoubleToInt32(&r, &context, DEC_ROUND_HALF_UP);
}
bool Decimal64::isInf() const
{
switch (decDoubleClass(&dec))
{
case DEC_CLASS_NEG_INF:
case DEC_CLASS_POS_INF:
return true;
}
return false;
}
bool Decimal64::isNan() const
{
switch (decDoubleClass(&dec))
{
case DEC_CLASS_SNAN:
case DEC_CLASS_QNAN:
return true;
}
return false;
}
int Decimal64::sign() const
{
if (decDoubleIsZero(&dec))
return 0;
if (decDoubleIsSigned(&dec))
return -1;
return 1;
}
#ifdef DEV_BUILD
int Decimal64::show()
{
decDoubleShow(&dec, "");
return 0;
}
#endif
Decimal64 Decimal64::neg() const
{
Decimal64 rc;
decDoubleCopyNegate(&rc.dec, &dec);
return rc;
}
void Decimal64::makeKey(ULONG* key) const
{
unsigned char coeff[DECDOUBLE_Pmax];
int sign = decDoubleGetCoefficient(&dec, coeff);
int exp = decDoubleGetExponent(&dec);
make(key, DECDOUBLE_Pmax, DECDOUBLE_Bias, sizeof(dec), coeff, sign, exp);
}
void Decimal64::grabKey(ULONG* key)
{
int exp, sign;
unsigned char bcd[DECDOUBLE_Pmax];
grab(key, DECDOUBLE_Pmax, DECDOUBLE_Bias, sizeof(dec), bcd, sign, exp);
decDoubleFromBCD(&dec, exp, bcd, sign);
}
Decimal64 Decimal64::quantize(DecimalStatus decSt, Decimal64 op2) const
{
DecimalContext context(this, decSt);
Decimal64 rc;
decDoubleQuantize(&rc.dec, &dec, &op2.dec, &context);
return rc;
}
Decimal64 Decimal64::normalize(DecimalStatus decSt) const
{
DecimalContext context(this, decSt);
Decimal64 rc;
decDoubleReduce(&rc.dec, &dec, &context);
return rc;
}
short Decimal64::totalOrder(Decimal64 op2) const
{
decDouble r;
decDoubleCompareTotal(&r, &dec, &op2.dec);
fb_assert(!decDoubleIsNaN(&r));
DecimalContext context2(this, 0);
return decDoubleToInt32(&r, &context2, DEC_ROUND_HALF_UP);
}
/*
* decCompare() implements SQL function COMPARE_DECFLOAT() which has non-traditional return values.
* COMPARE_DECFLOAT (X, Y)
* 0 - X == Y
* 1 - X < Y
* 2 - X > Y
* 3 - values unordered
*/
short Decimal64::decCompare(Decimal64 op2) const
{
if (decDoubleIsNaN(&dec) || decDoubleIsNaN(&op2.dec))
return 3;
switch (totalOrder(op2))
{
case -1:
return 1;
case 0:
return 0;
case 1:
return 2;
default:
fb_assert(false);
}
// warning silencer
return 3;
}
Decimal128 Decimal128::set(Decimal64 d64)
{
decDoubleToWider(&d64.dec, &dec);
return *this;
}
#if SIZEOF_LONG < 8
Decimal128 Decimal128::set(int value, DecimalStatus decSt, int scale)
{
return set(SLONG(value), decSt, scale);
}
#endif
Decimal128 Decimal128::set(SLONG value, DecimalStatus decSt, int scale)
{
decQuadFromInt32(&dec, value);
setScale(decSt, -scale);
return *this;
}
Decimal128 Decimal128::set(SINT64 value, DecimalStatus decSt, int scale)
{
{
int high = value >> 32;
unsigned low = value & 0xFFFFFFFF;
DecimalContext context(this, decSt);
decQuad pow2_32;
decQuadFromString(&pow2_32, "4294967296", &context);
decQuad up, down;
decQuadFromInt32(&up, high);
decQuadFromUInt32(&down, low);
decQuadFMA(&dec, &up, &pow2_32, &down, &context);
}
setScale(decSt, -scale);
return *this;
}
Decimal128 Decimal128::set(const char* value, DecimalStatus decSt)
{
DecimalContext context(this, decSt);
decQuadFromString(&dec, value, &context);
return *this;
}
Decimal128 Decimal128::set(double value, DecimalStatus decSt)
{
char s[50];
sprintf(s, "%.016e", value);
DecimalContext context(this, decSt);
decQuadFromString(&dec, s, &context);
return *this;
}
Decimal128 Decimal128::operator=(Decimal64 d64)
{
decDoubleToWider(&d64.dec, &dec);
return *this;
}
int Decimal128::toInteger(DecimalStatus decSt, int scale) const
{
Decimal128 tmp(*this);
tmp.setScale(decSt, -scale);
DecimalContext context(this, decSt);
enum rounding rMode = decContextGetRounding(&context);
return decQuadToInt32(&tmp.dec, &context, rMode);
}
void Decimal128::toString(DecimalStatus decSt, unsigned length, char* to) const
{
DecimalContext context(this, decSt);
if (length)
{
--length;
char s[IDecFloat34::STRING_SIZE];
memset(s, 0, sizeof(s));
decQuadToString(&dec, s);
if (strlen(s) > length)
decContextSetStatus(&context, DEC_Invalid_operation);
else
length = strlen(s);
memcpy(to, s, length + 1);
}
else
decContextSetStatus(&context, DEC_Invalid_operation);
}
void Decimal128::toString(string& to) const
{
to.grow(IDecFloat34::STRING_SIZE);
toString(DecimalStatus(0), to.length(), to.begin()); // provide long enough string, i.e. no traps
to.recalculate_length();
}
double Decimal128::toDouble(DecimalStatus decSt) const
{
DecimalContext context(this, decSt);
if (compare(decSt, dmin) < 0 || compare(decSt, dmax) > 0)
decContextSetStatus(&context, DEC_Overflow);
else
{
char s[IDecFloat34::STRING_SIZE];
memset(s, 0, sizeof(s));
decQuadToString(&dec, s);
return atof(s);
}
return 0.0;
}
SINT64 Decimal128::toInt64(DecimalStatus decSt, int scale) const
{
static CDecimal128 quant(1);
Decimal128 wrk(*this);
wrk.setScale(decSt, -scale);
wrk = wrk.quantize(decSt, quant);
if (wrk.compare(decSt, i64min) < 0 || wrk.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(&wrk.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* Decimal128::getBytes()
{
return dec.bytes;
}
Decimal64 Decimal128::toDecimal64(DecimalStatus decSt) const
{
Decimal64 rc;
DecimalContext context(this, decSt);
decDoubleFromWider(&rc.dec, &dec, &context);
return rc;
}
void Decimal128::setScale(DecimalStatus decSt, int scale)
{
if (scale)
{
DecimalContext context(this, decSt);
scale += decQuadGetExponent(&dec);
decQuadSetExponent(&dec, &context, scale);
}
}
int Decimal128::compare(DecimalStatus decSt, Decimal128 tgt) const
{
DecimalContext context(this, decSt);
decQuad r;
decQuadCompare(&r, &dec, &tgt.dec, &context);
return decQuadToInt32(&r, &context, DEC_ROUND_HALF_UP);
}
bool Decimal128::isInf() const
{
switch(decQuadClass(&dec))
{
case DEC_CLASS_NEG_INF:
case DEC_CLASS_POS_INF:
return true;
}
return false;
}
bool Decimal128::isNan() const
{
switch(decQuadClass(&dec))
{
case DEC_CLASS_SNAN:
case DEC_CLASS_QNAN:
return true;
}
return false;
}
int Decimal128::sign() const
{
if (decQuadIsZero(&dec))
return 0;
if (decQuadIsSigned(&dec))
return -1;
return 1;
}
Decimal128 Decimal128::abs() const
{
Decimal128 rc;
decQuadCopyAbs(&rc.dec, &dec);
return rc;
}
Decimal128 Decimal128::ceil(DecimalStatus decSt) const
{
DecimalContext context(this, decSt);
Decimal128 rc;
decQuadToIntegralValue(&rc.dec, &dec, &context, DEC_ROUND_CEILING);
return rc;
}
Decimal128 Decimal128::floor(DecimalStatus decSt) const
{
DecimalContext context(this, decSt);
Decimal128 rc;
decQuadToIntegralValue(&rc.dec, &dec, &context, DEC_ROUND_FLOOR);
return rc;
}
#ifdef DEV_BUILD
int Decimal128::show()
{
decQuadShow(&dec, "");
return 0;
}
#endif
Decimal128 Decimal128::add(DecimalStatus decSt, Decimal128 op2) const
{
DecimalContext context(this, decSt);
Decimal128 rc;
decQuadAdd(&rc.dec, &dec, &op2.dec, &context);
return rc;
}
Decimal128 Decimal128::sub(DecimalStatus decSt, Decimal128 op2) const
{
DecimalContext context(this, decSt);
Decimal128 rc;
decQuadSubtract(&rc.dec, &dec, &op2.dec, &context);
return rc;
}
Decimal128 Decimal128::mul(DecimalStatus decSt, Decimal128 op2) const
{
DecimalContext context(this, decSt);
Decimal128 rc;
decQuadMultiply(&rc.dec, &dec, &op2.dec, &context);
return rc;
}
Decimal128 Decimal128::div(DecimalStatus decSt, Decimal128 op2) const
{
DecimalContext context(this, decSt);
Decimal128 rc;
decQuadDivide(&rc.dec, &dec, &op2.dec, &context);
return rc;
}
Decimal128 Decimal128::neg() const
{
Decimal128 rc;
decQuadCopyNegate(&rc.dec, &dec);
return rc;
}
Decimal128 Decimal128::fma(DecimalStatus decSt, Decimal128 op2, Decimal128 op3) const
{
DecimalContext context(this, decSt);
Decimal128 rc;
decQuadFMA(&rc.dec, &op2.dec, &op3.dec, &dec, &context);
return rc;
}
Decimal128 Decimal128::sqrt(DecimalStatus decSt) const
{
decNumber dn;
decQuadToNumber(&dec, &dn);
DecimalContext context(this, decSt);
decNumberSquareRoot(&dn, &dn, &context);
Decimal128 rc;
decQuadFromNumber(&rc.dec, &dn, &context);
return rc;
}
Decimal128 Decimal128::pow(DecimalStatus decSt, Decimal128 op2) const
{
decNumber dn, dn2;
decQuadToNumber(&dec, &dn);
decQuadToNumber(&op2.dec, &dn2);
DecimalContext context(this, decSt);
decNumberPower(&dn, &dn, &dn2, &context);
Decimal128 rc;
decQuadFromNumber(&rc.dec, &dn, &context);
return rc;
}
Decimal128 Decimal128::ln(DecimalStatus decSt) const
{
decNumber dn;
decQuadToNumber(&dec, &dn);
DecimalContext context(this, decSt);
decNumberLn(&dn, &dn, &context);
Decimal128 rc;
decQuadFromNumber(&rc.dec, &dn, &context);
return rc;
}
Decimal128 Decimal128::log10(DecimalStatus decSt) const
{
decNumber dn;
decQuadToNumber(&dec, &dn);
DecimalContext context(this, decSt);
decNumberLog10(&dn, &dn, &context);
Decimal128 rc;
decQuadFromNumber(&rc.dec, &dn, &context);
return rc;
}
void Decimal128::makeKey(ULONG* key) const
{
unsigned char coeff[DECQUAD_Pmax];
int sign = decQuadGetCoefficient(&dec, coeff);
int exp = decQuadGetExponent(&dec);
make(key, DECQUAD_Pmax, DECQUAD_Bias, sizeof(dec), coeff, sign, exp);
}
void Decimal128::grabKey(ULONG* key)
{
int exp, sign;
unsigned char bcd[DECQUAD_Pmax];
grab(key, DECQUAD_Pmax, DECQUAD_Bias, sizeof(dec), bcd, sign, exp);
decQuadFromBCD(&dec, exp, bcd, sign);
}
ULONG Decimal128::getIndexKeyLength()
{
return 17;
}
ULONG Decimal128::makeIndexKey(vary* buf)
{
unsigned char coeff[DECQUAD_Pmax + 2];
int sign = decQuadGetCoefficient(&dec, coeff);
int exp = decQuadGetExponent(&dec);
const int bias = DECQUAD_Bias;
const unsigned pMax = DECQUAD_Pmax;
// normalize coeff & exponent
unsigned dig = digits(pMax, coeff, exp);
// exponent bias and sign
exp += (bias + 1);
if (!dig)
exp = 0;
if (sign)
exp = -exp;
exp += 2 * (bias + 1); // make it positive
fb_assert(exp >= 0 && exp < 64 * 1024);
// encode exp
char* k = buf->vary_string;
*k++ = exp >> 8;
*k++ = exp & 0xff;
// invert negative
unsigned char* const end = &coeff[dig];
if (sign && dig)
{
fb_assert(end[-1]);
--end[-1];
for (unsigned char* p = coeff; p < end; ++p)
*p = 9 - *p;
}
// Some 0's in the end - caller, do not forget to reserve additional space on stack
end[0] = end[1] = 0;
// Avoid bad data in k in case when coeff is zero
*k = 0;
// Shifts for moving 10-bit values to bytes buffer
struct ShiftTable { UCHAR rshift, lshift; };
static ShiftTable table[4] =
{
{ 2, 6 },
{ 4, 4 },
{ 6, 2 },
{ 8, 0 }
};
// compress coeff - 3 decimal digits (999) per 10 bits (1023)
unsigned char* p = coeff;
for (ShiftTable* t = table; p < end; p += 3)
{
USHORT val = p[0] * 100 + p[1] * 10 + p[2];
fb_assert(val < 1000); // 1024, 10 bit
*k |= (val >> t->rshift);
++k;
*k = (val << t->lshift);
if (!t->lshift)
{
++k;
*k = 0;
t = table;
}
else
++t;
}
if (*k)
++k;
// done
buf->vary_length = k - buf->vary_string;
return buf->vary_length;
}
Decimal128 Decimal128::quantize(DecimalStatus decSt, Decimal128 op2) const
{
DecimalContext context(this, decSt);
Decimal128 rc;
decQuadQuantize(&rc.dec, &dec, &op2.dec, &context);
return rc;
}
Decimal128 Decimal128::normalize(DecimalStatus decSt) const
{
DecimalContext context(this, decSt);
Decimal128 rc;
decQuadReduce(&rc.dec, &dec, &context);
return rc;
}
short Decimal128::totalOrder(Decimal128 op2) const
{
decQuad r;
decQuadCompareTotal(&r, &dec, &op2.dec);
fb_assert(!decQuadIsNaN(&r));
DecimalContext context2(this, 0);
return decQuadToInt32(&r, &context2, DEC_ROUND_HALF_UP);
}
/*
* decCompare() implements SQL function COMPARE_DECFLOAT() which has non-traditional return values.
* COMPARE_DECFLOAT (X, Y)
* 0 - X == Y
* 1 - X < Y
* 2 - X > Y
* 3 - values unordered
*/
short Decimal128::decCompare(Decimal128 op2) const
{
if (decQuadIsNaN(&dec) || decQuadIsNaN(&op2.dec))
return 3;
switch (totalOrder(op2))
{
case -1:
return 1;
case 0:
return 0;
case 1:
return 2;
default:
fb_assert(false);
}
// warning silencer
return 3;
}
} // namespace Firebird

195
src/common/DecFloat.h Normal file
View File

@ -0,0 +1,195 @@
/*
* PROGRAM: Decimal 64 & 128 type.
* MODULE: DecFloat.h
* DESCRIPTION: Floating point with decimal exponent.
*
* 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) 2016 Alex Peshkov <peshkoff at mail dot ru>
* and all contributors signed below.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
*
*
*/
#ifndef FB_DECIMAL_FLOAT
#define FB_DECIMAL_FLOAT
#include "firebird/Interface.h"
#include "fb_exception.h"
#include "classes/fb_string.h"
extern "C"
{
#include "../../extern/decNumber/decQuad.h"
#include "../../extern/decNumber/decDouble.h"
}
namespace Firebird {
struct DecimalStatus
{
DecimalStatus(USHORT exc)
: decExtFlag(exc), roundingMode(DEC_ROUND_HALF_UP)
{ }
USHORT decExtFlag, roundingMode;
};
struct DecimalBinding
{
DecimalBinding()
: bind(DEC_NATIVE), numScale(0)
{ }
enum Bind { DEC_NATIVE, DEC_TEXT, DEC_DOUBLE, DEC_NUMERIC };
Bind bind;
SCHAR numScale;
};
class Decimal64
{
friend class Decimal128;
public:
#if SIZEOF_LONG < 8
Decimal64 set(int value, DecimalStatus decSt, int scale);
#endif
Decimal64 set(SLONG value, DecimalStatus decSt, int scale);
Decimal64 set(SINT64 value, DecimalStatus decSt, int scale);
Decimal64 set(const char* value, DecimalStatus decSt);
Decimal64 set(double value, DecimalStatus decSt);
UCHAR* getBytes();
Decimal64 abs() const;
Decimal64 ceil(DecimalStatus decSt) const;
Decimal64 floor(DecimalStatus decSt) const;
Decimal64 neg() const;
void toString(DecimalStatus decSt, unsigned length, char* to) const;
void toString(string& to) const;
int compare(DecimalStatus decSt, Decimal64 tgt) const;
bool isInf() const;
bool isNan() const;
int sign() const;
void makeKey(ULONG* key) const;
void grabKey(ULONG* key);
Decimal64 quantize(DecimalStatus decSt, Decimal64 op2) const;
Decimal64 normalize(DecimalStatus decSt) const;
short totalOrder(Decimal64 op2) const;
short decCompare(Decimal64 op2) const;
#ifdef DEV_BUILD
int show();
#endif
private:
decDouble dec;
void setScale(DecimalStatus decSt, int scale);
};
class Decimal128
{
friend class Decimal64;
public:
Decimal128 set(Decimal64 d64);
#if SIZEOF_LONG < 8
Decimal128 set(int value, DecimalStatus decSt, int scale);
#endif
Decimal128 set(SLONG value, DecimalStatus decSt, int scale);
Decimal128 set(SINT64 value, DecimalStatus decSt, int scale);
Decimal128 set(const char* value, DecimalStatus decSt);
Decimal128 set(double value, DecimalStatus decSt);
Decimal128 operator=(Decimal64 d64);
int toInteger(DecimalStatus decSt, int scale) const;
void toString(DecimalStatus decSt, unsigned length, char* to) const;
void toString(string& to) const;
double toDouble(DecimalStatus decSt) const;
SINT64 toInt64(DecimalStatus decSt, int scale) const;
UCHAR* getBytes();
Decimal64 toDecimal64(DecimalStatus decSt) const;
Decimal128 abs() const;
Decimal128 ceil(DecimalStatus decSt) const;
Decimal128 floor(DecimalStatus decSt) const;
Decimal128 add(DecimalStatus decSt, Decimal128 op2) const;
Decimal128 sub(DecimalStatus decSt, Decimal128 op2) const;
Decimal128 mul(DecimalStatus decSt, Decimal128 op2) const;
Decimal128 div(DecimalStatus decSt, Decimal128 op2) const;
Decimal128 neg() const;
Decimal128 fma(DecimalStatus decSt, Decimal128 op2, Decimal128 op3) const;
Decimal128 sqrt(DecimalStatus decSt) const;
Decimal128 pow(DecimalStatus decSt, Decimal128 op2) const;
Decimal128 ln(DecimalStatus decSt) const;
Decimal128 log10(DecimalStatus decSt) const;
int compare(DecimalStatus decSt, Decimal128 tgt) const;
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);
Decimal128 quantize(DecimalStatus decSt, Decimal128 op2) const;
Decimal128 normalize(DecimalStatus decSt) const;
short totalOrder(Decimal128 op2) const;
short decCompare(Decimal128 op2) const;
#ifdef DEV_BUILD
int show();
#endif
private:
decQuad dec;
void setScale(DecimalStatus decSt, int scale);
};
class CDecimal128 : public Decimal128
{
public:
CDecimal128(double value, DecimalStatus decSt)
{
set(value, decSt);
}
CDecimal128(SINT64 value, DecimalStatus decSt)
{
set(value, decSt, 0);
}
CDecimal128(int value)
{
set(value, DecimalStatus(0), 0);
}
};
} // namespace Firebird
#endif // FB_DECIMAL_FLOAT

View File

@ -49,8 +49,7 @@ namespace
~TextTypeImpl()
{
if (cs->charset_fn_destroy)
cs->charset_fn_destroy(cs);
Firebird::IntlUtil::finiCharset(cs);
delete cs;
delete collation;
@ -539,6 +538,17 @@ bool IntlUtil::initUnicodeCollation(texttype* tt, charset* cs, const ASCII* name
}
void IntlUtil::finiCharset(charset* cs)
{
if (cs->charset_to_unicode.csconvert_fn_destroy)
cs->charset_to_unicode.csconvert_fn_destroy(&cs->charset_to_unicode);
if (cs->charset_from_unicode.csconvert_fn_destroy)
cs->charset_from_unicode.csconvert_fn_destroy(&cs->charset_from_unicode);
if (cs->charset_fn_destroy)
cs->charset_fn_destroy(cs);
}
ULONG IntlUtil::toLower(Jrd::CharSet* cs, ULONG srcLen, const UCHAR* src, ULONG dstLen, UCHAR* dst,
const ULONG* exceptions)
{

View File

@ -80,6 +80,8 @@ public:
static bool initUnicodeCollation(texttype* tt, charset* cs, const ASCII* name,
USHORT attributes, const UCharBuffer& specificAttributes, const string& configInfo);
static void finiCharset(charset* cs);
static ULONG toLower(Jrd::CharSet* cs, ULONG srcLen, const UCHAR* src, ULONG dstLen, UCHAR* dst,
const ULONG* exceptions);
static ULONG toUpper(Jrd::CharSet* cs, ULONG srcLen, const UCHAR* src, ULONG dstLen, UCHAR* dst,

View File

@ -286,6 +286,7 @@ void MsgMetadata::addItem(const MetaName& name, bool nullable, const dsc& desc)
item.subType = sqlSubType;
item.length = sqlLen;
item.scale = sqlScale;
item.charSet = desc.getCharSet();
item.finished = true;
}

View File

@ -167,7 +167,7 @@ const char* StatementMetadata::getPlan(bool detailed)
if (plan->isEmpty())
{
UCHAR info[] = {detailed ? isc_info_sql_explain_plan : isc_info_sql_get_plan};
UCHAR info[] = {UCHAR(detailed ? isc_info_sql_explain_plan : isc_info_sql_get_plan)};
UCHAR result[INFO_BUFFER_SIZE];
getAndParse(sizeof(info), info, sizeof(result), result);
@ -484,8 +484,8 @@ void StatementMetadata::fetchParameters(UCHAR code, Parameters* parameters)
{
isc_info_sql_sqlda_start,
2,
(startIndex & 0xFF),
((startIndex >> 8) & 0xFF),
UCHAR(startIndex & 0xFF),
UCHAR((startIndex >> 8) & 0xFF),
code
};
memcpy(items + 5, DESCRIBE_VARS, sizeof(DESCRIBE_VARS));

View File

@ -43,12 +43,11 @@ namespace
{
unsigned int hash_value = 0;
UCHAR* p;
UCHAR* const p = (UCHAR*) &hash_value;
const UCHAR* q = value;
while (length >= 4)
{
p = (UCHAR*) &hash_value;
p[0] += q[0];
p[1] += q[1];
p[2] += q[2];
@ -57,18 +56,16 @@ namespace
q += 4;
}
p = (UCHAR*) &hash_value;
if (length >= 2)
{
p[0] += q[0];
p[1] += q[1];
length -= 2;
q += 2;
}
if (length)
{
q += 2;
*p += *q;
}

View File

@ -117,7 +117,7 @@ protected:
void refCntDPrt(char f)
{
if (mark)
fprintf(stderr, "%s %p %c %lld\n", mark, this, f, refCounter.value());
fprintf(stderr, "%s %p %c %d\n", mark, this, f, int(refCounter.value()));
}
AtomicCounter refCounter;

View File

@ -172,6 +172,16 @@ MetadataFromBlr::MetadataFromBlr(unsigned aBlrLength, const unsigned char* aBlr,
item->length = sizeof(UCHAR);
break;
case blr_dec64:
item->type = SQL_DEC16;
item->length = sizeof(Decimal64);
break;
case blr_dec128:
item->type = SQL_DEC34;
item->length = sizeof(Decimal128);
break;
default:
(Arg::Gds(isc_sqlerr) << Arg::Num(-804) <<
Arg::Gds(isc_dsql_sqlda_err)

View File

@ -193,7 +193,7 @@ namespace Firebird
return ptr;
}
private:
protected:
T* assign(T* const p)
{
if (ptr != p)
@ -215,6 +215,7 @@ namespace Firebird
return ptr;
}
private:
T* ptr;
};

View File

@ -126,7 +126,7 @@
#define FB_CPU CpuPowerPc
#endif
#ifdef i386
#if defined(i386) || defined(__i386) || defined(__i386__)
#define I386
#define FB_CPU CpuIntel
#endif /* i386 */
@ -603,6 +603,13 @@ extern "C" int remove(const char* path);
#define FB_EXPORTED
#endif
#ifdef HAS_NOEXCEPT
#define NOEXCEPT noexcept
#define NOEXCEPT_ARG(X) noexcept((X))
#else
#define NOEXCEPT
#define NOEXCEPT_ARG(X)
#endif
/* alignment macros */

View File

@ -137,6 +137,7 @@ enum EXPECT_DATETIME
static void datetime_to_text(const dsc*, dsc*, Callbacks*);
static void float_to_text(const dsc*, dsc*, Callbacks*);
static void decimal_float_to_text(const dsc*, dsc*, DecimalStatus, Callbacks*);
static void integer_to_text(const dsc*, dsc*, Callbacks*);
static void string_to_datetime(const dsc*, GDS_TIMESTAMP*, const EXPECT_DATETIME, ErrorFunction);
static SINT64 hex_to_value(const char*& string, const char* end);
@ -296,7 +297,38 @@ static void float_to_text(const dsc* from, dsc* to, Callbacks* cb)
intermediate.dsc_length = chars_printed - 1;
}
CVT_move_common(&intermediate, to, cb);
CVT_move_common(&intermediate, to, 0, cb);
}
static void decimal_float_to_text(const dsc* from, dsc* to, DecimalStatus decSt, Callbacks* cb)
{
char temp[50];
try
{
Decimal128 d;
if (from->dsc_dtype == dtype_dec64)
d = *((Decimal64*) from->dsc_address);
else
d = *((Decimal128*) from->dsc_address);
d.toString(decSt, sizeof(temp), temp);
}
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);
}
@ -343,7 +375,7 @@ static void integer_to_text(const dsc* from, dsc* to, Callbacks* cb)
intermediate.dsc_scale = scale;
intermediate.dsc_address = (UCHAR*) &n;
CVT_move_common(from, &intermediate, cb);
CVT_move_common(from, &intermediate, 0, cb);
// Check for negation, then convert the number to a string of digits
@ -528,7 +560,7 @@ static void string_to_datetime(const dsc* desc,
VaryStr<100> buffer; // arbitrarily large
const char* p = NULL;
const USHORT length = CVT_make_string(desc, ttype_ascii, &p, &buffer, sizeof(buffer), err);
const USHORT length = CVT_make_string(desc, ttype_ascii, &p, &buffer, sizeof(buffer), 0, err);
const char* const end = p + length;
@ -862,7 +894,7 @@ static void string_to_datetime(const dsc* desc,
}
SLONG CVT_get_long(const dsc* desc, SSHORT scale, ErrorFunction err)
SLONG CVT_get_long(const dsc* desc, SSHORT scale, DecimalStatus decSt, ErrorFunction err)
{
/**************************************
*
@ -878,6 +910,7 @@ SLONG CVT_get_long(const dsc* desc, SSHORT scale, ErrorFunction err)
SLONG value, high;
double d, eps;
Decimal128 d128;
SINT64 val64;
VaryStr<50> buffer; // long enough to represent largest long in ASCII
@ -940,6 +973,15 @@ SLONG CVT_get_long(const dsc* desc, SSHORT scale, ErrorFunction err)
err(Arg::Gds(isc_arith_except) << Arg::Gds(isc_numeric_out_of_range));
break;
case dtype_dec64:
case dtype_dec128:
if (desc->dsc_dtype == dtype_dec64)
d128 = *((Decimal64*) p);
else
d128 = *((Decimal128*) p);
return d128.toInteger(decSt, scale);
case dtype_real:
case dtype_double:
if (desc->dsc_dtype == dtype_real)
@ -986,7 +1028,7 @@ SLONG CVT_get_long(const dsc* desc, SSHORT scale, ErrorFunction err)
case dtype_text:
{
USHORT length =
CVT_make_string(desc, ttype_ascii, &p, &buffer, sizeof(buffer), err);
CVT_make_string(desc, ttype_ascii, &p, &buffer, sizeof(buffer), decSt, err);
scale -= CVT_decompose(p, length, dtype_long, &value, err);
}
break;
@ -1054,7 +1096,7 @@ bool CVT_get_boolean(const dsc* desc, ErrorFunction err)
{
VaryStr<100> buffer; // arbitrarily large
const char* p = NULL;
int len = CVT_make_string(desc, ttype_ascii, &p, &buffer, sizeof(buffer), err);
int len = CVT_make_string(desc, ttype_ascii, &p, &buffer, sizeof(buffer), 0, err);
// Remove heading and trailing spaces.
@ -1082,7 +1124,7 @@ bool CVT_get_boolean(const dsc* desc, ErrorFunction err)
}
double CVT_get_double(const dsc* desc, ErrorFunction err)
double CVT_get_double(const dsc* desc, DecimalStatus decSt, ErrorFunction err, bool* getNumericOverflow)
{
/**************************************
*
@ -1128,6 +1170,18 @@ double CVT_get_double(const dsc* desc, ErrorFunction err)
memcpy(&value, desc->dsc_address, sizeof(double));
return value;
case dtype_dec64:
case dtype_dec128:
{
Decimal128 d128;
if (desc->dsc_dtype == dtype_dec64)
d128 = *((Decimal64*) desc->dsc_address);
else
d128 = *((Decimal128*) desc->dsc_address);
return d128.toDouble(decSt);
}
case dtype_varying:
case dtype_cstring:
case dtype_text:
@ -1136,7 +1190,7 @@ double CVT_get_double(const dsc* desc, ErrorFunction err)
const char* p;
const USHORT length =
CVT_make_string(desc, ttype_ascii, &p, &buffer, sizeof(buffer), err);
CVT_make_string(desc, ttype_ascii, &p, &buffer, sizeof(buffer), decSt, err);
value = 0.0;
int scale = 0;
SSHORT sign = 0;
@ -1217,7 +1271,15 @@ double CVT_get_double(const dsc* desc, ErrorFunction err)
// later in this routine.
if (exp >= SHORT_LIMIT)
{
if (getNumericOverflow)
{
*getNumericOverflow = true;
return 0;
}
err(Arg::Gds(isc_arith_except) << Arg::Gds(isc_numeric_out_of_range));
}
}
else if (*p == '-' && !digit_seen && !sign)
sign = -1;
@ -1250,8 +1312,15 @@ double CVT_get_double(const dsc* desc, ErrorFunction err)
// the user know...
if (ABSOLUT(scale) > DBL_MAX_10_EXP)
err(Arg::Gds(isc_arith_except) << Arg::Gds(isc_numeric_out_of_range));
{
if (getNumericOverflow)
{
*getNumericOverflow = true;
return 0;
}
err(Arg::Gds(isc_arith_except) << Arg::Gds(isc_numeric_out_of_range));
}
// Repeated division is a good way to mung the least significant bits
// of your value, so we have replaced this iterative multiplication/division
@ -1266,7 +1335,15 @@ double CVT_get_double(const dsc* desc, ErrorFunction err)
value *= CVT_power_of_ten(-scale);
if (isinf(value))
{
if (getNumericOverflow)
{
*getNumericOverflow = true;
return 0;
}
err(Arg::Gds(isc_arith_except) << Arg::Gds(isc_numeric_out_of_range));
}
}
return value;
@ -1308,7 +1385,7 @@ double CVT_get_double(const dsc* desc, ErrorFunction err)
}
void CVT_move_common(const dsc* from, dsc* to, Callbacks* cb)
void CVT_move_common(const dsc* from, dsc* to, DecimalStatus decSt, Callbacks* cb)
{
/**************************************
*
@ -1391,6 +1468,8 @@ void CVT_move_common(const dsc* from, dsc* to, Callbacks* cb)
case dtype_real:
case dtype_double:
case dtype_boolean:
case dtype_dec64:
case dtype_dec128:
CVT_conversion_error(from, cb->err);
break;
}
@ -1424,6 +1503,8 @@ void CVT_move_common(const dsc* from, dsc* to, Callbacks* cb)
case dtype_real:
case dtype_double:
case dtype_boolean:
case dtype_dec64:
case dtype_dec128:
CVT_conversion_error(from, cb->err);
break;
}
@ -1457,6 +1538,8 @@ void CVT_move_common(const dsc* from, dsc* to, Callbacks* cb)
case dtype_real:
case dtype_double:
case dtype_boolean:
case dtype_dec64:
case dtype_dec128:
CVT_conversion_error(from, cb->err);
break;
}
@ -1548,7 +1631,7 @@ void CVT_move_common(const dsc* from, dsc* to, Callbacks* cb)
{ // scope
USHORT strtype_unused;
UCHAR *ptr;
length = len = CVT_get_string_ptr_common(from, &strtype_unused, &ptr, NULL, 0, cb);
length = len = CVT_get_string_ptr_common(from, &strtype_unused, &ptr, NULL, 0, decSt, cb);
q = ptr;
} // end scope
@ -1644,6 +1727,11 @@ void CVT_move_common(const dsc* from, dsc* to, Callbacks* cb)
float_to_text(from, to, cb);
return;
case dtype_dec64:
case dtype_dec128:
decimal_float_to_text(from, to, decSt, cb);
return;
case dtype_sql_date:
case dtype_sql_time:
case dtype_timestamp:
@ -1660,7 +1748,7 @@ void CVT_move_common(const dsc* from, dsc* to, Callbacks* cb)
intermediate.makeText(static_cast<USHORT>(strlen(text)), CS_ASCII,
reinterpret_cast<UCHAR*>(text));
CVT_move_common(&intermediate, to, cb);
CVT_move_common(&intermediate, to, decSt, cb);
return;
}
@ -1695,7 +1783,7 @@ void CVT_move_common(const dsc* from, dsc* to, Callbacks* cb)
case dtype_short:
{
ULONG lval = CVT_get_long(from, (SSHORT) to->dsc_scale, cb->err);
ULONG lval = CVT_get_long(from, (SSHORT) to->dsc_scale, decSt, cb->err);
// TMN: Here we should really have the following fb_assert
// fb_assert(lval <= MAX_SSHORT);
*(SSHORT*) p = (SSHORT) lval;
@ -1705,11 +1793,11 @@ void CVT_move_common(const dsc* from, dsc* to, Callbacks* cb)
return;
case dtype_long:
*(SLONG *) p = CVT_get_long(from, (SSHORT) to->dsc_scale, cb->err);
*(SLONG *) p = CVT_get_long(from, (SSHORT) to->dsc_scale, decSt, cb->err);
return;
case dtype_int64:
*(SINT64 *) p = CVT_get_int64(from, (SSHORT) to->dsc_scale, cb->err);
*(SINT64 *) p = CVT_get_int64(from, (SSHORT) to->dsc_scale, decSt, cb->err);
return;
case dtype_quad:
@ -1719,12 +1807,12 @@ void CVT_move_common(const dsc* from, dsc* to, Callbacks* cb)
((SLONG *) p)[1] = ((SLONG *) q)[1];
return;
}
*(SQUAD *) p = CVT_get_quad(from, (SSHORT) to->dsc_scale, cb->err);
*(SQUAD *) p = CVT_get_quad(from, (SSHORT) to->dsc_scale, decSt, cb->err);
return;
case dtype_real:
{
double d_value = CVT_get_double(from, cb->err);
double d_value = CVT_get_double(from, decSt, cb->err);
if (ABSOLUT(d_value) > FLOAT_MAX)
cb->err(Arg::Gds(isc_arith_except) << Arg::Gds(isc_numeric_out_of_range));
*(float*) p = (float) d_value;
@ -1736,7 +1824,7 @@ void CVT_move_common(const dsc* from, dsc* to, Callbacks* cb)
{
USHORT strtype_unused;
UCHAR* ptr;
USHORT len = CVT_get_string_ptr_common(from, &strtype_unused, &ptr, NULL, 0, cb);
USHORT len = CVT_get_string_ptr_common(from, &strtype_unused, &ptr, NULL, 0, decSt, cb);
if (len == to->dsc_length)
{
@ -1751,14 +1839,22 @@ void CVT_move_common(const dsc* from, dsc* to, Callbacks* cb)
case DEFAULT_DOUBLE:
#ifdef HPUX
{
const double d_value = CVT_get_double(from, cb->err);
const double d_value = CVT_get_double(from, decSt, cb->err);
memcpy(p, &d_value, sizeof(double));
}
#else
*(double*) p = CVT_get_double(from, cb->err);
*(double*) p = CVT_get_double(from, decSt, cb->err);
#endif
return;
case dtype_dec64:
*((Decimal64*) p) = CVT_get_dec64(from, decSt, cb->err);
return;
case dtype_dec128:
*((Decimal128*) p) = CVT_get_dec128(from, decSt, cb->err);
return;
case dtype_boolean:
switch (from->dsc_dtype)
{
@ -1779,6 +1875,8 @@ void CVT_move_common(const dsc* from, dsc* to, Callbacks* cb)
case dtype_quad:
case dtype_real:
case dtype_double:
case dtype_dec64:
case dtype_dec128:
CVT_conversion_error(from, cb->err);
break;
}
@ -1832,7 +1930,7 @@ void CVT_conversion_error(const dsc* desc, ErrorFunction err)
const char* p;
VaryStr<128> s;
const USHORT length =
CVT_make_string(desc, ttype_ascii, &p, &s, sizeof(s), localError);
CVT_make_string(desc, ttype_ascii, &p, &s, sizeof(s), 0, localError);
message.assign(p, length);
}
/*
@ -1975,7 +2073,49 @@ static void datetime_to_text(const dsc* from, dsc* to, Callbacks* cb)
desc.dsc_length = MIN(desc.dsc_length, (to->dsc_length - l));
}
CVT_move_common(&desc, to, cb);
CVT_move_common(&desc, to, 0, cb);
}
void CVT_make_null_string(const dsc* desc,
USHORT to_interp,
const char** address,
vary* temp,
USHORT length,
DecimalStatus decSt,
ErrorFunction err)
{
/**************************************
*
* C V T _ m a k e _ n u l l _ s t r i n g
*
**************************************
*
* Functional description
* Convert the data from the desc to a zero-terminated string.
* The pointer to this string is returned in address.
* Data always placed to temp buffer.
*
**************************************/
fb_assert(temp);
USHORT len = CVT_make_string(desc, to_interp, address, temp, --length, decSt, err);
if (*address != temp->vary_string)
{
length -= sizeof(USHORT); // Take into an account VaryStr specifics
if (len > length)
{
err(Arg::Gds(isc_arith_except) << Arg::Gds(isc_string_truncation) <<
Arg::Gds(isc_imp_exc) <<
Arg::Gds(isc_trunc_limits) << Arg::Num(length) << Arg::Num(len));
}
memcpy(temp->vary_string, *address, len);
temp->vary_length = len;
}
fb_assert(temp->vary_length == len);
temp->vary_string[len] = 0;
}
@ -1984,6 +2124,7 @@ USHORT CVT_make_string(const dsc* desc,
const char** address,
vary* temp,
USHORT length,
DecimalStatus decSt,
ErrorFunction err)
{
/**************************************
@ -2035,7 +2176,7 @@ USHORT CVT_make_string(const dsc* desc,
temp_desc.dsc_address = (UCHAR *) temp;
temp_desc.dsc_dtype = dtype_varying;
temp_desc.setTextType(to_interp);
CVT_move(desc, &temp_desc, err);
CVT_move(desc, &temp_desc, decSt, err);
*address = temp->vary_string;
return temp->vary_length;
@ -2305,7 +2446,7 @@ SSHORT CVT_decompose(const char* string,
USHORT CVT_get_string_ptr_common(const dsc* desc, USHORT* ttype, UCHAR** address,
vary* temp, USHORT length, Callbacks* cb)
vary* temp, USHORT length, DecimalStatus decSt, Callbacks* cb)
{
/**************************************
*
@ -2371,7 +2512,7 @@ USHORT CVT_get_string_ptr_common(const dsc* desc, USHORT* ttype, UCHAR** address
temp_desc.dsc_address = (UCHAR *) temp;
temp_desc.dsc_dtype = dtype_varying;
temp_desc.setTextType(ttype_ascii);
CVT_move_common(desc, &temp_desc, cb);
CVT_move_common(desc, &temp_desc, decSt, cb);
*address = reinterpret_cast<UCHAR*>(temp->vary_string);
*ttype = INTL_TTYPE(&temp_desc);
@ -2379,7 +2520,182 @@ USHORT CVT_get_string_ptr_common(const dsc* desc, USHORT* ttype, UCHAR** address
}
SQUAD CVT_get_quad(const dsc* desc, SSHORT scale, ErrorFunction err)
static inline void SINT64_to_SQUAD(const SINT64 input, const SQUAD& value)
{
((SLONG*) &value)[LOW_WORD] = (SLONG) (input & 0xffffffff);
((SLONG*) &value)[HIGH_WORD] = (SLONG) (input >> 32);
}
Decimal64 CVT_get_dec64(const dsc* desc, DecimalStatus decSt, ErrorFunction err)
{
/**************************************
*
* C V T _ g e t _ d e c 6 4
*
**************************************
*
* Functional description
* Convert something arbitrary to a DecFloat(16) / (64 bit).
*
**************************************/
VaryStr<512> buffer; // long enough to represent largest decimal float in ASCII
Decimal64 d64;
// adjust exact numeric values to same scaling
int scale = 0;
if (DTYPE_IS_EXACT(desc->dsc_dtype))
scale = -desc->dsc_scale;
const char* p = reinterpret_cast<char*>(desc->dsc_address);
try
{
switch (desc->dsc_dtype)
{
case dtype_short:
return d64.set(*(SSHORT*) p, decSt, scale);
case dtype_long:
return d64.set(*(SLONG*) p, decSt, scale);
case dtype_quad:
return d64.set(CVT_get_int64(desc, 0, decSt, err), decSt, scale);
case dtype_int64:
return d64.set(*(SINT64*) p, decSt, scale);
case dtype_varying:
case dtype_cstring:
case dtype_text:
CVT_make_null_string(desc, ttype_ascii, &p, &buffer, sizeof(buffer) - 1, decSt, err);
return d64.set(buffer.vary_string, decSt);
case dtype_blob:
case dtype_sql_date:
case dtype_sql_time:
case dtype_timestamp:
case dtype_array:
case dtype_dbkey:
case dtype_boolean:
CVT_conversion_error(desc, err);
break;
case dtype_real:
return d64.set(*((float*) p), decSt);
case dtype_double:
return d64.set(*((double*) p), decSt);
case dtype_dec64:
return *(Decimal64*) p;
case dtype_dec128:
return ((Decimal128*) p)->toDecimal64(decSt);
default:
fb_assert(false);
err(Arg::Gds(isc_badblk)); // internal error
break;
}
}
catch (const Exception& ex)
{
// reraise using passed error function
Arg::StatusVector v(ex);
err(v);
}
// compiler silencer
return d64;
}
Decimal128 CVT_get_dec128(const dsc* desc, DecimalStatus decSt, ErrorFunction err)
{
/**************************************
*
* C V T _ g e t _ d e c 1 2 8
*
**************************************
*
* Functional description
* Convert something arbitrary to a DecFloat(34) / (128 bit).
*
**************************************/
VaryStr<1024> buffer; // represents unreasonably long decfloat literal in ASCII
Decimal128 d128;
// adjust exact numeric values to same scaling
int scale = 0;
if (DTYPE_IS_EXACT(desc->dsc_dtype))
scale = -desc->dsc_scale;
const char* p = reinterpret_cast<char*>(desc->dsc_address);
try
{
switch (desc->dsc_dtype)
{
case dtype_short:
return d128.set(*(SSHORT*) p, decSt, scale);
case dtype_long:
return d128.set(*(SLONG*) p, decSt, scale);
case dtype_quad:
return d128.set(CVT_get_int64(desc, 0, decSt, err), decSt, scale);
case dtype_int64:
return d128.set(*(SINT64*) p, decSt, scale);
case dtype_varying:
case dtype_cstring:
case dtype_text:
CVT_make_null_string(desc, ttype_ascii, &p, &buffer, sizeof(buffer) - 1, decSt, err);
return d128.set(buffer.vary_string, decSt);
case dtype_blob:
case dtype_sql_date:
case dtype_sql_time:
case dtype_timestamp:
case dtype_array:
case dtype_dbkey:
case dtype_boolean:
CVT_conversion_error(desc, err);
break;
case dtype_real:
return d128.set(*((float*) p), decSt);
case dtype_double:
return d128.set(*((double*) p), decSt);
case dtype_dec64:
return (d128 = (*(Decimal64*) p)); // cast to higher precision never cause rounding/traps
case dtype_dec128:
return *(Decimal128*) p;
default:
fb_assert(false);
err(Arg::Gds(isc_badblk)); // internal error
break;
}
}
catch (const Exception& ex)
{
// reraise using passed error function
Arg::StatusVector v(ex);
err(v);
}
// compiler silencer
return d128;
}
SQUAD CVT_get_quad(const dsc* desc, SSHORT scale, DecimalStatus decSt, ErrorFunction err)
{
/**************************************
*
@ -2425,11 +2741,7 @@ SQUAD CVT_get_quad(const dsc* desc, SSHORT scale, ErrorFunction err)
break;
case dtype_int64:
{
const SINT64 input = *(SINT64*) p;
((SLONG*) &value)[LOW_WORD] = (SLONG) (input & 0xffffffff);
((SLONG*) &value)[HIGH_WORD] = (SLONG) (input >> 32);
}
SINT64_to_SQUAD(*(SINT64*) p, value);
break;
case dtype_varying:
@ -2437,7 +2749,7 @@ SQUAD CVT_get_quad(const dsc* desc, SSHORT scale, ErrorFunction err)
case dtype_text:
{
USHORT length =
CVT_make_string(desc, ttype_ascii, &p, &buffer, sizeof(buffer), 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);
}
break;
@ -2452,6 +2764,11 @@ SQUAD CVT_get_quad(const dsc* desc, SSHORT scale, ErrorFunction err)
CVT_conversion_error(desc, err);
break;
case dtype_dec64:
case dtype_dec128:
SINT64_to_SQUAD(CVT_get_int64(desc, scale, decSt, err), value);
break;
default:
fb_assert(false);
err(Arg::Gds(isc_badblk)); // internal error
@ -2470,7 +2787,7 @@ SQUAD CVT_get_quad(const dsc* desc, SSHORT scale, ErrorFunction err)
}
SINT64 CVT_get_int64(const dsc* desc, SSHORT scale, ErrorFunction err)
SINT64 CVT_get_int64(const dsc* desc, SSHORT scale, DecimalStatus decSt, ErrorFunction err)
{
/**************************************
*
@ -2512,6 +2829,18 @@ SINT64 CVT_get_int64(const dsc* desc, SSHORT scale, ErrorFunction err)
value = (((SINT64) ((SLONG*) p)[HIGH_WORD]) << 32) + (((ULONG*) p)[LOW_WORD]);
break;
case dtype_dec64:
case dtype_dec128:
{
Decimal128 d128;
if (desc->dsc_dtype == dtype_dec64)
d128 = *((Decimal64*) p);
else
d128 = *((Decimal128*) p);
return d128.toInt64(decSt, scale);
}
case dtype_real:
case dtype_double:
if (desc->dsc_dtype == dtype_real)
@ -2556,7 +2885,7 @@ SINT64 CVT_get_int64(const dsc* desc, SSHORT scale, ErrorFunction err)
case dtype_text:
{
USHORT length =
CVT_make_string(desc, ttype_ascii, &p, &buffer, sizeof(buffer), err);
CVT_make_string(desc, ttype_ascii, &p, &buffer, sizeof(buffer), decSt, err);
scale -= CVT_decompose(p, length, dtype_int64, (SLONG *) & value, err);
}
break;
@ -2725,7 +3054,7 @@ namespace
USHORT CVT_get_string_ptr(const dsc* desc, USHORT* ttype, UCHAR** address,
vary* temp, USHORT length, ErrorFunction err)
vary* temp, USHORT length, DecimalStatus decSt, ErrorFunction err)
{
/**************************************
*
@ -2752,11 +3081,11 @@ USHORT CVT_get_string_ptr(const dsc* desc, USHORT* ttype, UCHAR** address,
fb_assert(err != NULL);
CommonCallbacks callbacks(err);
return CVT_get_string_ptr_common(desc, ttype, address, temp, length, &callbacks);
return CVT_get_string_ptr_common(desc, ttype, address, temp, length, decSt, &callbacks);
}
void CVT_move(const dsc* from, dsc* to, ErrorFunction err)
void CVT_move(const dsc* from, dsc* to, DecimalStatus decSt, ErrorFunction err)
{
/**************************************
*
@ -2769,5 +3098,5 @@ void CVT_move(const dsc* from, dsc* to, ErrorFunction err)
*
**************************************/
CommonCallbacks callbacks(err);
CVT_move_common(from, to, &callbacks);
CVT_move_common(from, to, decSt, &callbacks);
}

View File

@ -29,6 +29,8 @@
#ifndef COMMON_CVT_H
#define COMMON_CVT_H
#include "../common/DecFloat.h"
namespace Jrd {
class CharSet;
@ -70,16 +72,19 @@ public:
void CVT_conversion_error(const dsc*, ErrorFunction);
double CVT_power_of_ten(const int);
SLONG CVT_get_long(const dsc*, SSHORT, ErrorFunction);
SLONG CVT_get_long(const dsc*, SSHORT, Firebird::DecimalStatus, ErrorFunction);
bool CVT_get_boolean(const dsc*, ErrorFunction);
double CVT_get_double(const dsc*, ErrorFunction);
USHORT CVT_make_string(const dsc*, USHORT, const char**, vary*, USHORT, ErrorFunction);
void CVT_move_common(const dsc*, dsc*, Firebird::Callbacks*);
void CVT_move(const dsc*, dsc*, ErrorFunction);
double CVT_get_double(const dsc*, Firebird::DecimalStatus, ErrorFunction, bool* getNumericOverflow = nullptr);
Firebird::Decimal64 CVT_get_dec64(const dsc*, Firebird::DecimalStatus, ErrorFunction);
Firebird::Decimal128 CVT_get_dec128(const dsc*, Firebird::DecimalStatus, ErrorFunction);
USHORT CVT_make_string(const dsc*, USHORT, const char**, vary*, USHORT, Firebird::DecimalStatus, ErrorFunction);
void CVT_make_null_string(const dsc*, USHORT, const char**, vary*, USHORT, Firebird::DecimalStatus, ErrorFunction);
void CVT_move_common(const dsc*, dsc*, Firebird::DecimalStatus, Firebird::Callbacks*);
void CVT_move(const dsc*, dsc*, Firebird::DecimalStatus, ErrorFunction);
SSHORT CVT_decompose(const char*, USHORT, SSHORT, SLONG*, ErrorFunction);
USHORT CVT_get_string_ptr(const dsc*, USHORT*, UCHAR**, vary*, USHORT, ErrorFunction);
USHORT CVT_get_string_ptr_common(const dsc*, USHORT*, UCHAR**, vary*, USHORT, Firebird::Callbacks*);
SINT64 CVT_get_int64(const dsc*, SSHORT, ErrorFunction);
SQUAD CVT_get_quad(const dsc*, SSHORT, ErrorFunction);
USHORT CVT_get_string_ptr(const dsc*, USHORT*, UCHAR**, vary*, USHORT, Firebird::DecimalStatus, ErrorFunction);
USHORT CVT_get_string_ptr_common(const dsc*, USHORT*, UCHAR**, vary*, USHORT, Firebird::DecimalStatus, Firebird::Callbacks*);
SINT64 CVT_get_int64(const dsc*, SSHORT, Firebird::DecimalStatus, ErrorFunction);
SQUAD CVT_get_quad(const dsc*, SSHORT, Firebird::DecimalStatus, ErrorFunction);
#endif //COMMON_CVT_H

View File

@ -64,7 +64,9 @@ static const USHORT _DSC_convert_to_text_length[DTYPE_TYPE_MAX] =
9, // dtype_array FFFF:FFFF
20, // dtype_int64 -9223372036854775808
0, // dtype_dbkey
5 // dtype_boolean
5, // dtype_boolean
23, // dtype_dec64 1 + 1 + 1 + 1 + 16(34) + 3(4)
42 // dtype_dec128 +- . e +- coeff + exp
};
// blr to dsc type conversions
@ -89,7 +91,9 @@ static const USHORT DSC_blr_type_mapping[] =
blr_blob,
blr_int64,
blr_null,
blr_bool
blr_bool,
blr_dec64,
blr_dec128
};
// Unimplemented names are in lowercase & <brackets>
@ -117,7 +121,9 @@ static const TEXT* const DSC_dtype_names[] =
"ARRAY",
"BIGINT",
"DB_KEY",
"BOOLEAN"
"BOOLEAN",
"DECFLOAT(16)",
"DECFLOAT(34)"
};
@ -130,12 +136,12 @@ const BYTE DSC_add_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
{
/*
dtype_unknown dtype_text dtype_cstring dtype_varying
4 (unused) 5 (unused) dtype_packed dtype_byte
dtype_short dtype_long dtype_quad dtype_real
dtype_unknown dtype_text dtype_cstring dtype_varying
4 (unused) 5 (unused) dtype_packed dtype_byte
dtype_short dtype_long dtype_quad dtype_real
dtype_double dtype_d_float dtype_sql_date dtype_sql_time
dtype_timestamp dtype_blob dtype_array dtype_int64
dtype_dbkey, dtype_boolean
dtype_timestamp dtype_blob dtype_array dtype_int64
dtype_dbkey dtype_boolean dtype_dec64 dtype_dec128
*/
// dtype_unknown
@ -144,7 +150,7 @@ const BYTE DSC_add_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_unknown, dtype_unknown, DTYPE_CANNOT, dtype_unknown,
dtype_unknown, dtype_unknown, dtype_unknown, dtype_unknown,
dtype_unknown, DTYPE_CANNOT, DTYPE_CANNOT, dtype_unknown,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_unknown, dtype_unknown},
// dtype_text
{dtype_unknown, dtype_double, dtype_double, dtype_double,
@ -152,7 +158,7 @@ const BYTE DSC_add_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_double, dtype_double, DTYPE_CANNOT, dtype_double,
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128},
// dtype_cstring
{dtype_unknown, dtype_double, dtype_double, dtype_double,
@ -160,7 +166,7 @@ const BYTE DSC_add_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_double, dtype_double, DTYPE_CANNOT, dtype_double,
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128},
// dtype_varying
{dtype_unknown, dtype_double, dtype_double, dtype_double,
@ -168,7 +174,7 @@ const BYTE DSC_add_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_double, dtype_double, DTYPE_CANNOT, dtype_double,
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128},
// 4 (unused)
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -176,7 +182,7 @@ const BYTE DSC_add_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT},
// 5 (unused)
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -184,7 +190,7 @@ const BYTE DSC_add_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT},
// dtype_packed
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -192,7 +198,7 @@ const BYTE DSC_add_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT},
// dtype_byte
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -200,7 +206,7 @@ const BYTE DSC_add_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT},
// dtype_short
{dtype_unknown, dtype_double, dtype_double, dtype_double,
@ -208,7 +214,7 @@ const BYTE DSC_add_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_int64, dtype_int64, DTYPE_CANNOT, dtype_double,
dtype_double, dtype_d_float, dtype_sql_date, dtype_sql_time,
dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int64,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128},
// dtype_long
{dtype_unknown, dtype_double, dtype_double, dtype_double,
@ -216,7 +222,7 @@ const BYTE DSC_add_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_int64, dtype_int64, DTYPE_CANNOT, dtype_double,
dtype_double, dtype_d_float, dtype_sql_date, dtype_sql_time,
dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int64,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128},
// dtype_quad
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -224,7 +230,7 @@ const BYTE DSC_add_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT},
// dtype_real
{dtype_unknown, dtype_double, dtype_double, dtype_double,
@ -232,7 +238,7 @@ const BYTE DSC_add_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_double, dtype_double, DTYPE_CANNOT, dtype_double,
dtype_double, dtype_d_float, dtype_sql_date, dtype_sql_time,
dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_double, dtype_double},
// dtype_double
{dtype_unknown, dtype_double, dtype_double, dtype_double,
@ -240,7 +246,7 @@ const BYTE DSC_add_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_double, dtype_double, DTYPE_CANNOT, dtype_double,
dtype_double, dtype_d_float, dtype_sql_date, dtype_sql_time,
dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_double, dtype_double},
// dtype_d_float -- VMS deprecated
{dtype_unknown, dtype_d_float, dtype_d_float, dtype_d_float,
@ -248,7 +254,7 @@ const BYTE DSC_add_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_d_float, dtype_d_float, DTYPE_CANNOT, dtype_d_float,
dtype_d_float, dtype_d_float, dtype_sql_date, dtype_sql_time,
dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_d_float,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_d_float, dtype_d_float},
// dtype_sql_date
{dtype_unknown, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -256,7 +262,7 @@ const BYTE DSC_add_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_sql_date, dtype_sql_date, DTYPE_CANNOT, dtype_sql_date,
dtype_sql_date, dtype_sql_date, DTYPE_CANNOT, dtype_timestamp,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_sql_date,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_sql_date, dtype_sql_date},
// dtype_sql_time
{dtype_unknown, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -264,7 +270,7 @@ const BYTE DSC_add_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_sql_time, dtype_sql_time, DTYPE_CANNOT, dtype_sql_time,
dtype_sql_time, dtype_sql_time, dtype_timestamp, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_sql_time,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_sql_time, dtype_sql_time},
// dtype_timestamp
{dtype_unknown, dtype_timestamp, dtype_timestamp, dtype_timestamp,
@ -272,7 +278,7 @@ const BYTE DSC_add_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_timestamp, dtype_timestamp, DTYPE_CANNOT, dtype_timestamp,
dtype_timestamp, dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_timestamp,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_timestamp, dtype_timestamp},
// dtype_blob
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -280,7 +286,7 @@ const BYTE DSC_add_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT},
// dtype_array
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -288,7 +294,7 @@ const BYTE DSC_add_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT},
// dtype_int64
{dtype_unknown, dtype_double, dtype_double, dtype_double,
@ -296,7 +302,7 @@ const BYTE DSC_add_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_int64, dtype_int64, DTYPE_CANNOT, dtype_double,
dtype_double, dtype_d_float, dtype_sql_date, dtype_sql_time,
dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int64,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128},
// dtype_dbkey
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -304,7 +310,7 @@ const BYTE DSC_add_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT},
// dtype_boolean
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -312,7 +318,23 @@ const BYTE DSC_add_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT}
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT},
// dtype_dec64
{dtype_unknown, dtype_dec128, dtype_dec128, dtype_dec128,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
dtype_dec128, dtype_dec128, DTYPE_CANNOT, dtype_double,
dtype_double, dtype_d_float, dtype_sql_date, dtype_sql_time,
dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128,
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128},
// dtype_dec128
{dtype_unknown, dtype_dec128, dtype_dec128, dtype_dec128,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
dtype_dec128, dtype_dec128, DTYPE_CANNOT, dtype_double,
dtype_double, dtype_d_float, dtype_sql_date, dtype_sql_time,
dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128,
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128}
};
@ -325,12 +347,12 @@ const BYTE DSC_sub_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
{
/*
dtype_unknown dtype_text dtype_cstring dtype_varying
4 (unused) 5 (unused) dtype_packed dtype_byte
dtype_short dtype_long dtype_quad dtype_real
dtype_unknown dtype_text dtype_cstring dtype_varying
4 (unused) 5 (unused) dtype_packed dtype_byte
dtype_short dtype_long dtype_quad dtype_real
dtype_double dtype_d_float dtype_sql_date dtype_sql_time
dtype_timestamp dtype_blob dtype_array dtype_int64
dtype_dbkey, dtype_boolean
dtype_timestamp dtype_blob dtype_array dtype_int64
dtype_dbkey dtype_boolean dtype_dec64 dtype_dec128
*/
// dtype_unknown
@ -339,7 +361,7 @@ const BYTE DSC_sub_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_unknown, dtype_unknown, DTYPE_CANNOT, dtype_unknown,
dtype_unknown, dtype_unknown, dtype_unknown, dtype_unknown,
dtype_unknown, DTYPE_CANNOT, DTYPE_CANNOT, dtype_unknown,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_unknown, dtype_unknown},
// dtype_text
{dtype_unknown, dtype_double, dtype_double, dtype_double,
@ -347,7 +369,7 @@ const BYTE DSC_sub_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_double, dtype_double, DTYPE_CANNOT, dtype_double,
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128},
// dtype_cstring
{dtype_unknown, dtype_double, dtype_double, dtype_double,
@ -355,7 +377,7 @@ const BYTE DSC_sub_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_double, dtype_double, DTYPE_CANNOT, dtype_double,
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128},
// dtype_varying
{dtype_unknown, dtype_double, dtype_double, dtype_double,
@ -363,7 +385,7 @@ const BYTE DSC_sub_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_double, dtype_double, DTYPE_CANNOT, dtype_double,
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128},
// 4 (unused)
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -371,7 +393,7 @@ const BYTE DSC_sub_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT},
// 5 (unused)
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -379,7 +401,7 @@ const BYTE DSC_sub_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT},
// dtype_packed
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -387,7 +409,7 @@ const BYTE DSC_sub_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT},
// dtype_byte
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -395,7 +417,7 @@ const BYTE DSC_sub_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT},
// dtype_short
{dtype_unknown, dtype_double, dtype_double, dtype_double,
@ -403,7 +425,7 @@ const BYTE DSC_sub_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_int64, dtype_int64, DTYPE_CANNOT, dtype_double,
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int64,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128},
// dtype_long
{dtype_unknown, dtype_double, dtype_double, dtype_double,
@ -411,7 +433,7 @@ const BYTE DSC_sub_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_int64, dtype_int64, DTYPE_CANNOT, dtype_double,
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int64,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128},
// dtype_quad
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -419,7 +441,7 @@ const BYTE DSC_sub_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT},
// dtype_real
{dtype_unknown, dtype_double, dtype_double, dtype_double,
@ -427,7 +449,7 @@ const BYTE DSC_sub_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_double, dtype_double, DTYPE_CANNOT, dtype_double,
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_double, dtype_double},
// dtype_double
{dtype_unknown, dtype_double, dtype_double, dtype_double,
@ -435,7 +457,7 @@ const BYTE DSC_sub_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_double, dtype_double, DTYPE_CANNOT, dtype_double,
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_double, dtype_double},
// dtype_d_float -- VMS deprecated
{dtype_unknown, dtype_d_float, dtype_d_float, dtype_d_float,
@ -443,7 +465,7 @@ const BYTE DSC_sub_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_d_float, dtype_d_float, DTYPE_CANNOT, dtype_d_float,
dtype_d_float, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_d_float,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_d_float, dtype_d_float},
// dtype_sql_date
{dtype_unknown, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -451,7 +473,7 @@ const BYTE DSC_sub_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_sql_date, dtype_sql_date, DTYPE_CANNOT, dtype_sql_date,
dtype_sql_date, dtype_sql_date, dtype_long, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_sql_date,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_sql_date, dtype_sql_date},
// dtype_sql_time
{dtype_unknown, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -459,7 +481,7 @@ const BYTE DSC_sub_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_sql_time, dtype_sql_time, DTYPE_CANNOT, dtype_sql_time,
dtype_sql_time, dtype_sql_time, DTYPE_CANNOT, dtype_long,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_sql_time,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_sql_time, dtype_sql_time},
// dtype_timestamp
{dtype_unknown, dtype_timestamp, dtype_timestamp, dtype_timestamp,
@ -467,7 +489,7 @@ const BYTE DSC_sub_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_timestamp, dtype_timestamp, DTYPE_CANNOT, dtype_timestamp,
dtype_timestamp, dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT,
dtype_double, DTYPE_CANNOT, DTYPE_CANNOT, dtype_timestamp,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_timestamp, dtype_timestamp},
// dtype_blob
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -475,7 +497,7 @@ const BYTE DSC_sub_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT},
// dtype_array
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -483,7 +505,7 @@ const BYTE DSC_sub_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT},
// dtype_int64
{dtype_unknown, dtype_double, dtype_double, dtype_double,
@ -491,7 +513,7 @@ const BYTE DSC_sub_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_int64, dtype_int64, DTYPE_CANNOT, dtype_double,
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int64,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128},
// dtype_dbkey
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -499,7 +521,7 @@ const BYTE DSC_sub_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT},
// dtype_boolean
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -507,7 +529,24 @@ const BYTE DSC_sub_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT}
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT},
// dtype_dec64
{dtype_unknown, dtype_dec128, dtype_dec128, dtype_dec128,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
dtype_dec128, dtype_dec128, DTYPE_CANNOT, dtype_double,
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128,
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128},
// dtype_dec128
{dtype_unknown, dtype_dec128, dtype_dec128, dtype_dec128,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
dtype_dec128, dtype_dec128, DTYPE_CANNOT, dtype_double,
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128,
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128}
};
@ -520,12 +559,12 @@ const BYTE DSC_multiply_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
{
/*
dtype_unknown dtype_text dtype_cstring dtype_varying
4 (unused) 5 (unused) dtype_packed dtype_byte
dtype_short dtype_long dtype_quad dtype_real
dtype_unknown dtype_text dtype_cstring dtype_varying
4 (unused) 5 (unused) dtype_packed dtype_byte
dtype_short dtype_long dtype_quad dtype_real
dtype_double dtype_d_float dtype_sql_date dtype_sql_time
dtype_timestamp dtype_blob dtype_array dtype_int64
dtype_dbkey, dtype_boolean
dtype_timestamp dtype_blob dtype_array dtype_int64
dtype_dbkey dtype_boolean dtype_dec64 dtype_dec128
*/
// dtype_unknown
@ -534,7 +573,7 @@ const BYTE DSC_multiply_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_unknown, dtype_unknown, DTYPE_CANNOT, dtype_unknown,
dtype_unknown, dtype_unknown, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_unknown,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_unknown, dtype_unknown},
// dtype_text
{dtype_unknown, dtype_double, dtype_double, dtype_double,
@ -542,7 +581,7 @@ const BYTE DSC_multiply_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_double, dtype_double, DTYPE_CANNOT, dtype_double,
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128},
// dtype_cstring
{dtype_unknown, dtype_double, dtype_double, dtype_double,
@ -550,7 +589,7 @@ const BYTE DSC_multiply_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_double, dtype_double, DTYPE_CANNOT, dtype_double,
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128},
// dtype_varying
{dtype_unknown, dtype_double, dtype_double, dtype_double,
@ -558,7 +597,7 @@ const BYTE DSC_multiply_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_double, dtype_double, DTYPE_CANNOT, dtype_double,
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128},
// 4 (unused)
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -566,7 +605,7 @@ 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_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT},
// 5 (unused)
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -574,7 +613,7 @@ 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_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT},
// dtype_packed
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -582,7 +621,7 @@ 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_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT},
// dtype_byte
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -590,7 +629,7 @@ 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_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT},
// dtype_short
{dtype_unknown, dtype_double, dtype_double, dtype_double,
@ -598,7 +637,7 @@ const BYTE DSC_multiply_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_int64, dtype_int64, DTYPE_CANNOT, dtype_double,
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int64,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128},
// dtype_long
{dtype_unknown, dtype_double, dtype_double, dtype_double,
@ -606,7 +645,7 @@ const BYTE DSC_multiply_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_int64, dtype_int64, DTYPE_CANNOT, dtype_double,
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int64,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128},
// dtype_quad
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -614,7 +653,7 @@ 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_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT},
// dtype_real
{dtype_unknown, dtype_double, dtype_double, dtype_double,
@ -622,7 +661,7 @@ const BYTE DSC_multiply_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_double, dtype_double, DTYPE_CANNOT, dtype_double,
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_double, dtype_double},
// dtype_double
{dtype_unknown, dtype_double, dtype_double, dtype_double,
@ -630,7 +669,7 @@ const BYTE DSC_multiply_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_double, dtype_double, DTYPE_CANNOT, dtype_double,
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_double, dtype_double},
// dtype_d_float -- VMS deprecated
{dtype_unknown, dtype_d_float, dtype_d_float, dtype_d_float,
@ -638,7 +677,7 @@ const BYTE DSC_multiply_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_d_float, dtype_d_float, DTYPE_CANNOT, dtype_d_float,
dtype_d_float, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_d_float,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_d_float, dtype_d_float},
// dtype_sql_date
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -646,7 +685,7 @@ 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_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT},
// dtype_sql_time
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -654,7 +693,7 @@ 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_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT},
// dtype_timestamp
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -662,7 +701,7 @@ 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_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT},
// dtype_blob
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -670,7 +709,7 @@ 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_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT},
// dtype_array
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -678,7 +717,7 @@ 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_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT},
// dtype_int64
{dtype_unknown, dtype_double, dtype_double, dtype_double,
@ -686,7 +725,7 @@ const BYTE DSC_multiply_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_int64, dtype_int64, DTYPE_CANNOT, dtype_double,
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int64,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128},
// dtype_dbkey
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -694,7 +733,7 @@ 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_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT},
// dtype_boolean
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -702,7 +741,23 @@ 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_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT}
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT},
// dtype_dec64
{dtype_unknown, dtype_dec128, dtype_dec128, dtype_dec128,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
dtype_dec128, dtype_dec128, DTYPE_CANNOT, dtype_double,
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128,
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128},
// dtype_dec128
{dtype_unknown, dtype_dec128, dtype_dec128, dtype_dec128,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
dtype_dec128, dtype_dec128, DTYPE_CANNOT, dtype_double,
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128,
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128}
};
@ -715,12 +770,12 @@ const BYTE DSC_multiply_blr4_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
{
/*
dtype_unknown dtype_text dtype_cstring dtype_varying
4 (unused) 5 (unused) dtype_packed dtype_byte
dtype_short dtype_long dtype_quad dtype_real
dtype_unknown dtype_text dtype_cstring dtype_varying
4 (unused) 5 (unused) dtype_packed dtype_byte
dtype_short dtype_long dtype_quad dtype_real
dtype_double dtype_d_float dtype_sql_date dtype_sql_time
dtype_timestamp dtype_blob dtype_array dtype_int64
dtype_dbkey, dtype_boolean
dtype_timestamp dtype_blob dtype_array dtype_int64
dtype_dbkey dtype_boolean dtype_dec64 dtype_dec128
*/
// dtype_unknown
@ -729,7 +784,7 @@ const BYTE DSC_multiply_blr4_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_unknown, dtype_unknown, DTYPE_CANNOT, dtype_unknown,
dtype_unknown, dtype_unknown, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_unknown,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_unknown, dtype_unknown},
// dtype_text
{dtype_unknown, dtype_double, dtype_double, dtype_double,
@ -737,7 +792,7 @@ const BYTE DSC_multiply_blr4_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_double, dtype_double, DTYPE_CANNOT, dtype_double,
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128},
// dtype_cstring
{dtype_unknown, dtype_double, dtype_double, dtype_double,
@ -745,7 +800,7 @@ const BYTE DSC_multiply_blr4_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_double, dtype_double, DTYPE_CANNOT, dtype_double,
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128},
// dtype_varying
{dtype_unknown, dtype_double, dtype_double, dtype_double,
@ -753,7 +808,7 @@ const BYTE DSC_multiply_blr4_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_double, dtype_double, DTYPE_CANNOT, dtype_double,
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128},
// 4 (unused)
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -761,7 +816,7 @@ const BYTE DSC_multiply_blr4_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT},
// 5 (unused)
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -769,7 +824,7 @@ const BYTE DSC_multiply_blr4_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT},
// dtype_packed
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -777,7 +832,7 @@ const BYTE DSC_multiply_blr4_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT},
// dtype_byte
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -785,7 +840,7 @@ const BYTE DSC_multiply_blr4_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT},
// dtype_short
{dtype_unknown, dtype_double, dtype_double, dtype_double,
@ -793,7 +848,7 @@ const BYTE DSC_multiply_blr4_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_long, dtype_long, DTYPE_CANNOT, dtype_double,
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128},
// dtype_long
{dtype_unknown, dtype_double, dtype_double, dtype_double,
@ -801,7 +856,7 @@ const BYTE DSC_multiply_blr4_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_long, dtype_long, DTYPE_CANNOT, dtype_double,
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128},
// dtype_quad
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -809,7 +864,7 @@ const BYTE DSC_multiply_blr4_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT},
// dtype_real
{dtype_unknown, dtype_double, dtype_double, dtype_double,
@ -817,7 +872,7 @@ const BYTE DSC_multiply_blr4_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_double, dtype_double, DTYPE_CANNOT, dtype_double,
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_double, dtype_double},
// dtype_double
{dtype_unknown, dtype_double, dtype_double, dtype_double,
@ -825,7 +880,7 @@ const BYTE DSC_multiply_blr4_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_double, dtype_double, DTYPE_CANNOT, dtype_double,
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_double, dtype_double},
// dtype_d_float -- VMS deprecated
{dtype_unknown, dtype_d_float, dtype_d_float, dtype_d_float,
@ -833,7 +888,7 @@ const BYTE DSC_multiply_blr4_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_d_float, dtype_d_float, DTYPE_CANNOT, dtype_d_float,
dtype_d_float, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_d_float,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_d_float, dtype_d_float},
// dtype_sql_date
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -841,7 +896,7 @@ const BYTE DSC_multiply_blr4_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT},
// dtype_sql_time
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -849,7 +904,7 @@ const BYTE DSC_multiply_blr4_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT},
// dtype_timestamp
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -857,7 +912,7 @@ const BYTE DSC_multiply_blr4_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT},
// dtype_blob
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -865,7 +920,7 @@ const BYTE DSC_multiply_blr4_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT},
// dtype_array
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -873,7 +928,7 @@ const BYTE DSC_multiply_blr4_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT},
// dtype_int64
{dtype_unknown, dtype_double, dtype_double, dtype_double,
@ -881,7 +936,7 @@ const BYTE DSC_multiply_blr4_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
dtype_double, dtype_double, DTYPE_CANNOT, dtype_double,
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128},
// dtype_dbkey
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -889,7 +944,7 @@ const BYTE DSC_multiply_blr4_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT},
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT},
// dtype_boolean
{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
@ -897,7 +952,23 @@ const BYTE DSC_multiply_blr4_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT}
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT},
// dtype_dec64
{dtype_unknown, dtype_dec128, dtype_dec128, dtype_dec128,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
dtype_dec128, dtype_dec128, DTYPE_CANNOT, dtype_double,
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128,
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128},
// dtype_dec128
{dtype_unknown, dtype_dec128, dtype_dec128, dtype_dec128,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
dtype_dec128, dtype_dec128, DTYPE_CANNOT, dtype_double,
dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128,
DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128}
};
@ -1003,6 +1074,16 @@ bool DSC_make_descriptor(DSC* desc,
desc->dsc_dtype = dtype_double;
break;
case blr_dec64:
desc->dsc_length = sizeof(Decimal64);
desc->dsc_dtype = dtype_dec64;
break;
case blr_dec128:
desc->dsc_length = sizeof(Decimal128);
desc->dsc_dtype = dtype_dec128;
break;
case blr_timestamp:
desc->dsc_length = 2 * sizeof(SLONG);
desc->dsc_dtype = dtype_timestamp;
@ -1164,6 +1245,10 @@ const char* dsc::typeToText() const
return "dbkey";
case dtype_boolean:
return "boolean";
case dtype_dec64:
return "decfloat(16)";
case dtype_dec128:
return "decfloat(34)";
default:
return "out of range";
}
@ -1252,6 +1337,16 @@ void dsc::getSqlInfo(SLONG* sqlLength, SLONG* sqlSubType, SLONG* sqlScale, SLONG
*sqlType = SQL_BOOLEAN;
break;
case dtype_dec64:
*sqlType = SQL_DEC16;
*sqlScale = 0;
break;
case dtype_dec128:
*sqlType = SQL_DEC34;
*sqlScale = 0;
break;
default:
status_exception::raise(
Arg::Gds(isc_sqlerr) << Arg::Num(-804) <<

View File

@ -31,6 +31,7 @@
#include "consts_pub.h"
#include "../jrd/ods.h"
#include "../intl/charsets.h"
#include "../common/DecFloat.h"
// Data type information
@ -67,9 +68,14 @@ inline bool DTYPE_IS_APPROX(UCHAR d)
return d == dtype_double || d == dtype_real;
}
inline bool DTYPE_IS_DECFLOAT(UCHAR d)
{
return d == dtype_dec128 || d == dtype_dec64;
}
inline bool DTYPE_IS_NUMERIC(UCHAR d)
{
return (d >= dtype_byte && d <= dtype_d_float) || d == dtype_int64;
return (d >= dtype_byte && d <= dtype_d_float) || d == dtype_int64 || DTYPE_IS_DECFLOAT(d);
}
// Descriptor format
@ -155,6 +161,21 @@ typedef struct dsc
return dsc_dtype >= dtype_sql_date && dsc_dtype <= dtype_timestamp;
}
bool isDecFloat() const
{
return DTYPE_IS_DECFLOAT(dsc_dtype);
}
bool isDecOrInt() const
{
return isDecFloat() || isExact();
}
bool isApprox() const
{
return DTYPE_IS_APPROX(dsc_dtype);
}
bool isUnknown() const
{
return dsc_dtype == dtype_unknown;
@ -259,6 +280,22 @@ typedef struct dsc
dsc_address = (UCHAR*) address;
}
void makeDecimal64(Firebird::Decimal64* address = NULL)
{
clear();
dsc_dtype = dtype_dec64;
dsc_length = sizeof(Firebird::Decimal64);
dsc_address = (UCHAR*) address;
}
void makeDecimal128(Firebird::Decimal128* address = NULL)
{
clear();
dsc_dtype = dtype_dec128;
dsc_length = sizeof(Firebird::Decimal128);
dsc_address = (UCHAR*) address;
}
void makeInt64(SCHAR scale, SINT64* address = NULL)
{
clear();

View File

@ -61,7 +61,9 @@
#define dtype_int64 19
#define dtype_dbkey 20
#define dtype_boolean 21
#define DTYPE_TYPE_MAX 22
#define dtype_dec64 22
#define dtype_dec128 23
#define DTYPE_TYPE_MAX 24
#define ISC_TIME_SECONDS_PRECISION 10000
#define ISC_TIME_SECONDS_PRECISION_SCALE (-4)

View File

@ -845,6 +845,16 @@ static const UCHAR* sdl_desc(const UCHAR* ptr, DSC* desc)
desc->dsc_length = sizeof(double);
break;
case blr_dec64:
desc->dsc_dtype = dtype_dec64;
desc->dsc_length = sizeof(Decimal64);
break;
case blr_dec128:
desc->dsc_dtype = dtype_dec128;
desc->dsc_length = sizeof(Decimal128);
break;
case blr_timestamp:
desc->dsc_dtype = dtype_timestamp;
desc->dsc_length = sizeof(ISC_QUAD);

View File

@ -1480,89 +1480,66 @@ void logAndDie(const char* text)
#endif
}
UCHAR sqlTypeToDscType(SSHORT sqlType)
{
switch (sqlType)
{
case SQL_VARYING:
return dtype_varying;
case SQL_TEXT:
return dtype_text;
case SQL_NULL:
return dtype_text;
case SQL_DOUBLE:
return dtype_double;
case SQL_FLOAT:
return dtype_real;
case SQL_D_FLOAT:
return dtype_d_float;
case SQL_TYPE_DATE:
return dtype_sql_date;
case SQL_TYPE_TIME:
return dtype_sql_time;
case SQL_TIMESTAMP:
return dtype_timestamp;
case SQL_BLOB:
return dtype_blob;
case SQL_ARRAY:
return dtype_array;
case SQL_LONG:
return dtype_long;
case SQL_SHORT:
return dtype_short;
case SQL_INT64:
return dtype_int64;
case SQL_QUAD:
return dtype_quad;
case SQL_BOOLEAN:
return dtype_boolean;
case SQL_DEC16:
return dtype_dec64;
case SQL_DEC34:
return dtype_dec128;
default:
return dtype_unknown;
}
}
unsigned sqlTypeToDsc(unsigned runOffset, unsigned sqlType, unsigned sqlLength,
unsigned* dtype, unsigned* len, unsigned* offset, unsigned* nullOffset)
{
sqlType &= ~1;
unsigned dscType;
unsigned dscType = sqlTypeToDscType(sqlType);
switch (sqlType)
if (dscType == dtype_unknown)
{
case SQL_VARYING:
dscType = dtype_varying;
break;
case SQL_TEXT:
dscType = dtype_text;
break;
case SQL_DOUBLE:
dscType = dtype_double;
break;
case SQL_FLOAT:
dscType = dtype_real;
break;
case SQL_D_FLOAT:
dscType = dtype_d_float;
break;
case SQL_TYPE_DATE:
dscType = dtype_sql_date;
break;
case SQL_TYPE_TIME:
dscType = dtype_sql_time;
break;
case SQL_TIMESTAMP:
dscType = dtype_timestamp;
break;
case SQL_BLOB:
dscType = dtype_blob;
break;
case SQL_ARRAY:
dscType = dtype_array;
break;
case SQL_LONG:
dscType = dtype_long;
break;
case SQL_SHORT:
dscType = dtype_short;
break;
case SQL_INT64:
dscType = dtype_int64;
break;
case SQL_QUAD:
dscType = dtype_quad;
break;
case SQL_BOOLEAN:
dscType = dtype_boolean;
break;
case SQL_NULL:
dscType = dtype_text;
break;
default:
fb_assert(false);
// keep old yvalve logic
dscType = sqlType;
break;
}
if (dtype)
{
*dtype = dscType;
}
if (sqlType == SQL_VARYING)
sqlLength += sizeof(USHORT);

View File

@ -184,6 +184,9 @@ namespace fb_utils
void logAndDie(const char* text);
// On incorrect sqlType returns dsc_unknown
UCHAR sqlTypeToDscType(SSHORT sqlType);
// Returns next offset value
unsigned sqlTypeToDsc(unsigned prevOffset, unsigned sqlType, unsigned sqlLength,
unsigned* dtype, unsigned* len, unsigned* offset, unsigned* nullOffset);

View File

@ -30,6 +30,7 @@
#include "../common/xdr_proto.h"
#include "../yvalve/gds_proto.h"
#include "../common/gdsassert.h"
#include "../common/DecFloat.h"
inline UCHAR* XDR_ALLOC(ULONG size)
{
@ -104,7 +105,7 @@ bool_t xdr_hyper( XDR* xdrs, void* pi64)
{
/**************************************
*
* x d r _ h y p e r ( n o n - S O L A R I S )
* x d r _ h y p e r
*
**************************************
*
@ -112,13 +113,6 @@ bool_t xdr_hyper( XDR* xdrs, void* pi64)
* Map a 64-bit Integer from external to internal representation
* (or vice versa).
*
* Enable this for all platforms except Solaris (since it is
* available in the XDR library on Solaris). This function (normally)
* would have been implemented in REMOTE/xdr.c. Since some system
* XDR libraries (HP-UX) do not implement this function, we have it
* in this module. At a later date, when the function is available
* on all platforms, we can start using the system-provided version.
*
* Handles "swapping" of the 2 long's to be "Endian" sensitive.
*
**************************************/
@ -259,6 +253,18 @@ bool_t xdr_datum( XDR* xdrs, const dsc* desc, UCHAR* buffer)
return FALSE;
break;
case dtype_dec64:
fb_assert(desc->dsc_length >= sizeof(Firebird::Decimal64));
if (!xdr_dec64(xdrs, reinterpret_cast<Firebird::Decimal64*>(p)))
return FALSE;
break;
case dtype_dec128:
fb_assert(desc->dsc_length >= sizeof(Firebird::Decimal128));
if (!xdr_dec128(xdrs, reinterpret_cast<Firebird::Decimal128*>(p)))
return FALSE;
break;
case dtype_timestamp:
fb_assert(desc->dsc_length >= 2 * sizeof(SLONG));
if (!xdr_long(xdrs, &((SLONG*) p)[0]))
@ -337,6 +343,25 @@ bool_t xdr_double(XDR* xdrs, double* ip)
}
bool_t xdr_dec64(XDR* xdrs, Firebird::Decimal64* ip)
{
return xdr_hyper(xdrs, ip->getBytes());
}
bool_t xdr_dec128(XDR* xdrs, Firebird::Decimal128* 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)
{
/**************************************

View File

@ -27,12 +27,10 @@
#include "../common/dsc.h"
#include "../common/xdr.h"
// 15 Jan 2003. Nickolay Samofatov
// Functions below need to have C++ linkage to avoid name clash with
// standard XDR. Firebird XDR is NOT compatible with Sun XDR at interface level
bool_t xdr_datum(XDR*, const dsc*, UCHAR*);
bool_t xdr_double(XDR*, double*);
bool_t xdr_dec64(XDR*, Firebird::Decimal64*);
bool_t xdr_dec128(XDR*, Firebird::Decimal128*);
bool_t xdr_enum(XDR*, xdr_op*);
bool_t xdr_float(XDR*, float*);
bool_t xdr_int(XDR*, int*);

View File

@ -281,7 +281,7 @@ bool AggNode::dsqlMatch(const ExprNode* other, bool ignoreMapCast) const
if (!ExprNode::dsqlMatch(other, ignoreMapCast))
return false;
const AggNode* o = other->as<AggNode>();
const AggNode* o = nodeAs<AggNode>(other);
fb_assert(o);
// ASF: We compare name address. That should be ok, as we have only one AggInfo instance
@ -385,7 +385,7 @@ bool AggNode::aggPass(thread_db* tdbb, jrd_req* request) const
to.dsc_sub_type = 0;
to.dsc_scale = 0;
to.dsc_ttype() = ttype_sort_key;
to.dsc_length = asb->keyItems[0].skd_length;
to.dsc_length = asb->keyItems[0].getSkdLength();
to.dsc_address = data;
INTL_string_to_key(tdbb, INTL_TEXT_TO_INDEX(desc->getTextType()),
desc, &to, INTL_KEY_UNIQUE);
@ -393,7 +393,7 @@ bool AggNode::aggPass(thread_db* tdbb, jrd_req* request) const
dsc toDesc = asb->desc;
toDesc.dsc_address = data +
(asb->intl ? asb->keyItems[1].skd_offset : 0);
(asb->intl ? asb->keyItems[1].getSkdOffset() : 0);
MOV_move(tdbb, desc, &toDesc);
// dimitr: Here we add a monotonically increasing value to the sort record.
@ -455,7 +455,7 @@ dsc* AggNode::execute(thread_db* tdbb, jrd_req* request) const
break;
}
desc.dsc_address = data + (asb->intl ? asb->keyItems[1].skd_offset : 0);
desc.dsc_address = data + (asb->intl ? asb->keyItems[1].getSkdOffset() : 0);
aggPass(tdbb, request, &desc);
}
@ -494,7 +494,12 @@ void AvgAggNode::make(DsqlCompilerScratch* dsqlScratch, dsc* desc)
if (desc->isNull())
return;
if (dialect1)
if (DTYPE_IS_DECFLOAT(desc->dsc_dtype))
{
desc->dsc_dtype = dtype_dec128;
desc->dsc_length = sizeof(Decimal128);
}
else if (dialect1)
{
if (!DTYPE_IS_NUMERIC(desc->dsc_dtype) && !DTYPE_IS_TEXT(desc->dsc_dtype))
{
@ -531,6 +536,17 @@ void AvgAggNode::getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc)
{
arg->getDesc(tdbb, csb, desc);
if (DTYPE_IS_DECFLOAT(desc->dsc_dtype))
{
desc->dsc_dtype = dtype_dec128;
desc->dsc_length = sizeof(Decimal128);
desc->dsc_scale = 0;
desc->dsc_sub_type = 0;
desc->dsc_flags = 0;
nodFlags |= FLAG_DECFLOAT;
return;
}
if (dialect1)
{
if (!(DTYPE_IS_NUMERIC(desc->dsc_dtype) || DTYPE_IS_TEXT(desc->dsc_dtype)))
@ -601,7 +617,7 @@ AggNode* AvgAggNode::pass2(thread_db* tdbb, CompilerScratch* csb)
{
AggNode::pass2(tdbb, csb);
if (dialect1)
if (dialect1 && !(nodFlags & FLAG_DECFLOAT))
nodFlags |= FLAG_DOUBLE;
// We need a second descriptor in the impure area for AVG.
@ -659,15 +675,23 @@ dsc* AvgAggNode::aggExecute(thread_db* tdbb, jrd_req* request) const
dsc temp;
SINT64 i;
double d;
Decimal128 dec;
if (!dialect1 && impure->vlu_desc.dsc_dtype == dtype_int64)
{
i = *((SINT64*) impure->vlu_desc.dsc_address) / impure->vlux_count;
temp.makeInt64(impure->vlu_desc.dsc_scale, &i);
}
else if (DTYPE_IS_DECFLOAT(impure->vlu_desc.dsc_dtype))
{
DecimalStatus decSt = tdbb->getAttachment()->att_dec_status;
dec.set(impure->vlux_count, decSt, 0);
dec = MOV_get_dec128(tdbb, &impure->vlu_desc).div(decSt, dec);
temp.makeDecimal128(&dec);
}
else
{
d = MOV_get_double(&impure->vlu_desc) / impure->vlux_count;
d = MOV_get_double(tdbb, &impure->vlu_desc) / impure->vlux_count;
temp.makeDouble(&d);
}
@ -961,7 +985,12 @@ void SumAggNode::make(DsqlCompilerScratch* dsqlScratch, dsc* desc)
if (desc->isNull())
return;
if (dialect1)
if (DTYPE_IS_DECFLOAT(desc->dsc_dtype))
{
desc->dsc_dtype = dtype_dec128;
desc->dsc_length = sizeof(Decimal128);
}
else if (dialect1)
{
if (!DTYPE_IS_NUMERIC(desc->dsc_dtype) && !DTYPE_IS_TEXT(desc->dsc_dtype))
{
@ -1008,6 +1037,16 @@ void SumAggNode::getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc)
{
arg->getDesc(tdbb, csb, desc);
if (DTYPE_IS_DECFLOAT(desc->dsc_dtype))
{
desc->dsc_dtype = dtype_dec128;
desc->dsc_length = sizeof(Decimal128);
desc->dsc_sub_type = 0;
desc->dsc_flags = 0;
nodFlags |= FLAG_DECFLOAT;
return;
}
if (dialect1)
{
switch (desc->dsc_dtype)
@ -1237,7 +1276,7 @@ void MaxMinAggNode::aggPass(thread_db* tdbb, jrd_req* request, dsc* desc) const
return;
}
const int result = MOV_compare(desc, &impure->vlu_desc);
const int result = MOV_compare(tdbb, desc, &impure->vlu_desc);
if ((type == TYPE_MAX && result > 0) || (type == TYPE_MIN && result < 0))
EVL_make_value(tdbb, desc, impure);
@ -1290,13 +1329,32 @@ void StdDevAggNode::parseArgs(thread_db* tdbb, CompilerScratch* csb, unsigned /*
void StdDevAggNode::make(DsqlCompilerScratch* dsqlScratch, dsc* desc)
{
desc->makeDouble();
MAKE_desc(dsqlScratch, desc, arg);
desc->setNullable(true);
if (desc->isNull())
return;
if (DTYPE_IS_DECFLOAT(desc->dsc_dtype))
desc->makeDecimal128();
else
desc->makeDouble();
}
void StdDevAggNode::getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc)
{
desc->makeDouble();
arg->getDesc(tdbb, csb, desc);
if (DTYPE_IS_DECFLOAT(desc->dsc_dtype))
{
desc->makeDecimal128();
nodFlags |= FLAG_DECFLOAT;
}
else
{
desc->makeDouble();
nodFlags |= FLAG_DOUBLE;
}
}
ValueExprNode* StdDevAggNode::copy(thread_db* tdbb, NodeCopier& copier) const
@ -1331,10 +1389,18 @@ void StdDevAggNode::aggInit(thread_db* tdbb, jrd_req* request) const
AggNode::aggInit(tdbb, request);
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
impure->make_double(0);
StdDevImpure* impure2 = request->getImpure<StdDevImpure>(impure2Offset);
impure2->x = impure2->x2 = 0.0;
if (nodFlags & FLAG_DECFLOAT)
{
impure->make_decimal128(CDecimal128(0));
impure2->dec.x = impure2->dec.x2 = CDecimal128(0);
}
else
{
impure->make_double(0);
impure2->dbl.x = impure2->dbl.x2 = 0.0;
}
}
void StdDevAggNode::aggPass(thread_db* tdbb, jrd_req* request, dsc* desc) const
@ -1342,11 +1408,22 @@ void StdDevAggNode::aggPass(thread_db* tdbb, jrd_req* request, dsc* desc) const
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
++impure->vlux_count;
const double d = MOV_get_double(desc);
StdDevImpure* impure2 = request->getImpure<StdDevImpure>(impure2Offset);
impure2->x += d;
impure2->x2 += d * d;
if (nodFlags & FLAG_DECFLOAT)
{
DecimalStatus decSt = tdbb->getAttachment()->att_dec_status;
const Decimal128 d = MOV_get_dec128(tdbb, desc);
impure2->dec.x = impure2->dec.x.add(decSt, d);
impure2->dec.x2 = impure2->dec.x2.fma(decSt, d, d);
}
else
{
const double d = MOV_get_double(tdbb, desc);
impure2->dbl.x += d;
impure2->dbl.x2 += d * d;
}
}
dsc* StdDevAggNode::aggExecute(thread_db* tdbb, jrd_req* request) const
@ -1354,6 +1431,12 @@ dsc* StdDevAggNode::aggExecute(thread_db* tdbb, jrd_req* request) const
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
StdDevImpure* impure2 = request->getImpure<StdDevImpure>(impure2Offset);
double d;
Decimal128 dec;
DecimalStatus decSt = tdbb->getAttachment()->att_dec_status;
Decimal128 cnt;
if (nodFlags & FLAG_DECFLOAT)
cnt.set(impure->vlux_count, decSt, 0);
switch (type)
{
@ -1362,11 +1445,25 @@ dsc* StdDevAggNode::aggExecute(thread_db* tdbb, jrd_req* request) const
if (impure->vlux_count < 2)
return NULL;
d = (impure2->x2 - impure2->x * impure2->x / impure->vlux_count) /
(impure->vlux_count - 1);
if (nodFlags & FLAG_DECFLOAT)
{
Decimal128 cntMinus1;
cntMinus1.set(impure->vlux_count - 1, decSt, 0);
dec = impure2->dec.x.mul(decSt, impure2->dec.x).div(decSt, cnt);
dec = impure2->dec.x2.sub(decSt, dec);
dec = dec.div(decSt, cntMinus1);
if (type == TYPE_STDDEV_SAMP)
d = sqrt(d);
if (type == TYPE_STDDEV_SAMP)
dec = dec.sqrt(decSt);
}
else
{
d = (impure2->dbl.x2 - impure2->dbl.x * impure2->dbl.x / impure->vlux_count) /
(impure->vlux_count - 1);
if (type == TYPE_STDDEV_SAMP)
d = sqrt(d);
}
break;
case TYPE_STDDEV_POP:
@ -1374,18 +1471,33 @@ dsc* StdDevAggNode::aggExecute(thread_db* tdbb, jrd_req* request) const
if (impure->vlux_count == 0)
return NULL;
d = (impure2->x2 - impure2->x * impure2->x / impure->vlux_count) /
impure->vlux_count;
if (nodFlags & FLAG_DECFLOAT)
{
dec = impure2->dec.x.mul(decSt, impure2->dec.x).div(decSt, cnt);
dec = impure2->dec.x2.sub(decSt, dec);
dec = dec.div(decSt, cnt);
if (type == TYPE_STDDEV_POP)
d = sqrt(d);
if (type == TYPE_STDDEV_SAMP)
dec = dec.sqrt(decSt);
}
else
{
d = (impure2->dbl.x2 - impure2->dbl.x * impure2->dbl.x / impure->vlux_count) /
impure->vlux_count;
if (type == TYPE_STDDEV_POP)
d = sqrt(d);
}
break;
}
dsc temp;
temp.makeDouble(&d);
EVL_make_value(tdbb, &temp, impure);
if (nodFlags & FLAG_DECFLOAT)
temp.makeDecimal128(&dec);
else
temp.makeDouble(&d);
EVL_make_value(tdbb, &temp, impure);
return &impure->vlu_desc;
}
@ -1426,13 +1538,32 @@ void CorrAggNode::parseArgs(thread_db* tdbb, CompilerScratch* csb, unsigned /*co
void CorrAggNode::make(DsqlCompilerScratch* dsqlScratch, dsc* desc)
{
desc->makeDouble();
MAKE_desc(dsqlScratch, desc, arg);
desc->setNullable(true);
if (desc->isNull())
return;
if (DTYPE_IS_DECFLOAT(desc->dsc_dtype))
desc->makeDecimal128();
else
desc->makeDouble();
}
void CorrAggNode::getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc)
{
desc->makeDouble();
arg->getDesc(tdbb, csb, desc);
if (DTYPE_IS_DECFLOAT(desc->dsc_dtype))
{
desc->makeDecimal128();
nodFlags |= FLAG_DECFLOAT;
}
else
{
desc->makeDouble();
nodFlags |= FLAG_DOUBLE;
}
}
ValueExprNode* CorrAggNode::copy(thread_db* tdbb, NodeCopier& copier) const
@ -1468,10 +1599,18 @@ void CorrAggNode::aggInit(thread_db* tdbb, jrd_req* request) const
AggNode::aggInit(tdbb, request);
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
impure->make_double(0);
CorrImpure* impure2 = request->getImpure<CorrImpure>(impure2Offset);
impure2->x = impure2->x2 = impure2->y = impure2->y2 = impure2->xy = 0.0;
if (nodFlags & FLAG_DECFLOAT)
{
impure->make_decimal128(CDecimal128(0));
impure2->dec.x = impure2->dec.x2 = impure2->dec.y = impure2->dec.y2 = impure2->dec.xy = CDecimal128(0);
}
else
{
impure->make_double(0);
impure2->dbl.x = impure2->dbl.x2 = impure2->dbl.y = impure2->dbl.y2 = impure2->dbl.xy = 0.0;
}
}
bool CorrAggNode::aggPass(thread_db* tdbb, jrd_req* request) const
@ -1490,16 +1629,30 @@ bool CorrAggNode::aggPass(thread_db* tdbb, jrd_req* request) const
return false;
++impure->vlux_count;
const double y = MOV_get_double(desc);
const double x = MOV_get_double(desc2);
CorrImpure* impure2 = request->getImpure<CorrImpure>(impure2Offset);
impure2->x += x;
impure2->x2 += x * x;
impure2->y += y;
impure2->y2 += y * y;
impure2->xy += x * y;
if (nodFlags & FLAG_DECFLOAT)
{
const Decimal128 y = MOV_get_dec128(tdbb, desc);
const Decimal128 x = MOV_get_dec128(tdbb, desc2);
DecimalStatus decSt = tdbb->getAttachment()->att_dec_status;
impure2->dec.x = impure2->dec.x.add(decSt, x);
impure2->dec.x2 = impure2->dec.x2.fma(decSt, x, x);
impure2->dec.y = impure2->dec.y.add(decSt, y);
impure2->dec.y2 = impure2->dec.y2.fma(decSt, y, y);
impure2->dec.xy = impure2->dec.xy.fma(decSt, x, y);
}
else
{
const double y = MOV_get_double(tdbb, desc);
const double x = MOV_get_double(tdbb, desc2);
impure2->dbl.x += x;
impure2->dbl.x2 += x * x;
impure2->dbl.y += y;
impure2->dbl.y2 += y * y;
impure2->dbl.xy += x * y;
}
return true;
}
@ -1514,19 +1667,43 @@ dsc* CorrAggNode::aggExecute(thread_db* tdbb, jrd_req* request) const
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
CorrImpure* impure2 = request->getImpure<CorrImpure>(impure2Offset);
double d;
Decimal128 dec;
DecimalStatus decSt = tdbb->getAttachment()->att_dec_status;
Decimal128 cnt;
if (nodFlags & FLAG_DECFLOAT)
cnt.set(impure->vlux_count, decSt, 0);
switch (type)
{
case TYPE_COVAR_SAMP:
if (impure->vlux_count < 2)
return NULL;
d = (impure2->xy - impure2->y * impure2->x / impure->vlux_count) / (impure->vlux_count - 1);
if (nodFlags & FLAG_DECFLOAT)
{
Decimal128 cntMinus1;
cntMinus1.set(impure->vlux_count - 1, decSt, 0);
dec = impure2->dec.x.mul(decSt, impure2->dec.y).div(decSt, cnt);
dec = impure2->dec.xy.sub(decSt, dec);
dec = dec.div(decSt, cntMinus1);
}
else
d = (impure2->dbl.xy - impure2->dbl.y * impure2->dbl.x / impure->vlux_count) / (impure->vlux_count - 1);
break;
case TYPE_COVAR_POP:
if (impure->vlux_count == 0)
return NULL;
d = (impure2->xy - impure2->y * impure2->x / impure->vlux_count) / impure->vlux_count;
if (nodFlags & FLAG_DECFLOAT)
{
dec = impure2->dec.x.mul(decSt, impure2->dec.y).div(decSt, cnt);
dec = impure2->dec.xy.sub(decSt, dec);
dec = dec.div(decSt, cnt);
}
else
d = (impure2->dbl.xy - impure2->dbl.y * impure2->dbl.x / impure->vlux_count) / impure->vlux_count;
break;
case TYPE_CORR:
@ -1535,24 +1712,51 @@ dsc* CorrAggNode::aggExecute(thread_db* tdbb, jrd_req* request) const
if (impure->vlux_count == 0)
return NULL;
const double covarPop = (impure2->xy - impure2->y * impure2->x / impure->vlux_count) /
impure->vlux_count;
const double varPopX = (impure2->x2 - impure2->x * impure2->x / impure->vlux_count) /
impure->vlux_count;
const double varPopY = (impure2->y2 - impure2->y * impure2->y / impure->vlux_count) /
impure->vlux_count;
const double divisor = sqrt(varPopX) * sqrt(varPopY);
if (nodFlags & FLAG_DECFLOAT)
{
dec = impure2->dec.x.mul(decSt, impure2->dec.y).div(decSt, cnt);
dec = impure2->dec.xy.sub(decSt, dec);
const Decimal128 covarPop = dec.div(decSt, cnt);
if (divisor == 0.0)
return NULL;
dec = impure2->dec.x.mul(decSt, impure2->dec.x).div(decSt, cnt);
dec = impure2->dec.x2.sub(decSt, dec);
const Decimal128 varPopX = dec.div(decSt, cnt);
d = covarPop / divisor;
dec = impure2->dec.y.mul(decSt, impure2->dec.y).div(decSt, cnt);
dec = impure2->dec.y2.sub(decSt, dec);
const Decimal128 varPopY = dec.div(decSt, cnt);
const Decimal128 divisor = varPopX.sqrt(decSt).mul(decSt, varPopY.sqrt(decSt));
if (divisor.compare(decSt, CDecimal128(0)) == 0)
return NULL;
dec = covarPop.div(decSt, divisor);
}
else
{
const double covarPop = (impure2->dbl.xy - impure2->dbl.y * impure2->dbl.x / impure->vlux_count) /
impure->vlux_count;
const double varPopX = (impure2->dbl.x2 - impure2->dbl.x * impure2->dbl.x / impure->vlux_count) /
impure->vlux_count;
const double varPopY = (impure2->dbl.y2 - impure2->dbl.y * impure2->dbl.y / impure->vlux_count) /
impure->vlux_count;
const double divisor = sqrt(varPopX) * sqrt(varPopY);
if (divisor == 0.0)
return NULL;
d = covarPop / divisor;
}
break;
}
}
dsc temp;
temp.makeDouble(&d);
if (nodFlags & FLAG_DECFLOAT)
temp.makeDecimal128(&dec);
else
temp.makeDouble(&d);
EVL_make_value(tdbb, &temp, impure);
@ -1612,13 +1816,32 @@ void RegrAggNode::parseArgs(thread_db* tdbb, CompilerScratch* csb, unsigned /*co
void RegrAggNode::make(DsqlCompilerScratch* dsqlScratch, dsc* desc)
{
desc->makeDouble();
MAKE_desc(dsqlScratch, desc, arg);
desc->setNullable(true);
if (desc->isNull())
return;
if (DTYPE_IS_DECFLOAT(desc->dsc_dtype))
desc->makeDecimal128();
else
desc->makeDouble();
}
void RegrAggNode::getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc)
{
desc->makeDouble();
arg->getDesc(tdbb, csb, desc);
if (DTYPE_IS_DECFLOAT(desc->dsc_dtype))
{
desc->makeDecimal128();
nodFlags |= FLAG_DECFLOAT;
}
else
{
desc->makeDouble();
nodFlags |= FLAG_DOUBLE;
}
}
ValueExprNode* RegrAggNode::copy(thread_db* tdbb, NodeCopier& copier) const
@ -1654,10 +1877,18 @@ void RegrAggNode::aggInit(thread_db* tdbb, jrd_req* request) const
AggNode::aggInit(tdbb, request);
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
impure->make_double(0);
RegrImpure* impure2 = request->getImpure<RegrImpure>(impure2Offset);
impure2->x = impure2->x2 = impure2->y = impure2->y2 = impure2->xy = 0.0;
if (nodFlags & FLAG_DECFLOAT)
{
impure->make_decimal128(CDecimal128(0));
impure2->dec.x = impure2->dec.x2 = impure2->dec.y = impure2->dec.y2 = impure2->dec.xy = CDecimal128(0);
}
else
{
impure->make_double(0);
impure2->dbl.x = impure2->dbl.x2 = impure2->dbl.y = impure2->dbl.y2 = impure2->dbl.xy = 0.0;
}
}
bool RegrAggNode::aggPass(thread_db* tdbb, jrd_req* request) const
@ -1676,16 +1907,31 @@ bool RegrAggNode::aggPass(thread_db* tdbb, jrd_req* request) const
return false;
++impure->vlux_count;
const double y = MOV_get_double(desc);
const double x = MOV_get_double(desc2);
RegrImpure* impure2 = request->getImpure<RegrImpure>(impure2Offset);
impure2->x += x;
impure2->x2 += x * x;
impure2->y += y;
impure2->y2 += y * y;
impure2->xy += x * y;
if (nodFlags & FLAG_DECFLOAT)
{
const Decimal128 y = MOV_get_dec128(tdbb, desc);
const Decimal128 x = MOV_get_dec128(tdbb, desc2);
DecimalStatus decSt = tdbb->getAttachment()->att_dec_status;
impure2->dec.x = impure2->dec.x.add(decSt, x);
impure2->dec.x2 = impure2->dec.x2.fma(decSt, x, x);
impure2->dec.y = impure2->dec.y.add(decSt, y);
impure2->dec.y2 = impure2->dec.y2.fma(decSt, y, y);
impure2->dec.xy = impure2->dec.xy.fma(decSt, x, y);
}
else
{
const double y = MOV_get_double(tdbb, desc);
const double x = MOV_get_double(tdbb, desc2);
impure2->dbl.x += x;
impure2->dbl.x2 += x * x;
impure2->dbl.y += y;
impure2->dbl.y2 += y * y;
impure2->dbl.xy += x * y;
}
return true;
}
@ -1699,74 +1945,148 @@ dsc* RegrAggNode::aggExecute(thread_db* tdbb, jrd_req* request) const
{
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
RegrImpure* impure2 = request->getImpure<RegrImpure>(impure2Offset);
dsc temp;
if (impure->vlux_count == 0)
return NULL;
const double varPopX = (impure2->x2 - impure2->x * impure2->x / impure->vlux_count) / impure->vlux_count;
const double varPopY = (impure2->y2 - impure2->y * impure2->y / impure->vlux_count) / impure->vlux_count;
const double covarPop = (impure2->xy - impure2->y * impure2->x / impure->vlux_count) / impure->vlux_count;
const double avgX = impure2->x / impure->vlux_count;
const double avgY = impure2->y / impure->vlux_count;
const double slope = covarPop / varPopX;
const double sq = sqrt(varPopX) * sqrt(varPopY);
const double corr = covarPop / sq;
double d;
switch (type)
if (nodFlags & FLAG_DECFLOAT)
{
case TYPE_REGR_AVGX:
d = avgX;
break;
DecimalStatus decSt = tdbb->getAttachment()->att_dec_status;
Decimal128 cnt;
cnt.set(impure->vlux_count, decSt, 0);
DecimalStatus safeDivide = decSt;
safeDivide.decExtFlag &= ~DEC_Division_by_zero;
case TYPE_REGR_AVGY:
d = avgY;
break;
const Decimal128 sxx = impure2->dec.x2.sub(decSt, impure2->dec.x.mul(decSt, impure2->dec.x).div(decSt, cnt));
const Decimal128 syy = impure2->dec.y2.sub(decSt, impure2->dec.y.mul(decSt, impure2->dec.y).div(decSt, cnt));
const Decimal128 sxy = impure2->dec.xy.sub(decSt, impure2->dec.x.mul(decSt, impure2->dec.y).div(decSt, cnt));
const Decimal128 varPopX = sxx.div(decSt, cnt);
const Decimal128 varPopY = syy.div(decSt, cnt);
const Decimal128 covarPop = sxy.div(decSt, cnt);
const Decimal128 avgX = impure2->dec.x.div(decSt, cnt);
const Decimal128 avgY = impure2->dec.y.div(decSt, cnt);
const Decimal128 slope = covarPop.div(safeDivide, varPopX);
const Decimal128 sq = varPopX.sqrt(decSt).mul(decSt, varPopY.sqrt(decSt));
const Decimal128 corr = covarPop.div(safeDivide, sq);
case TYPE_REGR_INTERCEPT:
if (varPopX == 0.0)
return NULL;
else
d = avgY - slope * avgX;
break;
Decimal128 d;
case TYPE_REGR_R2:
if (varPopX == 0.0)
return NULL;
else if (varPopY == 0.0)
d = 1.0;
else if (sq == 0.0)
return NULL;
else
d = corr * corr;
break;
switch (type)
{
case TYPE_REGR_AVGX:
d = avgX;
break;
case TYPE_REGR_SLOPE:
if (varPopX == 0.0)
return NULL;
else
d = covarPop / varPopX;
break;
case TYPE_REGR_AVGY:
d = avgY;
break;
case TYPE_REGR_SXX:
d = impure->vlux_count * varPopX;
break;
case TYPE_REGR_INTERCEPT:
if (varPopX.compare(decSt, CDecimal128(0)) == 0)
return NULL;
else
d = avgY.sub(decSt, slope.mul(decSt, avgX));
break;
case TYPE_REGR_SXY:
d = impure->vlux_count * covarPop;
break;
case TYPE_REGR_R2:
if (varPopX.compare(decSt, CDecimal128(0)) == 0)
return NULL;
else if (varPopY.compare(decSt, CDecimal128(0)) == 0)
d.set(1, decSt, 0);
else if (sq.compare(decSt, CDecimal128(0)) == 0)
return NULL;
else
d = corr.mul(decSt, corr);
break;
case TYPE_REGR_SYY:
d = impure->vlux_count * varPopY;
break;
case TYPE_REGR_SLOPE:
if (varPopX.compare(decSt, CDecimal128(0)) == 0)
return NULL;
else
d = slope;
break;
case TYPE_REGR_SXX:
d = sxx;
break;
case TYPE_REGR_SXY:
d = sxy;
break;
case TYPE_REGR_SYY:
d = syy;
break;
}
temp.makeDecimal128(&d);
}
else
{
const double varPopX = (impure2->dbl.x2 - impure2->dbl.x * impure2->dbl.x / impure->vlux_count) / impure->vlux_count;
const double varPopY = (impure2->dbl.y2 - impure2->dbl.y * impure2->dbl.y / impure->vlux_count) / impure->vlux_count;
const double covarPop = (impure2->dbl.xy - impure2->dbl.y * impure2->dbl.x / impure->vlux_count) / impure->vlux_count;
const double avgX = impure2->dbl.x / impure->vlux_count;
const double avgY = impure2->dbl.y / impure->vlux_count;
const double slope = covarPop / varPopX;
const double sq = sqrt(varPopX) * sqrt(varPopY);
const double corr = covarPop / sq;
double d;
switch (type)
{
case TYPE_REGR_AVGX:
d = avgX;
break;
case TYPE_REGR_AVGY:
d = avgY;
break;
case TYPE_REGR_INTERCEPT:
if (varPopX == 0.0)
return NULL;
else
d = avgY - slope * avgX;
break;
case TYPE_REGR_R2:
if (varPopX == 0.0)
return NULL;
else if (varPopY == 0.0)
d = 1.0;
else if (sq == 0.0)
return NULL;
else
d = corr * corr;
break;
case TYPE_REGR_SLOPE:
if (varPopX == 0.0)
return NULL;
else
d = covarPop / varPopX;
break;
case TYPE_REGR_SXX:
d = impure->vlux_count * varPopX;
break;
case TYPE_REGR_SXY:
d = impure->vlux_count * covarPop;
break;
case TYPE_REGR_SYY:
d = impure->vlux_count * varPopY;
break;
}
temp.makeDouble(&d);
}
dsc temp;
temp.makeDouble(&d);
EVL_make_value(tdbb, &temp, impure);
return &impure->vlu_desc;
}

View File

@ -186,9 +186,16 @@ public:
TYPE_VAR_POP
};
struct StdDevImpure
union StdDevImpure
{
double x, x2;
struct
{
double x, x2;
} dbl;
struct
{
Firebird::Decimal128 x, x2;
} dec;
};
explicit StdDevAggNode(MemoryPool& pool, StdDevType aType, ValueExprNode* aArg = NULL);
@ -230,9 +237,16 @@ public:
TYPE_CORR
};
struct CorrImpure
union CorrImpure
{
double x, x2, y, y2, xy;
struct
{
double x, x2, y, y2, xy;
} dbl;
struct
{
Firebird::Decimal128 x, x2, y, y2, xy;
} dec;
};
explicit CorrAggNode(MemoryPool& pool, CorrType aType,
@ -282,9 +296,16 @@ public:
TYPE_REGR_SYY
};
struct RegrImpure
union RegrImpure
{
double x, x2, y, y2, xy;
struct
{
double x, x2, y, y2, xy;
} dbl;
struct
{
Firebird::Decimal128 x, x2, y, y2, xy;
} dec;
};
explicit RegrAggNode(MemoryPool& pool, RegrType aType,

View File

@ -73,7 +73,7 @@ BoolExprNode* BoolExprNode::pass2(thread_db* tdbb, CompilerScratch* csb)
if (csb->csb_current_nodes.hasData())
{
RseNode* topRseNode = csb->csb_current_nodes[0]->as<RseNode>();
RseNode* topRseNode = nodeAs<RseNode>(csb->csb_current_nodes[0]);
fb_assert(topRseNode);
if (!topRseNode->rse_invariants)
@ -144,7 +144,7 @@ bool BinaryBoolNode::dsqlMatch(const ExprNode* other, bool ignoreMapCast) const
if (!BoolExprNode::dsqlMatch(other, ignoreMapCast))
return false;
const BinaryBoolNode* o = other->as<BinaryBoolNode>();
const BinaryBoolNode* o = nodeAs<BinaryBoolNode>(other);
fb_assert(o);
return blrOp == o->blrOp;
@ -152,7 +152,7 @@ bool BinaryBoolNode::dsqlMatch(const ExprNode* other, bool ignoreMapCast) const
bool BinaryBoolNode::sameAs(const ExprNode* other, bool ignoreStreams) const
{
const BinaryBoolNode* const otherNode = other->as<BinaryBoolNode>();
const BinaryBoolNode* const otherNode = nodeAs<BinaryBoolNode>(other);
if (!otherNode || blrOp != otherNode->blrOp)
return false;
@ -366,7 +366,7 @@ BoolExprNode* ComparativeBoolNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
if (dsqlSpecialArg)
{
ValueListNode* listNode = dsqlSpecialArg->as<ValueListNode>();
ValueListNode* listNode = nodeAs<ValueListNode>(dsqlSpecialArg);
if (listNode)
{
int listItemCount = 0;
@ -392,7 +392,7 @@ BoolExprNode* ComparativeBoolNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
return resultNode->dsqlPass(dsqlScratch);
}
SelectExprNode* selNode = dsqlSpecialArg->as<SelectExprNode>();
SelectExprNode* selNode = nodeAs<SelectExprNode>(dsqlSpecialArg);
if (selNode)
{
fb_assert(!(selNode->dsqlFlags & RecordSourceNode::DFLAG_SINGLETON));
@ -495,7 +495,7 @@ bool ComparativeBoolNode::dsqlMatch(const ExprNode* other, bool ignoreMapCast) c
if (!BoolExprNode::dsqlMatch(other, ignoreMapCast))
return false;
const ComparativeBoolNode* o = other->as<ComparativeBoolNode>();
const ComparativeBoolNode* o = nodeAs<ComparativeBoolNode>(other);
fb_assert(o);
return dsqlFlag == o->dsqlFlag && blrOp == o->blrOp;
@ -503,7 +503,7 @@ bool ComparativeBoolNode::dsqlMatch(const ExprNode* other, bool ignoreMapCast) c
bool ComparativeBoolNode::sameAs(const ExprNode* other, bool ignoreStreams) const
{
const ComparativeBoolNode* const otherNode = other->as<ComparativeBoolNode>();
const ComparativeBoolNode* const otherNode = nodeAs<ComparativeBoolNode>(other);
if (!otherNode || blrOp != otherNode->blrOp)
return false;
@ -582,7 +582,7 @@ BoolExprNode* ComparativeBoolNode::pass1(thread_db* tdbb, CompilerScratch* csb)
// If there is no top-level RSE present and patterns are not constant, unmark node as invariant
// because it may be dependent on data or variables.
if ((nodFlags & FLAG_INVARIANT) &&
(!arg2->is<LiteralNode>() || (arg3 && !arg3->is<LiteralNode>())))
(!nodeIs<LiteralNode>(arg2) || (arg3 && !nodeIs<LiteralNode>(arg3))))
{
ExprNode* const* ctx_node;
ExprNode* const* end;
@ -590,7 +590,7 @@ BoolExprNode* ComparativeBoolNode::pass1(thread_db* tdbb, CompilerScratch* csb)
for (ctx_node = csb->csb_current_nodes.begin(), end = csb->csb_current_nodes.end();
ctx_node != end; ++ctx_node)
{
if ((*ctx_node)->as<RseNode>())
if (nodeAs<RseNode>(*ctx_node))
break;
}
@ -614,7 +614,7 @@ void ComparativeBoolNode::pass2Boolean2(thread_db* tdbb, CompilerScratch* csb)
if (arg3)
{
if ((keyNode = arg3->as<RecordKeyNode>()) && keyNode->aggregate)
if ((keyNode = nodeAs<RecordKeyNode>(arg3)) && keyNode->aggregate)
ERR_post(Arg::Gds(isc_bad_dbkey));
dsc descriptor_c;
@ -627,8 +627,8 @@ void ComparativeBoolNode::pass2Boolean2(thread_db* tdbb, CompilerScratch* csb)
}
}
if (((keyNode = arg1->as<RecordKeyNode>()) && keyNode->aggregate) ||
((keyNode = arg2->as<RecordKeyNode>()) && keyNode->aggregate))
if (((keyNode = nodeAs<RecordKeyNode>(arg1)) && keyNode->aggregate) ||
((keyNode = nodeAs<RecordKeyNode>(arg2)) && keyNode->aggregate))
{
ERR_post(Arg::Gds(isc_bad_dbkey));
}
@ -768,13 +768,13 @@ bool ComparativeBoolNode::execute(thread_db* tdbb, jrd_req* request) const
case blr_leq:
case blr_neq:
case blr_between:
comparison = MOV_compare(desc[0], desc[1]);
comparison = MOV_compare(tdbb, desc[0], desc[1]);
}
// If we are checking equality of record_version
// and same transaction updated the record, force equality.
const RecordKeyNode* recVersionNode = arg1->as<RecordKeyNode>();
const RecordKeyNode* recVersionNode = nodeAs<RecordKeyNode>(arg1);
if (recVersionNode && recVersionNode->blrOp == blr_record_version && force_equal)
comparison = 0;
@ -806,7 +806,7 @@ bool ComparativeBoolNode::execute(thread_db* tdbb, jrd_req* request) const
desc[1] = EVL_expr(tdbb, request, arg3);
if (request->req_flags & req_null)
return false;
return comparison >= 0 && MOV_compare(desc[0], desc[1]) <= 0;
return comparison >= 0 && MOV_compare(tdbb, desc[0], desc[1]) <= 0;
case blr_containing:
case blr_starting:
@ -849,7 +849,7 @@ bool ComparativeBoolNode::stringBoolean(thread_db* tdbb, jrd_req* request, dsc*
VaryStr<256> temp1;
USHORT xtype1;
const USHORT l1 = MOV_get_string_ptr(desc1, &xtype1, &p1, &temp1, sizeof(temp1));
const USHORT l1 = MOV_get_string_ptr(tdbb, desc1, &xtype1, &p1, &temp1, sizeof(temp1));
fb_assert(xtype1 == type1);
@ -915,7 +915,7 @@ bool ComparativeBoolNode::stringBoolean(thread_db* tdbb, jrd_req* request, dsc*
break;
}
escape_length = MOV_make_string(desc, type1,
escape_length = MOV_make_string(tdbb, desc, type1,
reinterpret_cast<const char**>(&escape_str), &temp3, sizeof(temp3));
if (!escape_length || charset->length(escape_length, escape_str, true) != 1)
@ -1124,7 +1124,7 @@ bool ComparativeBoolNode::stringFunction(thread_db* tdbb, jrd_req* request,
return false;
}
escape_length = MOV_make_string(desc, ttype,
escape_length = MOV_make_string(tdbb, desc, ttype,
reinterpret_cast<const char**>(&escape_str), &temp3, sizeof(temp3));
if (!escape_length || charset->length(escape_length, escape_str, true) != 1)
@ -1375,7 +1375,7 @@ BoolExprNode* MissingBoolNode::pass1(thread_db* tdbb, CompilerScratch* csb)
void MissingBoolNode::pass2Boolean2(thread_db* tdbb, CompilerScratch* csb)
{
RecordKeyNode* keyNode = arg->as<RecordKeyNode>();
RecordKeyNode* keyNode = nodeAs<RecordKeyNode>(arg);
if (keyNode && keyNode->aggregate)
ERR_post(Arg::Gds(isc_bad_dbkey));
@ -1448,7 +1448,7 @@ BoolExprNode* NotBoolNode::copy(thread_db* tdbb, NodeCopier& copier) const
BoolExprNode* NotBoolNode::pass1(thread_db* tdbb, CompilerScratch* csb)
{
RseBoolNode* rseBoolean = arg->as<RseBoolNode>();
RseBoolNode* rseBoolean = nodeAs<RseBoolNode>(arg);
if (rseBoolean)
{
@ -1475,7 +1475,7 @@ bool NotBoolNode::execute(thread_db* tdbb, jrd_req* request) const
// Get rid of redundant nested NOT predicates.
BoolExprNode* NotBoolNode::process(DsqlCompilerScratch* dsqlScratch, bool invert)
{
NotBoolNode* notArg = arg->as<NotBoolNode>();
NotBoolNode* notArg = nodeAs<NotBoolNode>(arg);
if (notArg)
{
@ -1486,12 +1486,12 @@ BoolExprNode* NotBoolNode::process(DsqlCompilerScratch* dsqlScratch, bool invert
if (!invert)
return arg->dsqlPass(dsqlScratch);
ComparativeBoolNode* cmpArg = arg->as<ComparativeBoolNode>();
BinaryBoolNode* binArg = arg->as<BinaryBoolNode>();
ComparativeBoolNode* cmpArg = nodeAs<ComparativeBoolNode>(arg);
BinaryBoolNode* binArg = nodeAs<BinaryBoolNode>(arg);
// Do not handle special case: <value> NOT IN <list>
if (cmpArg && (!cmpArg->dsqlSpecialArg || !cmpArg->dsqlSpecialArg->is<ValueListNode>()))
if (cmpArg && (!cmpArg->dsqlSpecialArg || !nodeIs<ValueListNode>(cmpArg->dsqlSpecialArg)))
{
// Invert the given boolean.
switch (cmpArg->blrOp)
@ -1646,7 +1646,7 @@ BoolExprNode* RseBoolNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
const DsqlContextStack::iterator base(*dsqlScratch->context);
RseBoolNode* node = FB_NEW_POOL(getPool()) RseBoolNode(getPool(), blrOp,
PASS1_rse(dsqlScratch, dsqlRse->as<SelectExprNode>(), false));
PASS1_rse(dsqlScratch, nodeAs<SelectExprNode>(dsqlRse), false));
// Finish off by cleaning up contexts
dsqlScratch->context->clear(base);
@ -1657,7 +1657,7 @@ BoolExprNode* RseBoolNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
void RseBoolNode::genBlr(DsqlCompilerScratch* dsqlScratch)
{
dsqlScratch->appendUChar(blrOp);
GEN_rse(dsqlScratch, dsqlRse->as<RseNode>());
GEN_rse(dsqlScratch, nodeAs<RseNode>(dsqlRse));
}
bool RseBoolNode::dsqlMatch(const ExprNode* other, bool ignoreMapCast) const
@ -1665,7 +1665,7 @@ bool RseBoolNode::dsqlMatch(const ExprNode* other, bool ignoreMapCast) const
if (!BoolExprNode::dsqlMatch(other, ignoreMapCast))
return false;
const RseBoolNode* o = other->as<RseBoolNode>();
const RseBoolNode* o = nodeAs<RseBoolNode>(other);
fb_assert(o);
return blrOp == o->blrOp;
@ -1676,7 +1676,7 @@ bool RseBoolNode::sameAs(const ExprNode* other, bool ignoreStreams) const
if (!BoolExprNode::sameAs(other, ignoreStreams))
return false;
const RseBoolNode* const otherNode = other->as<RseBoolNode>();
const RseBoolNode* const otherNode = nodeAs<RseBoolNode>(other);
fb_assert(otherNode);
return blrOp == otherNode->blrOp;
@ -1730,7 +1730,7 @@ BoolExprNode* RseBoolNode::pass1(thread_db* tdbb, CompilerScratch* csb)
BoolExprNode* boolean = rse->rse_boolean;
if (boolean)
{
BinaryBoolNode* const binaryNode = boolean->as<BinaryBoolNode>();
BinaryBoolNode* const binaryNode = nodeAs<BinaryBoolNode>(boolean);
if (binaryNode && binaryNode->blrOp == blr_and)
boolean = binaryNode->arg2;
@ -1856,7 +1856,7 @@ BoolExprNode* RseBoolNode::convertNeqAllToNotAny(thread_db* tdbb, CompilerScratc
if (!outerRse || outerRse->type != RseNode::TYPE || outerRse->rse_relations.getCount() != 1 ||
!outerRse->rse_boolean ||
!(outerRseNeq = outerRse->rse_boolean->as<ComparativeBoolNode>()) ||
!(outerRseNeq = nodeAs<ComparativeBoolNode>(outerRse->rse_boolean)) ||
outerRseNeq->blrOp != blr_neq)
{
return NULL;

View File

@ -393,26 +393,8 @@ void defineComputed(DsqlCompilerScratch* dsqlScratch, RelationSourceNode* relati
field->subType = desc.dsc_sub_type;
}
if (field && field->precision == 0 && field->scale != 0)
{
switch (field->dtype)
{
case dtype_short:
field->precision = 4;
break;
case dtype_long:
field->precision = 9;
break;
case dtype_int64:
field->precision = 18;
break;
default:
fb_assert(!DTYPE_IS_EXACT(field->dtype));
}
}
if (field)
field->setExactPrecision();
dsqlScratch->resetContextStack();
@ -1043,9 +1025,9 @@ void DdlNode::storeGlobalField(thread_db* tdbb, jrd_tra* transaction, MetaName&
++ptr, ++position)
{
const ValueExprNode* element = *ptr++;
const SLONG lrange = element->as<LiteralNode>()->getSlong();
const SLONG lrange = nodeAs<LiteralNode>(element)->getSlong();
element = *ptr;
const SLONG hrange = element->as<LiteralNode>()->getSlong();
const SLONG hrange = nodeAs<LiteralNode>(element)->getSlong();
if (lrange >= hrange)
{
@ -1565,7 +1547,7 @@ DdlNode* CreateAlterFunctionNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
const NestConst<StmtNode>* ptr = variables->statements.begin();
for (const NestConst<StmtNode>* const end = variables->statements.end(); ptr != end; ++ptr)
{
const DeclareVariableNode* varNode = (*ptr)->as<DeclareVariableNode>();
const DeclareVariableNode* varNode = nodeAs<DeclareVariableNode>(*ptr);
if (varNode)
{
@ -2011,9 +1993,11 @@ void CreateAlterFunctionNode::storeArgument(thread_db* tdbb, DsqlCompilerScratch
ARG.RDB$MECHANISM.NULL = TRUE;
ARG.RDB$FIELD_TYPE.NULL = TRUE;
ARG.RDB$FIELD_LENGTH.NULL = TRUE;
ARG.RDB$FIELD_SUB_TYPE.NULL = TRUE;
ARG.RDB$FIELD_PRECISION.NULL = TRUE;
ARG.RDB$FIELD_SCALE.NULL = TRUE;
ARG.RDB$CHARACTER_SET_ID.NULL = TRUE;
ARG.RDB$CHARACTER_LENGTH.NULL = TRUE;
ARG.RDB$COLLATION_ID.NULL = TRUE;
ARG.RDB$ARGUMENT_MECHANISM.NULL = TRUE;
@ -2569,7 +2553,7 @@ DdlNode* CreateAlterProcedureNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
const NestConst<StmtNode>* ptr = variables->statements.begin();
for (const NestConst<StmtNode>* const end = variables->statements.end(); ptr != end; ++ptr)
{
const DeclareVariableNode* varNode = (*ptr)->as<DeclareVariableNode>();
const DeclareVariableNode* varNode = nodeAs<DeclareVariableNode>(*ptr);
if (varNode)
{
@ -3878,6 +3862,7 @@ void CreateCollationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
{
if (MET_get_char_coll_subtype_info(tdbb,
INTL_CS_COLL_TO_TTYPE(forCharSetId, fromCollationId), &info) &&
forCharSetId != CS_METADATA &&
info.specificAttributes.hasData())
{
UCharBuffer temp;
@ -4475,6 +4460,8 @@ void AlterDomainNode::checkUpdate(const dyn_fld& origFld, const dyn_fld& newFld)
case blr_d_float:
case blr_double:
case blr_float:
case blr_dec64:
case blr_dec128:
switch (newFld.dyn_dtype)
{
case blr_blob:
@ -4571,6 +4558,44 @@ void AlterDomainNode::checkUpdate(const dyn_fld& origFld, const dyn_fld& newFld)
}
break;
case blr_dec64:
switch (origFld.dyn_dtype)
{
case blr_short:
case blr_long:
case blr_float:
case blr_d_float:
case blr_double:
case blr_dec64:
break;
default:
// Cannot change datatype for column %s. Conversion from base type %s to base type %s is not supported.
errorCode = isc_dyn_invalid_dtype_conversion;
break;
}
break;
case blr_dec128:
switch (origFld.dyn_dtype)
{
case blr_short:
case blr_long:
case blr_int64:
case blr_float:
case blr_d_float:
case blr_double:
case blr_dec64:
case blr_dec128:
break;
default:
// Cannot change datatype for column %s. Conversion from base type %s to base type %s is not supported.
errorCode = isc_dyn_invalid_dtype_conversion;
break;
}
break;
// If the original field is a numeric field and the new field is a character field,
// is there enough space in the new field?
case blr_text:
@ -6365,7 +6390,7 @@ bool RelationNode::defineDefault(thread_db* /*tdbb*/, DsqlCompilerScratch* dsqlS
value.assign(dsqlScratch->getBlrData());
return ExprNode::is<NullNode>(input);
return nodeIs<NullNode>(input);
}
// Make a constraint object from a legacy node.
@ -8641,22 +8666,21 @@ void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
ValueExprNode* nameNode = fieldNode;
const char* aliasName = NULL;
while (nameNode->is<DsqlAliasNode>() || nameNode->is<DerivedFieldNode>() ||
nameNode->is<DsqlMapNode>())
while (nodeIs<DsqlAliasNode>(nameNode) || nodeIs<DerivedFieldNode>(nameNode) || nodeIs<DsqlMapNode>(nameNode))
{
DsqlAliasNode* aliasNode;
DsqlMapNode* mapNode;
DerivedFieldNode* derivedField;
if ((aliasNode = nameNode->as<DsqlAliasNode>()))
if ((aliasNode = nodeAs<DsqlAliasNode>(nameNode)))
{
if (!aliasName)
aliasName = aliasNode->name.c_str();
nameNode = aliasNode->value;
}
else if ((mapNode = nameNode->as<DsqlMapNode>()))
else if ((mapNode = nodeAs<DsqlMapNode>(nameNode)))
nameNode = mapNode->map->map_node;
else if ((derivedField = nameNode->as<DerivedFieldNode>()))
else if ((derivedField = nodeAs<DerivedFieldNode>(nameNode)))
{
if (!aliasName)
aliasName = derivedField->name.c_str();
@ -8665,7 +8689,7 @@ void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
}
const dsql_fld* nameField = NULL;
const FieldNode* fieldNameNode = nameNode->as<FieldNode>();
const FieldNode* fieldNameNode = nodeAs<FieldNode>(nameNode);
if (fieldNameNode)
nameField = fieldNameNode->dsqlField;
@ -8679,7 +8703,7 @@ void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
// Check if this is a field or an expression.
DsqlAliasNode* aliasNode = fieldNode->as<DsqlAliasNode>();
DsqlAliasNode* aliasNode = nodeAs<DsqlAliasNode>(fieldNode);
if (aliasNode)
fieldNode = aliasNode->value;
@ -8687,7 +8711,7 @@ void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
dsql_fld* field = NULL;
const dsql_ctx* context = NULL;
fieldNameNode = fieldNode->as<FieldNode>();
fieldNameNode = nodeAs<FieldNode>(fieldNode);
if (fieldNameNode)
{
@ -8714,7 +8738,7 @@ void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
if (ptr)
{
if (ptr < end)
fieldStr = (*ptr)->as<FieldNode>()->dsqlName.c_str();
fieldStr = nodeAs<FieldNode>(*ptr)->dsqlName.c_str();
else
{
// Generate an error when going out of this loop.
@ -8830,6 +8854,8 @@ void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
else
newField.subType = desc.dsc_sub_type;
newField.setExactPrecision();
if (relField) // modifying a view
{
AutoRequest request2;
@ -8925,11 +8951,11 @@ void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
Arg::Gds(isc_col_name_err));
}
RseNode* querySpec = selectExpr->querySpec->as<RseNode>();
RseNode* querySpec = nodeAs<RseNode>(selectExpr->querySpec);
fb_assert(querySpec);
if (querySpec->dsqlFrom->items.getCount() != 1 ||
!querySpec->dsqlFrom->items[0]->is<ProcedureSourceNode>())
!nodeIs<ProcedureSourceNode>(querySpec->dsqlFrom->items[0]))
{
// Only one table allowed for VIEW WITH CHECK OPTION
status_exception::raise(
@ -8997,10 +9023,10 @@ void CreateAlterViewNode::createCheckTrigger(thread_db* tdbb, DsqlCompilerScratc
dsqlScratch->resetContextStack();
RseNode* querySpec = selectExpr->querySpec->as<RseNode>();
RseNode* querySpec = nodeAs<RseNode>(selectExpr->querySpec);
fb_assert(querySpec);
ProcedureSourceNode* sourceNode = querySpec->dsqlFrom->items[0]->as<ProcedureSourceNode>();
ProcedureSourceNode* sourceNode = nodeAs<ProcedureSourceNode>(querySpec->dsqlFrom->items[0]);
if (triggerType == PRE_MODIFY_TRIGGER)
{
@ -9069,14 +9095,14 @@ void CreateAlterViewNode::createCheckTrigger(thread_db* tdbb, DsqlCompilerScratc
NestConst<ValueExprNode> valueNod = *ptr2;
DsqlAliasNode* aliasNode;
if ((aliasNode = fieldNod->as<DsqlAliasNode>()))
if ((aliasNode = nodeAs<DsqlAliasNode>(fieldNod)))
fieldNod = aliasNode->value;
if ((aliasNode = valueNod->as<DsqlAliasNode>()))
if ((aliasNode = nodeAs<DsqlAliasNode>(valueNod)))
valueNod = aliasNode->value;
FieldNode* fieldNode = fieldNod->as<FieldNode>();
FieldNode* valueNode = valueNod->as<FieldNode>();
FieldNode* fieldNode = nodeAs<FieldNode>(fieldNod);
FieldNode* valueNode = nodeAs<FieldNode>(valueNod);
// Generate the actual comparisons.
@ -9135,10 +9161,10 @@ void CreateAlterViewNode::createCheckTrigger(thread_db* tdbb, DsqlCompilerScratc
ValueExprNode* valueNode = *ptr;
DsqlAliasNode* aliasNode;
if ((aliasNode = valueNode->as<DsqlAliasNode>()))
if ((aliasNode = nodeAs<DsqlAliasNode>(valueNode)))
valueNode = aliasNode->value;
FieldNode* fieldNode = valueNode->as<FieldNode>();
FieldNode* fieldNode = nodeAs<FieldNode>(valueNode);
fb_assert(fieldNode);
savedNames.add(field->fld_name);
@ -9577,7 +9603,7 @@ void CreateIndexNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
for (; ptr != end; ++ptr)
{
MetaName& column = definition.columns.add();
column = (*ptr)->as<FieldNode>()->dsqlName;
column = nodeAs<FieldNode>(*ptr)->dsqlName;
}
}
else if (computed)
@ -10613,7 +10639,7 @@ void MappingNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd
if (ddlTriggerAction > 0)
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, ddlTriggerAction, name, NULL);
DFW_post_work(transaction, dfw_clear_cache, NULL, MAPPING_CACHE);
DFW_post_work(transaction, dfw_clear_cache, NULL, Mapping::MAPPING_CACHE);
savePoint.release(); // everything is ok
}
@ -11005,7 +11031,7 @@ void GrantRevokeNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
}
// Invalidate system privileges cache
DFW_post_work(transaction, dfw_clear_cache, NULL, SYSTEM_PRIVILEGES_CACHE);
DFW_post_work(transaction, dfw_clear_cache, NULL, Mapping::SYSTEM_PRIVILEGES_CACHE);
}
}
@ -11123,7 +11149,7 @@ void GrantRevokeNode::modifyPrivileges(thread_db* tdbb, jrd_tra* transaction, SS
for (NestConst<ValueExprNode>* ptr = fields->items.begin(); ptr != fields->items.end(); ++ptr)
{
grantRevoke(tdbb, transaction, object, user, privs0,
(*ptr)->as<FieldNode>()->dsqlName, option);
nodeAs<FieldNode>(*ptr)->dsqlName, option);
}
}
else

View File

@ -278,7 +278,7 @@ void DsqlCompilerScratch::putLocalVariables(CompoundStmtNode* parameters, USHORT
DeclareVariableNode* varNode;
if ((varNode = parameter->as<DeclareVariableNode>()))
if ((varNode = nodeAs<DeclareVariableNode>(parameter)))
{
dsql_fld* field = varNode->dsqlDef->type;
const NestConst<StmtNode>* rest = ptr;
@ -287,7 +287,7 @@ void DsqlCompilerScratch::putLocalVariables(CompoundStmtNode* parameters, USHORT
{
const DeclareVariableNode* varNode2;
if ((varNode2 = (*rest)->as<DeclareVariableNode>()))
if ((varNode2 = nodeAs<DeclareVariableNode>(*rest)))
{
const dsql_fld* rest_field = varNode2->dsqlDef->type;
@ -607,11 +607,11 @@ void DsqlCompilerScratch::checkUnusedCTEs() const
SelectExprNode* DsqlCompilerScratch::pass1RecursiveCte(SelectExprNode* input)
{
RecordSourceNode* const query = input->querySpec;
UnionSourceNode* unionQuery = query->as<UnionSourceNode>();
UnionSourceNode* unionQuery = nodeAs<UnionSourceNode>(query);
if (!unionQuery)
{
if (!pass1RseIsRecursive(query->as<RseNode>()))
if (!pass1RseIsRecursive(nodeAs<RseNode>(query)))
return input;
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) <<
@ -640,7 +640,7 @@ SelectExprNode* DsqlCompilerScratch::pass1RecursiveCte(SelectExprNode* input)
if (iter == unionQuery->dsqlClauses->items.begin())
{
unionQuery = clause->as<UnionSourceNode>();
unionQuery = nodeAs<UnionSourceNode>(clause);
if (unionQuery)
{
@ -654,7 +654,7 @@ SelectExprNode* DsqlCompilerScratch::pass1RecursiveCte(SelectExprNode* input)
}
}
RseNode* const rse = clause->as<RseNode>();
RseNode* const rse = nodeAs<RseNode>(clause);
fb_assert(rse);
RseNode* const newRse = pass1RseIsRecursive(rse);
@ -815,7 +815,7 @@ RseNode* DsqlCompilerScratch::pass1RseIsRecursive(RseNode* input)
{
*prev++ = *pDstTable = *pSrcTable;
RseNode* rseNode = (*pDstTable)->as<RseNode>();
RseNode* rseNode = nodeAs<RseNode>(*pDstTable);
if (rseNode)
{
@ -841,7 +841,7 @@ RseNode* DsqlCompilerScratch::pass1RseIsRecursive(RseNode* input)
result->dsqlWhere = PASS1_compose(result->dsqlWhere, joinBool, blr_and);
}
}
else if ((*pDstTable)->is<ProcedureSourceNode>() || (*pDstTable)->is<RelationSourceNode>())
else if (nodeIs<ProcedureSourceNode>(*pDstTable) || nodeIs<RelationSourceNode>(*pDstTable))
{
if (pass1RelProcIsRecursive(*pDstTable))
{
@ -858,9 +858,7 @@ RseNode* DsqlCompilerScratch::pass1RseIsRecursive(RseNode* input)
}
}
else
{
fb_assert((*pDstTable)->is<SelectExprNode>());
}
fb_assert(nodeIs<SelectExprNode>(*pDstTable));
}
if (found)
@ -877,12 +875,12 @@ bool DsqlCompilerScratch::pass1RelProcIsRecursive(RecordSourceNode* input)
ProcedureSourceNode* procNode;
RelationSourceNode* relNode;
if ((procNode = input->as<ProcedureSourceNode>()))
if ((procNode = nodeAs<ProcedureSourceNode>(input)))
{
relName = procNode->dsqlName.identifier;
relAlias = procNode->alias;
}
else if ((relNode = input->as<RelationSourceNode>()))
else if ((relNode = nodeAs<RelationSourceNode>(input)))
{
relName = relNode->dsqlName;
relAlias = relNode->alias;
@ -906,7 +904,7 @@ bool DsqlCompilerScratch::pass1RelProcIsRecursive(RecordSourceNode* input)
// outer join or more than one recursive reference is found
BoolExprNode* DsqlCompilerScratch::pass1JoinIsRecursive(RecordSourceNode*& input)
{
RseNode* inputRse = input->as<RseNode>();
RseNode* inputRse = nodeAs<RseNode>(input);
fb_assert(inputRse);
const UCHAR joinType = inputRse->rse_jointype;
@ -917,7 +915,7 @@ BoolExprNode* DsqlCompilerScratch::pass1JoinIsRecursive(RecordSourceNode*& input
NestConst<RecordSourceNode>* joinTable = &inputRse->dsqlFrom->items[0];
RseNode* joinRse;
if ((joinRse = (*joinTable)->as<RseNode>()) && joinRse->dsqlExplicitJoin)
if ((joinRse = nodeAs<RseNode>(*joinTable)) && joinRse->dsqlExplicitJoin)
{
leftBool = pass1JoinIsRecursive(*joinTable->getAddress());
leftRecursive = (leftBool != NULL);
@ -943,7 +941,7 @@ BoolExprNode* DsqlCompilerScratch::pass1JoinIsRecursive(RecordSourceNode*& input
joinTable = &inputRse->dsqlFrom->items[1];
if ((joinRse = (*joinTable)->as<RseNode>()) && joinRse->dsqlExplicitJoin)
if ((joinRse = nodeAs<RseNode>(*joinTable)) && joinRse->dsqlExplicitJoin)
{
rightBool = pass1JoinIsRecursive(*joinTable->getAddress());
rightRecursive = (rightBool != NULL);

File diff suppressed because it is too large Load Diff

View File

@ -797,6 +797,8 @@ public:
return *reinterpret_cast<SLONG*>(litDesc.dsc_address);
}
void fixMinSInt64();
public:
const IntlString* dsqlStr;
dsc litDesc;
@ -1059,7 +1061,7 @@ public:
if (!ListExprNode::dsqlMatch(other, ignoreMapCast))
return false;
const Frame* o = other->as<Frame>();
const Frame* o = nodeAs<Frame>(other);
fb_assert(o);
return bound == o->bound;
@ -1128,7 +1130,7 @@ public:
if (!ListExprNode::dsqlMatch(other, ignoreMapCast))
return false;
const FrameExtent* o = other->as<FrameExtent>();
const FrameExtent* o = nodeAs<FrameExtent>(other);
fb_assert(o);
return unit == o->unit;
@ -1197,7 +1199,7 @@ public:
if (!DsqlNode::dsqlMatch(other, ignoreMapCast))
return false;
const WindowClause* o = other->as<WindowClause>();
const WindowClause* o = nodeAs<WindowClause>(other);
fb_assert(o);
return exclusion == o->exclusion;

View File

@ -281,21 +281,25 @@ public:
};
class SetSessionNode : public Node
class SessionManagementNode : public Node
{
public:
enum Type { TYPE_IDLE_TIMEOUT, TYPE_STMT_TIMEOUT };
SetSessionNode(MemoryPool& pool, Type aType, ULONG aVal, UCHAR blr_timepart);
explicit SessionManagementNode(MemoryPool& pool)
: Node(pool)
{
}
public:
virtual Firebird::string internalPrint(NodePrinter& printer) const;
virtual SetSessionNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
virtual void execute(thread_db* tdbb, dsql_req* request) const;
virtual SessionManagementNode* dsqlPass(DsqlCompilerScratch* dsqlScratch)
{
Node::dsqlPass(dsqlScratch);
private:
Type m_type;
ULONG m_value;
dsqlScratch->getStatement()->setType(DsqlCompiledStatement::TYPE_SESSION_MANAGEMENT);
return this;
}
virtual void execute(thread_db* tdbb, dsql_req* request) const = 0;
};
@ -352,6 +356,37 @@ public:
};
template <typename To, typename From> static To* nodeAs(From* fromNode)
{
return fromNode && fromNode->type == To::TYPE ? static_cast<To*>(fromNode) : NULL;
}
template <typename To, typename From> static To* nodeAs(NestConst<From>& fromNode)
{
return fromNode && fromNode->type == To::TYPE ? static_cast<To*>(fromNode.getObject()) : NULL;
}
template <typename To, typename From> static const To* nodeAs(const From* fromNode)
{
return fromNode && fromNode->type == To::TYPE ? static_cast<const To*>(fromNode) : NULL;
}
template <typename To, typename From> static const To* nodeAs(const NestConst<From>& fromNode)
{
return fromNode && fromNode->type == To::TYPE ? static_cast<const To*>(fromNode.getObject()) : NULL;
}
template <typename To, typename From> static bool nodeIs(const From* fromNode)
{
return fromNode && fromNode->type == To::TYPE;
}
template <typename To, typename From> static bool nodeIs(const NestConst<From>& fromNode)
{
return fromNode && fromNode->type == To::TYPE;
}
// Stores a reference to a specialized ExprNode.
// This class and NodeRefImpl exists for nodes to replace themselves (eg. pass1) in a type-safe way.
class NodeRef
@ -489,7 +524,8 @@ public:
// Value flags.
static const unsigned FLAG_DOUBLE = 0x10;
static const unsigned FLAG_DATE = 0x20;
static const unsigned FLAG_VALUE = 0x40; // Full value area required in impure space.
static const unsigned FLAG_DECFLOAT = 0x40;
static const unsigned FLAG_VALUE = 0x80; // Full value area required in impure space.
explicit ExprNode(Type aType, MemoryPool& pool, Kind aKind)
: DmlNode(pool, aKind),
@ -502,39 +538,6 @@ public:
{
}
template <typename T> T* as()
{
const ExprNode* const thisPointer = this; // avoid warning
return thisPointer && type == T::TYPE ? static_cast<T*>(this) : NULL;
}
template <typename T> const T* as() const
{
const ExprNode* const thisPointer = this; // avoid warning
return thisPointer && type == T::TYPE ? static_cast<const T*>(this) : NULL;
}
template <typename T> bool is() const
{
const ExprNode* const thisPointer = this; // avoid warning
return thisPointer && type == T::TYPE;
}
template <typename T, typename LegacyType> static T* as(LegacyType* node)
{
return node ? node->template as<T>() : NULL;
}
template <typename T, typename LegacyType> static const T* as(const LegacyType* node)
{
return node ? node->template as<T>() : NULL;
}
template <typename T, typename LegacyType> static bool is(const LegacyType* node)
{
return node ? node->template is<T>() : false;
}
// Allocate and assign impure space for various nodes.
template <typename T> static void doPass2(thread_db* tdbb, CompilerScratch* csb, T** node)
{

View File

@ -22,6 +22,7 @@
#include "firebird.h"
#include <ctype.h>
#include <math.h>
#include "../dsql/Parser.h"
#include "../dsql/chars.h"
#include "../jrd/jrd.h"
@ -29,6 +30,12 @@
#include "../yvalve/keywords.h"
#include "../jrd/intl_proto.h"
#ifdef HAVE_FLOAT_H
#include <float.h>
#else
#define DBL_MAX_10_EXP 308
#endif
using namespace Firebird;
using namespace Jrd;
@ -925,15 +932,19 @@ int Parser::yylexAux()
{
// The following variables are used to recognize kinds of numbers.
bool have_error = false; // syntax error or value too large
bool have_digit = false; // we've seen a digit
bool have_decimal = false; // we've seen a '.'
bool have_exp = false; // digit ... [eE]
bool have_exp_sign = false; // digit ... [eE] {+-]
bool have_exp_digit = false; // digit ... [eE] ... digit
bool have_error = false; // syntax error or value too large
bool have_digit = false; // we've seen a digit
bool have_decimal = false; // we've seen a '.'
bool have_exp = false; // digit ... [eE]
bool have_exp_sign = false; // digit ... [eE] {+-]
bool have_exp_digit = false; // digit ... [eE] ... digit
bool have_overflow = false; // value of digits > MAX_SINT64
bool positive_overflow = false; // number is exactly (MAX_SINT64 + 1)
FB_UINT64 number = 0;
int expVal = 0;
FB_UINT64 limit_by_10 = MAX_SINT64 / 10;
SCHAR scale = 0;
int scale = 0;
int expSign = 1;
for (--lex.ptr; lex.ptr < lex.end; lex.ptr++)
{
@ -953,10 +964,22 @@ int Parser::yylexAux()
{
// We've seen e or E, but nothing beyond that.
if ( ('-' == c) || ('+' == c) )
{
have_exp_sign = true;
if ('-' == c)
expSign = -1;
}
else if ( classes(c) & CHR_DIGIT )
{
// We have a digit: we haven't seen a sign yet, but it's too late now.
have_exp_digit = have_exp_sign = true;
if (!have_overflow)
{
expVal = expVal * 10 + (c - '0');
if (expVal > DBL_MAX_10_EXP)
have_overflow = true;
}
}
else
{
// end of the token
@ -978,19 +1001,26 @@ int Parser::yylexAux()
{
// Before computing the next value, make sure there will be no overflow.
have_digit = true;
if (number >= limit_by_10)
if (!have_overflow)
{
// possibility of an overflow
if ((number > limit_by_10) || (c > '8'))
have_digit = true;
if (number >= limit_by_10)
{
have_error = true;
break;
// possibility of an overflow
if ((number > limit_by_10) || (c >= '8'))
{
have_overflow = true;
if ((number == limit_by_10) && (c == '8'))
positive_overflow = true;
}
}
}
else
positive_overflow = false;
number = number * 10 + (c - '0');
if (!have_overflow)
number = number * 10 + (c - '0');
if (have_decimal)
--scale;
@ -1009,15 +1039,48 @@ int Parser::yylexAux()
{
fb_assert(have_digit);
if (have_exp_digit)
if (positive_overflow)
have_overflow = false;
if (scale < MIN_SCHAR || scale > MAX_SCHAR)
{
have_overflow = true;
positive_overflow = false;
}
// check for a more complex overflow case
if ((!have_overflow) && (expSign > 0) && (expVal > -scale))
{
expVal += scale;
double maxNum = DBL_MAX / pow(10.0, expVal);
if (double(number) > maxNum)
{
have_overflow = true;
positive_overflow = false;
}
}
// Should we use floating point type?
if (have_exp_digit || have_overflow || positive_overflow)
{
if (positive_overflow && scale)
{
yylval.lim64ptr = newLim64String(
Firebird::string(lex.last_token, lex.ptr - lex.last_token), scale);
lex.last_token_bk = lex.last_token;
lex.line_start_bk = lex.line_start;
lex.lines_bk = lex.lines;
return TOK_LIMIT64_NUMBER;
}
yylval.stringPtr = newString(
Firebird::string(lex.last_token, lex.ptr - lex.last_token));
lex.last_token_bk = lex.last_token;
lex.line_start_bk = lex.line_start;
lex.lines_bk = lex.lines;
return TOK_FLOAT_NUMBER;
return positive_overflow ? TOK_LIMIT64_INT : have_overflow ? TOK_DECIMAL_NUMBER : TOK_FLOAT_NUMBER;
}
if (!have_exp)

View File

@ -144,6 +144,11 @@ public:
return FB_NEW_POOL(getPool()) Firebird::string(getPool(), s);
}
Lim64String* newLim64String(const Firebird::string& s, int scale)
{
return FB_NEW_POOL(getPool()) Lim64String(getPool(), s, scale);
}
IntlString* newIntlString(const Firebird::string& s, const char* charSet = NULL)
{
return FB_NEW_POOL(getPool()) IntlString(getPool(), s, charSet);
@ -209,7 +214,7 @@ private:
BoolExprNode* valueToBool(ValueExprNode* value)
{
BoolAsValueNode* node = value->as<BoolAsValueNode>();
BoolAsValueNode* node = nodeAs<BoolAsValueNode>(value);
if (node)
return node->boolean;

View File

@ -195,7 +195,7 @@ namespace
return NULL;
// nod_returning was already processed
CompoundStmtNode* processedStmt = processed->as<CompoundStmtNode>();
CompoundStmtNode* processedStmt = nodeAs<CompoundStmtNode>(processed);
fb_assert(processed);
// And we create a RETURNING node where the targets are already processed.
@ -211,7 +211,7 @@ namespace
{
AssignmentNode* temp = FB_NEW_POOL(scratch->getPool()) AssignmentNode(scratch->getPool());
temp->asgnFrom = *srcPtr;
temp->asgnTo = (*dstPtr)->as<AssignmentNode>()->asgnTo;
temp->asgnTo = nodeAs<AssignmentNode>(*dstPtr)->asgnTo;
newNode->statements.add(temp);
}
@ -291,7 +291,7 @@ void AssignmentNode::validateTarget(CompilerScratch* csb, const ValueExprNode* t
{
const FieldNode* fieldNode;
if ((fieldNode = target->as<FieldNode>()))
if ((fieldNode = nodeAs<FieldNode>(target)))
{
CompilerScratch::csb_repeat* tail = &csb->csb_rpt[fieldNode->fieldStream];
@ -311,13 +311,13 @@ void AssignmentNode::validateTarget(CompilerScratch* csb, const ValueExprNode* t
if (fieldNode->cursorNumber.specified)
ERR_post(Arg::Gds(isc_read_only_field));
}
else if (!(target->is<ParameterNode>() || target->is<VariableNode>() || target->is<NullNode>()))
else if (!(nodeIs<ParameterNode>(target) || nodeIs<VariableNode>(target) || nodeIs<NullNode>(target)))
ERR_post(Arg::Gds(isc_read_only_field));
}
void AssignmentNode::dsqlValidateTarget(const ValueExprNode* target)
{
const DerivedFieldNode* fieldNode = target->as<DerivedFieldNode>();
const DerivedFieldNode* fieldNode = nodeAs<DerivedFieldNode>(target);
if (fieldNode && fieldNode->context &&
(fieldNode->context->ctx_flags & (CTX_system | CTX_cursor)) == CTX_cursor)
@ -381,7 +381,7 @@ AssignmentNode* AssignmentNode::pass1(thread_db* tdbb, CompilerScratch* csb)
StreamType stream;
CompilerScratch::csb_repeat* tail;
if ((fieldNode = sub->as<FieldNode>()))
if ((fieldNode = nodeAs<FieldNode>(sub)))
{
stream = fieldNode->fieldStream;
jrd_fld* field = MET_get_field(csb->csb_rpt[stream].csb_relation, fieldNode->fieldId);
@ -392,7 +392,7 @@ AssignmentNode* AssignmentNode::pass1(thread_db* tdbb, CompilerScratch* csb)
sub = asgnTo;
if ((fieldNode = sub->as<FieldNode>()))
if ((fieldNode = nodeAs<FieldNode>(sub)))
{
stream = fieldNode->fieldStream;
tail = &csb->csb_rpt[stream];
@ -603,7 +603,7 @@ const StmtNode* BlockNode::execute(thread_db* tdbb, jrd_req* request, ExeState*
ptr != end;
++ptr)
{
const ErrorHandlerNode* const handlerNode = (*ptr)->as<ErrorHandlerNode>();
const ErrorHandlerNode* const handlerNode = nodeAs<ErrorHandlerNode>(*ptr);
if (testAndFixupError(tdbb, request, handlerNode->conditions))
{
@ -1189,7 +1189,7 @@ const StmtNode* CursorStmtNode::execute(thread_db* tdbb, jrd_req* request, ExeSt
const dsc* desc = EVL_expr(tdbb, request, scrollExpr);
const bool unknown = !desc || (request->req_flags & req_null);
const SINT64 offset = unknown ? 0 : MOV_get_int64(desc, 0);
const SINT64 offset = unknown ? 0 : MOV_get_int64(tdbb, desc, 0);
switch (scrollOp)
{
@ -2115,7 +2115,7 @@ StmtNode* EraseNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
rse->dsqlFlags |= RecordSourceNode::DFLAG_SINGLETON;
node->dsqlRse = rse;
node->dsqlRelation = rse->dsqlStreams->items[0]->as<RelationSourceNode>();
node->dsqlRelation = nodeAs<RelationSourceNode>(rse->dsqlStreams->items[0]);
node->statement = dsqlProcessReturning(dsqlScratch, dsqlReturning, statement);
@ -5153,9 +5153,9 @@ StmtNode* MergeNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
forNode->dsqlForceSingular = true;
// Get the already processed relations.
RseNode* processedRse = forNode->rse->dsqlStreams->items[0]->as<RseNode>();
RseNode* processedRse = nodeAs<RseNode>(forNode->rse->dsqlStreams->items[0]);
source = processedRse->dsqlStreams->items[0];
target = processedRse->dsqlStreams->items[1]->as<RelationSourceNode>();
target = nodeAs<RelationSourceNode>(processedRse->dsqlStreams->items[1]);
DsqlContextStack usingCtxs;
dsqlGetContexts(usingCtxs, source);
@ -5181,7 +5181,7 @@ StmtNode* MergeNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
// Separate the new and org values to process in correct contexts.
for (FB_SIZE_T i = 0; i < stmts->statements.getCount(); ++i)
{
AssignmentNode* const assign = stmts->statements[i]->as<AssignmentNode>();
AssignmentNode* const assign = nodeAs<AssignmentNode>(stmts->statements[i]);
fb_assert(assign);
orgValues.add(assign->asgnFrom);
newValues.add(assign->asgnTo);
@ -5345,7 +5345,7 @@ StmtNode* MergeNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
store->overrideClause = notMatched->overrideClause;
bool needSavePoint; // unused
thisIf->trueAction = store = store->internalDsqlPass(dsqlScratch, false, needSavePoint)->as<StoreNode>();
thisIf->trueAction = store = nodeAs<StoreNode>(store->internalDsqlPass(dsqlScratch, false, needSavePoint));
fb_assert(store);
if (notMatched->condition)
@ -5521,11 +5521,8 @@ void MessageNode::setup(thread_db* tdbb, CompilerScratch* csb, USHORT message, U
// So we only check even indexes, which is the actual parameter.
if (itemInfo.isSpecial() && index % 2 == 0)
{
csb->csb_dbg_info->argInfoToName.get(
ArgumentInfo(csb->csb_msg_number, index / 2), itemInfo.name);
csb->csb_map_item_info.put(Item(Item::TYPE_PARAMETER, csb->csb_msg_number, index),
itemInfo);
csb->csb_dbg_info->argInfoToName.get(ArgumentInfo(csb->csb_msg_number, index / 2), itemInfo.name);
csb->csb_map_item_info.put(Item(Item::TYPE_PARAMETER, message, index), itemInfo);
}
}
@ -5654,18 +5651,18 @@ StmtNode* ModifyNode::internalDsqlPass(DsqlCompilerScratch* dsqlScratch, bool up
Array<NestConst<ValueExprNode> > orgValues, newValues;
CompoundStmtNode* assignments = statement->as<CompoundStmtNode>();
CompoundStmtNode* assignments = nodeAs<CompoundStmtNode>(statement);
fb_assert(assignments);
for (FB_SIZE_T i = 0; i < assignments->statements.getCount(); ++i)
{
AssignmentNode* const assign = assignments->statements[i]->as<AssignmentNode>();
AssignmentNode* const assign = nodeAs<AssignmentNode>(assignments->statements[i]);
fb_assert(assign);
orgValues.add(assign->asgnFrom);
newValues.add(assign->asgnTo);
}
NestConst<RelationSourceNode> relation = dsqlRelation->as<RelationSourceNode>();
NestConst<RelationSourceNode> relation = nodeAs<RelationSourceNode>(dsqlRelation);
fb_assert(relation);
NestConst<ValueExprNode>* ptr;
@ -5854,7 +5851,7 @@ string ModifyNode::internalPrint(NodePrinter& printer) const
void ModifyNode::genBlr(DsqlCompilerScratch* dsqlScratch)
{
RseNode* rse = dsqlRse->as<RseNode>();
RseNode* rse = nodeAs<RseNode>(dsqlRse);
const dsql_msg* message = dsqlGenDmlHeader(dsqlScratch, rse);
@ -5884,7 +5881,7 @@ void ModifyNode::genBlr(DsqlCompilerScratch* dsqlScratch)
ModifyNode* ModifyNode::pass1(thread_db* tdbb, CompilerScratch* csb)
{
preprocessAssignments(tdbb, csb, newStream, statement->as<CompoundStmtNode>(), NULL);
preprocessAssignments(tdbb, csb, newStream, nodeAs<CompoundStmtNode>(statement), NULL);
pass1Modify(tdbb, csb, this);
@ -6449,7 +6446,7 @@ DmlNode* StoreNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* cs
const UCHAR* blrPos = csb->csb_blr_reader.getPos();
node->relationSource = PAR_parseRecordSource(tdbb, csb)->as<RelationSourceNode>();
node->relationSource = nodeAs<RelationSourceNode>(PAR_parseRecordSource(tdbb, csb));
if (!node->relationSource)
{
@ -6489,7 +6486,7 @@ StmtNode* StoreNode::internalDsqlPass(DsqlCompilerScratch* dsqlScratch,
if (dsqlRse)
{
SelectExprNode* selExpr = dsqlRse->as<SelectExprNode>();
SelectExprNode* selExpr = nodeAs<SelectExprNode>(dsqlRse);
fb_assert(selExpr);
if (dsqlReturning || statement2)
@ -6540,13 +6537,13 @@ StmtNode* StoreNode::internalDsqlPass(DsqlCompilerScratch* dsqlScratch,
const FieldNode* fieldNode;
const DerivedFieldNode* derivedField;
if ((fieldNode = ExprNode::as<FieldNode>(temp2)))
if ((fieldNode = nodeAs<FieldNode>(temp2)))
{
tmp_ctx = fieldNode->dsqlContext;
if (fieldNode->dsqlField)
tmp_name = fieldNode->dsqlField->fld_name.c_str();
}
else if ((derivedField = ExprNode::as<DerivedFieldNode>(temp2)))
else if ((derivedField = nodeAs<DerivedFieldNode>(temp2)))
{
tmp_ctx = derivedField->context;
tmp_name = derivedField->name.nullStr();
@ -6594,7 +6591,7 @@ StmtNode* StoreNode::internalDsqlPass(DsqlCompilerScratch* dsqlScratch,
if (!*ptr2)
{
const FieldNode* field = (*ptr)->as<FieldNode>();
const FieldNode* field = nodeAs<FieldNode>(*ptr);
if (field && field->dsqlField)
{
@ -6661,7 +6658,7 @@ StmtNode* StoreNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
StmtNode* node = SavepointEncloseNode::make(getPool(), dsqlScratch,
internalDsqlPass(dsqlScratch, false, needSavePoint));
if (!needSavePoint || node->is<SavepointEncloseNode>())
if (!needSavePoint || nodeIs<SavepointEncloseNode>(node))
return node;
return FB_NEW SavepointEncloseNode(getPool(), node);
@ -6687,7 +6684,7 @@ string StoreNode::internalPrint(NodePrinter& printer) const
void StoreNode::genBlr(DsqlCompilerScratch* dsqlScratch)
{
const dsql_msg* message = dsqlGenDmlHeader(dsqlScratch, dsqlRse->as<RseNode>());
const dsql_msg* message = dsqlGenDmlHeader(dsqlScratch, nodeAs<RseNode>(dsqlRse));
dsqlScratch->appendUChar(overrideClause.specified ? blr_store3 : (statement2 ? blr_store2 : blr_store));
@ -6709,7 +6706,7 @@ void StoreNode::genBlr(DsqlCompilerScratch* dsqlScratch)
StoreNode* StoreNode::pass1(thread_db* tdbb, CompilerScratch* csb)
{
preprocessAssignments(tdbb, csb, relationSource->getStream(), statement->as<CompoundStmtNode>(), &overrideClause);
preprocessAssignments(tdbb, csb, relationSource->getStream(), nodeAs<CompoundStmtNode>(statement), &overrideClause);
if (pass1Store(tdbb, csb, this))
makeDefaults(tdbb, csb);
@ -6871,7 +6868,7 @@ void StoreNode::makeDefaults(thread_db* tdbb, CompilerScratch* csb)
if (assign)
{
const FieldNode* fieldNode = assign->asgnTo->as<FieldNode>();
const FieldNode* fieldNode = nodeAs<FieldNode>(assign->asgnTo);
fb_assert(fieldNode);
if (fieldNode && fieldNode->fieldStream == stream && fieldNode->fieldId == fieldId)
@ -6984,7 +6981,7 @@ const StmtNode* StoreNode::store(thread_db* tdbb, jrd_req* request, WhichTrigger
switch (request->req_operation)
{
case jrd_req::req_evaluate:
if (!parentStmt->is<ForNode>())
if (!nodeIs<ForNode>(parentStmt))
request->req_records_affected.clear();
request->req_records_affected.bumpModified(false);
@ -7208,7 +7205,7 @@ const StmtNode* UserSavepointNode::execute(thread_db* tdbb, jrd_req* request, Ex
}
default:
BUGCHECK(232);
SOFT_BUGCHECK(232); // msg 232 EVL_expr: invalid operation
break;
}
@ -7260,7 +7257,7 @@ SelectNode* SelectNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
// stored procedure occurs in the select list. In these cases all of stored procedure is
// executed under savepoint for open cursor.
RseNode* rseNode = node->dsqlRse->as<RseNode>();
RseNode* rseNode = nodeAs<RseNode>(node->dsqlRse);
if (rseNode->dsqlOrder || rseNode->dsqlDistinct)
{
@ -7288,7 +7285,7 @@ string SelectNode::internalPrint(NodePrinter& printer) const
// Generate BLR for a SELECT statement.
void SelectNode::genBlr(DsqlCompilerScratch* dsqlScratch)
{
RseNode* const rse = dsqlRse->as<RseNode>();
RseNode* const rse = nodeAs<RseNode>(dsqlRse);
fb_assert(rse);
DsqlCompiledStatement* const statement = dsqlScratch->getStatement();
@ -7326,7 +7323,7 @@ void SelectNode::genBlr(DsqlCompilerScratch* dsqlScratch)
RecordSourceNode* const item = *ptr2;
RelationSourceNode* relNode;
if (item && (relNode = ExprNode::as<RelationSourceNode>(item)))
if (item && (relNode = nodeAs<RelationSourceNode>(item)))
{
context = relNode->dsqlContext;
const dsql_rel* const relation = context->ctx_relation;
@ -7532,7 +7529,7 @@ const StmtNode* SetGeneratorNode::execute(thread_db* tdbb, jrd_req* request, Exe
DDL_TRIGGER_ALTER_SEQUENCE, generator.name, NULL, *request->getStatement()->sqlText);
dsc* const desc = EVL_expr(tdbb, request, value);
DPM_gen_id(tdbb, generator.id, true, MOV_get_int64(desc, 0));
DPM_gen_id(tdbb, generator.id, true, MOV_get_int64(tdbb, desc, 0));
DdlNode::executeDdlTrigger(tdbb, transaction, DdlNode::DTW_AFTER,
DDL_TRIGGER_ALTER_SEQUENCE, generator.name, NULL, *request->getStatement()->sqlText);
@ -7685,11 +7682,11 @@ const StmtNode* SuspendNode::execute(thread_db* tdbb, jrd_req* request, ExeState
if (!(request->req_flags & req_proc_fetch))
return statement;
const CompoundStmtNode* list = parentStmt->as<CompoundStmtNode>();
const CompoundStmtNode* list = nodeAs<CompoundStmtNode>(parentStmt);
if (list && !list->parentStmt && list->statements[list->statements.getCount() - 1] == this)
{
list = statement->as<CompoundStmtNode>();
list = nodeAs<CompoundStmtNode>(statement);
if (list && list->onlyAssignments && list->statements.hasData())
{
@ -7957,14 +7954,7 @@ void SetTransactionNode::genTableLock(DsqlCompilerScratch* dsqlScratch,
//--------------------
SetRoleNode* SetRoleNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
{
dsqlScratch->getStatement()->setType(DsqlCompiledStatement::TYPE_SET_ROLE);
return this;
}
void SetRoleNode::execute(thread_db* tdbb, dsql_req* request, jrd_tra** transaction) const
void SetRoleNode::execute(thread_db* tdbb, dsql_req* request) const
{
SET_TDBB(tdbb);
Attachment* const attachment = tdbb->getAttachment();
@ -7988,8 +7978,122 @@ void SetRoleNode::execute(thread_db* tdbb, dsql_req* request, jrd_tra** transact
//--------------------
namespace
{
struct TextCode
{
const char* name;
USHORT val;
};
//#define FB_TEXTCODE(x) { STRINGIZE(x), x }
#define FB_TEXTCODE(x) { #x, x }
const TextCode roundModes[] = {
FB_TEXTCODE(DEC_ROUND_CEILING),
FB_TEXTCODE(DEC_ROUND_UP),
FB_TEXTCODE(DEC_ROUND_HALF_UP),
FB_TEXTCODE(DEC_ROUND_HALF_EVEN),
FB_TEXTCODE(DEC_ROUND_HALF_DOWN),
FB_TEXTCODE(DEC_ROUND_DOWN),
FB_TEXTCODE(DEC_ROUND_FLOOR),
{ "DEC_ROUND_REROUND", DEC_ROUND_05UP },
{ NULL, 0 }
};
//DEC_ROUND_
//0123456789
const unsigned FB_RMODE_OFFSET = 10;
const TextCode ieeeTraps[] = {
FB_TEXTCODE(DEC_IEEE_754_Division_by_zero),
FB_TEXTCODE(DEC_IEEE_754_Inexact),
FB_TEXTCODE(DEC_IEEE_754_Invalid_operation),
FB_TEXTCODE(DEC_IEEE_754_Overflow),
FB_TEXTCODE(DEC_IEEE_754_Underflow),
{ NULL, 0 }
};
//DEC_IEEE_754_
//0123456789012
const unsigned FB_TRAPS_OFFSET = 13;
#undef FB_TEXTCODE
const TextCode* getCodeByText(const MetaName& text, const TextCode* textCode, unsigned offset)
{
NoCaseString name(text.c_str(), text.length());
for (const TextCode* tc = textCode; tc->name; ++tc)
{
if (name == &tc->name[offset])
return tc;
}
return nullptr;
}
}
//--------------------
SetRoundNode::SetRoundNode(MemoryPool& pool, Firebird::MetaName* name)
: SessionManagementNode(pool)
{
fb_assert(name);
const TextCode* mode = getCodeByText(*name, roundModes, FB_RMODE_OFFSET);
if (!mode)
(Arg::Gds(isc_random) << "Invalid round mode for decfloat").raise();
rndMode = mode->val;
}
void SetRoundNode::execute(thread_db* tdbb, dsql_req* /*request*/) const
{
SET_TDBB(tdbb);
Attachment* const attachment = tdbb->getAttachment();
attachment->att_dec_status.roundingMode = rndMode;
}
//--------------------
void SetTrapsNode::trap(Firebird::MetaName* name)
{
fb_assert(name);
const TextCode* trap = getCodeByText(*name, ieeeTraps, FB_TRAPS_OFFSET);
if (!trap)
(Arg::Gds(isc_random) << "Invalid decfloat trap").raise();
traps |= trap->val;
}
void SetTrapsNode::execute(thread_db* tdbb, dsql_req* /*request*/) const
{
SET_TDBB(tdbb);
Attachment* const attachment = tdbb->getAttachment();
attachment->att_dec_status.decExtFlag = traps;
}
//--------------------
void SetBindNode::execute(thread_db* tdbb, dsql_req* /*request*/) const
{
SET_TDBB(tdbb);
Attachment* const attachment = tdbb->getAttachment();
attachment->att_dec_binding = bind;
}
//--------------------
SetSessionNode::SetSessionNode(MemoryPool& pool, Type aType, ULONG aVal, UCHAR blr_timepart)
: Node(pool),
: SessionManagementNode(pool),
m_type(aType),
m_value(0)
{
@ -8036,12 +8140,6 @@ string SetSessionNode::internalPrint(NodePrinter& printer) const
return "SetSessionNode";
}
SetSessionNode* SetSessionNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
{
dsqlScratch->getStatement()->setType(DsqlCompiledStatement::TYPE_SET_SESSION);
return this;
}
void SetSessionNode::execute(thread_db* tdbb, dsql_req* request) const
{
Attachment* att = tdbb->getAttachment();
@ -8070,7 +8168,7 @@ StmtNode* UpdateOrInsertNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
if (!dsqlScratch->isPsql())
dsqlScratch->flags |= DsqlCompilerScratch::FLAG_UPDATE_OR_INSERT;
const MetaName& relation_name = relation->as<RelationSourceNode>()->dsqlName;
const MetaName& relation_name = nodeAs<RelationSourceNode>(relation)->dsqlName;
MetaName base_name = relation_name;
bool needSavePoint;
@ -8082,7 +8180,7 @@ StmtNode* UpdateOrInsertNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
insert->dsqlValues = values;
insert->dsqlReturning = returning;
insert->overrideClause = overrideClause;
insert = insert->internalDsqlPass(dsqlScratch, true, needSavePoint)->as<StoreNode>();
insert = nodeAs<StoreNode>(insert->internalDsqlPass(dsqlScratch, true, needSavePoint));
fb_assert(insert);
dsql_ctx* context = insert->dsqlRelation->dsqlContext;
@ -8154,7 +8252,7 @@ StmtNode* UpdateOrInsertNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
NestConst<ValueExprNode>* valuePtr = values->items.begin();
Array<NestConst<StmtNode> >& insertStatements =
insert->statement->as<CompoundStmtNode>()->statements;
nodeAs<CompoundStmtNode>(insert->statement)->statements;
for (; fieldPtr != fieldsCopy.end(); ++fieldPtr, ++valuePtr)
{
@ -8192,7 +8290,7 @@ StmtNode* UpdateOrInsertNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
++matchCount;
const FB_SIZE_T fieldPos = fieldPtr - fieldsCopy.begin();
AssignmentNode* assign2 = insertStatements[fieldPos]->as<AssignmentNode>();
AssignmentNode* assign2 = nodeAs<AssignmentNode>(insertStatements[fieldPos]);
NestConst<ValueExprNode>& expr = assign2->asgnFrom;
ValueExprNode* var = dsqlPassHiddenVariable(dsqlScratch, expr);
@ -8240,7 +8338,7 @@ StmtNode* UpdateOrInsertNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
dsqlScratch, returning, insert->statement2);
}
update = update->internalDsqlPass(dsqlScratch, true)->as<ModifyNode>();
update = nodeAs<ModifyNode>(update->internalDsqlPass(dsqlScratch, true));
fb_assert(update);
// test if ROW_COUNT = 0
@ -8269,7 +8367,7 @@ StmtNode* UpdateOrInsertNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
dsqlScratch->getStatement()->setType(DsqlCompiledStatement::TYPE_INSERT);
StmtNode* ret = SavepointEncloseNode::make(getPool(), dsqlScratch, list);
if (!needSavePoint || ret->is<SavepointEncloseNode>())
if (!needSavePoint || nodeIs<SavepointEncloseNode>(ret))
return ret;
return FB_NEW SavepointEncloseNode(getPool(), ret);
@ -8415,13 +8513,13 @@ static dsql_ctx* dsqlGetContext(const RecordSourceNode* node)
const RelationSourceNode* relNode;
const RseNode* rseNode;
if ((procNode = ExprNode::as<ProcedureSourceNode>(node)))
if ((procNode = nodeAs<ProcedureSourceNode>(node)))
return procNode->dsqlContext;
if ((relNode = ExprNode::as<RelationSourceNode>(node)))
if ((relNode = nodeAs<RelationSourceNode>(node)))
return relNode->dsqlContext;
if ((rseNode = ExprNode::as<RseNode>(node)))
if ((rseNode = nodeAs<RseNode>(node)))
return rseNode->dsqlContext;
fb_assert(false);
@ -8435,11 +8533,11 @@ static void dsqlGetContexts(DsqlContextStack& contexts, const RecordSourceNode*
const RelationSourceNode* relNode;
const RseNode* rseNode;
if ((procNode = ExprNode::as<ProcedureSourceNode>(node)))
if ((procNode = nodeAs<ProcedureSourceNode>(node)))
contexts.push(procNode->dsqlContext);
else if ((relNode = ExprNode::as<RelationSourceNode>(node)))
else if ((relNode = nodeAs<RelationSourceNode>(node)))
contexts.push(relNode->dsqlContext);
else if ((rseNode = ExprNode::as<RseNode>(node)))
else if ((rseNode = nodeAs<RseNode>(node)))
{
if (rseNode->dsqlContext) // derived table
contexts.push(rseNode->dsqlContext);
@ -8472,11 +8570,11 @@ static StmtNode* dsqlNullifyReturning(DsqlCompilerScratch* dsqlScratch, StmtNode
ModifyNode* modifyNode;
StoreNode* storeNode;
if (eraseNode = input->as<EraseNode>())
if (eraseNode = nodeAs<EraseNode>(input))
returning = eraseNode->statement;
else if (modifyNode = input->as<ModifyNode>())
else if (modifyNode = nodeAs<ModifyNode>(input))
returning = modifyNode->statement2;
else if (storeNode = input->as<StoreNode>())
else if (storeNode = nodeAs<StoreNode>(input))
returning = storeNode->statement2;
else
{
@ -8493,7 +8591,7 @@ static StmtNode* dsqlNullifyReturning(DsqlCompilerScratch* dsqlScratch, StmtNode
// completely removed.
// nod_returning was already processed
CompoundStmtNode* returningStmt = returning->as<CompoundStmtNode>();
CompoundStmtNode* returningStmt = nodeAs<CompoundStmtNode>(returning);
fb_assert(returningStmt);
CompoundStmtNode* nullAssign = FB_NEW_POOL(pool) CompoundStmtNode(pool);
@ -8507,7 +8605,7 @@ static StmtNode* dsqlNullifyReturning(DsqlCompilerScratch* dsqlScratch, StmtNode
{
AssignmentNode* assign = FB_NEW_POOL(pool) AssignmentNode(pool);
assign->asgnFrom = FB_NEW_POOL(pool) NullNode(pool);
assign->asgnTo = (*ret_ptr)->as<AssignmentNode>()->asgnTo;
assign->asgnTo = nodeAs<AssignmentNode>(*ret_ptr)->asgnTo;
*null_ptr = assign;
}
@ -8529,7 +8627,7 @@ static void dsqlFieldAppearsOnce(const Array<NestConst<ValueExprNode> >& values,
{
for (FB_SIZE_T i = 0; i < values.getCount(); ++i)
{
const FieldNode* field1 = values[i]->as<FieldNode>();
const FieldNode* field1 = nodeAs<FieldNode>(values[i]);
if (!field1)
continue;
@ -8537,7 +8635,7 @@ static void dsqlFieldAppearsOnce(const Array<NestConst<ValueExprNode> >& values,
for (FB_SIZE_T j = i + 1; j < values.getCount(); ++j)
{
const FieldNode* field2 = values[j]->as<FieldNode>();
const FieldNode* field2 = nodeAs<FieldNode>(values[j]);
if (!field2)
continue;
@ -8589,7 +8687,7 @@ static dsql_ctx* dsqlPassCursorContext(DsqlCompilerScratch* dsqlScratch, const M
DeclareCursorNode::CUR_TYPE_ALL, true);
fb_assert(node);
const RseNode* nodeRse = node->rse->as<RseNode>();
const RseNode* nodeRse = nodeAs<RseNode>(node->rse);
fb_assert(nodeRse);
if (nodeRse->dsqlDistinct)
@ -8607,7 +8705,7 @@ static dsql_ctx* dsqlPassCursorContext(DsqlCompilerScratch* dsqlScratch, const M
for (const NestConst<RecordSourceNode>* const end = temp->items.end(); ptr != end; ++ptr)
{
RecordSourceNode* r_node = *ptr;
RelationSourceNode* relNode = ExprNode::as<RelationSourceNode>(r_node);
RelationSourceNode* relNode = nodeAs<RelationSourceNode>(r_node);
if (relNode)
{
@ -8628,7 +8726,7 @@ static dsql_ctx* dsqlPassCursorContext(DsqlCompilerScratch* dsqlScratch, const M
context = candidate;
}
}
else if (ExprNode::as<AggregateSourceNode>(r_node))
else if (nodeAs<AggregateSourceNode>(r_node))
{
// cursor with aggregation is not updatable
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-510) <<
@ -8694,8 +8792,7 @@ static RseNode* dsqlPassCursorReference(DsqlCompilerScratch* dsqlScratch, const
RseNode* rse = FB_NEW_POOL(pool) RseNode(pool);
rse->dsqlStreams = FB_NEW_POOL(pool) RecSourceListNode(pool, 1);
RelationSourceNode* relation_node =
PASS1_relation(dsqlScratch, relation_name)->as<RelationSourceNode>();
RelationSourceNode* relation_node = nodeAs<RelationSourceNode>(PASS1_relation(dsqlScratch, relation_name));
rse->dsqlStreams->items[0] = relation_node;
RecordKeyNode* dbKeyNode = FB_NEW_POOL(pool) RecordKeyNode(pool, blr_dbkey);
@ -8961,7 +9058,7 @@ static void dsqlSetParameterName(ExprNode* exprNode, const ValueExprNode* fld_no
if (!exprNode)
return;
const FieldNode* fieldNode = ExprNode::as<FieldNode>(fld_node);
const FieldNode* fieldNode = nodeAs<FieldNode>(fld_node);
fb_assert(fieldNode); // Could it be something else ???
if (fieldNode->nodDesc.dsc_dtype != dtype_array)
@ -8984,7 +9081,7 @@ static void dsqlSetParameterName(ExprNode* exprNode, const ValueExprNode* fld_no
case ExprNode::TYPE_PARAMETER:
{
ParameterNode* paramNode = exprNode->as<ParameterNode>();
ParameterNode* paramNode = nodeAs<ParameterNode>(exprNode);
dsql_par* parameter = paramNode->dsqlParameter;
parameter->par_name = fieldNode->dsqlField->fld_name.c_str();
parameter->par_rel_name = relation->rel_name.c_str();
@ -9005,7 +9102,7 @@ static void dsqlSetParametersName(CompoundStmtNode* statements, const RecordSour
for (NestConst<StmtNode>* const end = ptr + count; ptr != end; ++ptr)
{
AssignmentNode* assign = (*ptr)->as<AssignmentNode>();
AssignmentNode* assign = nodeAs<AssignmentNode>(*ptr);
if (assign)
dsqlSetParameterName(assign->asgnFrom, assign->asgnTo, relation);
@ -9154,7 +9251,7 @@ static StmtNode* pass1ExpandView(thread_db* tdbb, CompilerScratch* csb, StreamTy
const jrd_fld* field = MET_get_field(relation, id);
if (field->fld_source)
newId = field->fld_source->as<FieldNode>()->fieldId;
newId = nodeAs<FieldNode>(field->fld_source)->fieldId;
else
newId = id;
}
@ -9353,13 +9450,13 @@ static void preprocessAssignments(thread_db* tdbb, CompilerScratch* csb,
for (size_t i = compoundNode->statements.getCount(); i--; )
{
const AssignmentNode* assign = compoundNode->statements[i]->as<AssignmentNode>();
const AssignmentNode* assign = nodeAs<AssignmentNode>(compoundNode->statements[i]);
fb_assert(assign);
if (!assign)
continue;
const ExprNode* assignFrom = assign->asgnFrom;
const FieldNode* assignToField = assign->asgnTo->as<FieldNode>();
const FieldNode* assignToField = nodeAs<FieldNode>(assign->asgnTo);
if (assignToField)
{
@ -9374,7 +9471,7 @@ static void preprocessAssignments(thread_db* tdbb, CompilerScratch* csb,
{
if (insertOverride && fld->fld_identity_type.specified)
{
if (insertOverride->specified || !assignFrom->is<DefaultNode>())
if (insertOverride->specified || !nodeIs<DefaultNode>(assignFrom))
identityType = fld->fld_identity_type;
if (*insertOverride == OverrideClause::USER_VALUE)
@ -9386,7 +9483,7 @@ static void preprocessAssignments(thread_db* tdbb, CompilerScratch* csb,
if (fld->fld_computation)
{
if (assignFrom->is<DefaultNode>())
if (nodeIs<DefaultNode>(assignFrom))
compoundNode->statements.remove(i);
}
else if (relation->rel_view_rse && fld->fld_source_rel_field.first.hasData())
@ -9447,7 +9544,7 @@ static void validateExpressions(thread_db* tdbb, const Array<ValidateInfo>& vali
const dsc* desc = EVL_expr(tdbb, request, i->value);
const USHORT length = (desc && !(request->req_flags & req_null)) ?
MOV_make_string(desc, ttype_dynamic, &value, &temp, sizeof(temp) - 1) : 0;
MOV_make_string(tdbb, desc, ttype_dynamic, &value, &temp, sizeof(temp) - 1) : 0;
if (!desc || (request->req_flags & req_null))
value = NULL_STRING_MARK;
@ -9457,7 +9554,7 @@ static void validateExpressions(thread_db* tdbb, const Array<ValidateInfo>& vali
const_cast<char*>(value)[length] = 0; // safe cast - data is actually on the stack
string name;
const FieldNode* fieldNode = i->value->as<FieldNode>();
const FieldNode* fieldNode = nodeAs<FieldNode>(i->value);
if (fieldNode)
{

View File

@ -1556,22 +1556,18 @@ public:
};
// This node should better be session management node,
// but as long as we do not have other session management and
// node is rather similiar internally to transaction management
// let it for now be transaction management node.
class SetRoleNode : public TransactionNode
class SetRoleNode : public SessionManagementNode
{
public:
explicit SetRoleNode(MemoryPool& pool)
: TransactionNode(pool),
: SessionManagementNode(pool),
trusted(true),
roleName(pool)
{
}
SetRoleNode(MemoryPool& pool, Firebird::MetaName* name)
: TransactionNode(pool),
: SessionManagementNode(pool),
trusted(false),
roleName(pool, *name)
{
@ -1580,7 +1576,7 @@ public:
public:
virtual Firebird::string internalPrint(NodePrinter& printer) const
{
TransactionNode::internalPrint(printer);
SessionManagementNode::internalPrint(printer);
NODE_PRINT(printer, trusted);
NODE_PRINT(printer, roleName);
@ -1588,8 +1584,7 @@ public:
return "SetRoleNode";
}
virtual SetRoleNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
virtual void execute(thread_db* tdbb, dsql_req* request, jrd_tra** transaction) const;
virtual void execute(thread_db* tdbb, dsql_req* request) const;
public:
bool trusted;
@ -1597,6 +1592,99 @@ public:
};
class SetSessionNode : public SessionManagementNode
{
public:
enum Type { TYPE_IDLE_TIMEOUT, TYPE_STMT_TIMEOUT };
SetSessionNode(MemoryPool& pool, Type aType, ULONG aVal, UCHAR blr_timepart);
public:
virtual Firebird::string internalPrint(NodePrinter& printer) const;
virtual void execute(thread_db* tdbb, dsql_req* request) const;
private:
Type m_type;
ULONG m_value;
};
class SetRoundNode : public SessionManagementNode
{
public:
SetRoundNode(MemoryPool& pool, Firebird::MetaName* name);
public:
virtual Firebird::string internalPrint(NodePrinter& printer) const
{
SessionManagementNode::internalPrint(printer);
NODE_PRINT(printer, rndMode);
return "SetRoundNode";
}
virtual void execute(thread_db* tdbb, dsql_req* request) const;
public:
USHORT rndMode;
};
class SetTrapsNode : public SessionManagementNode
{
public:
SetTrapsNode(MemoryPool& pool)
: SessionManagementNode(pool),
traps(0u)
{
}
public:
virtual Firebird::string internalPrint(NodePrinter& printer) const
{
SessionManagementNode::internalPrint(printer);
NODE_PRINT(printer, traps);
return "SetTrapsNode";
}
virtual void execute(thread_db* tdbb, dsql_req* request) const;
void trap(Firebird::MetaName* name);
public:
USHORT traps;
};
class SetBindNode : public SessionManagementNode
{
public:
SetBindNode(MemoryPool& pool)
: SessionManagementNode(pool)
{
}
public:
virtual Firebird::string internalPrint(NodePrinter& printer) const
{
SessionManagementNode::internalPrint(printer);
NODE_PRINT(printer, bind.bind);
NODE_PRINT(printer, bind.numScale);
return "SetBindNode";
}
virtual void execute(thread_db* tdbb, dsql_req* request) const;
public:
Firebird::DecimalBinding bind;
};
class UpdateOrInsertNode : public TypedNode<DsqlOnlyStmtNode, StmtNode::TYPE_UPDATE_OR_INSERT>
{
public:

View File

@ -599,7 +599,7 @@ dsc* NthValueWinNode::winPass(thread_db* tdbb, jrd_req* request, SlidingWindow*
if (!desc || (request->req_flags & req_null))
return NULL;
SINT64 records = MOV_get_int64(desc, 0);
SINT64 records = MOV_get_int64(tdbb, desc, 0);
if (records <= 0)
{
status_exception::raise(Arg::Gds(isc_sysf_argnmustbe_positive) <<
@ -607,7 +607,7 @@ dsc* NthValueWinNode::winPass(thread_db* tdbb, jrd_req* request, SlidingWindow*
}
desc = EVL_expr(tdbb, request, from);
const SLONG fromPos = desc ? MOV_get_long(desc, 0) : FROM_FIRST;
const SLONG fromPos = desc ? MOV_get_long(tdbb, desc, 0) : FROM_FIRST;
if (fromPos == FROM_FIRST)
records += -(window->getRecordPosition() - window->getFrameStart()) - 1;
@ -688,7 +688,7 @@ dsc* LagLeadWinNode::winPass(thread_db* tdbb, jrd_req* request, SlidingWindow* w
if (!desc || (request->req_flags & req_null))
return NULL;
SINT64 records = MOV_get_int64(desc, 0);
SINT64 records = MOV_get_int64(tdbb, desc, 0);
if (records < 0)
{
status_exception::raise(Arg::Gds(isc_sysf_argnmustbe_nonneg) <<
@ -850,7 +850,7 @@ void NTileWinNode::aggInit(thread_db* tdbb, jrd_req* request) const
Arg::Num(1) << Arg::Str(aggInfo.name));
}
thisImpure->buckets = MOV_get_int64(desc, 0);
thisImpure->buckets = MOV_get_int64(tdbb, desc, 0);
if (thisImpure->buckets <= 0)
{

View File

@ -57,7 +57,9 @@ const USHORT blr_dtypes[] = {
blr_short, // dtype_array
blr_int64, // dtype_int64
0, // DB_KEY
blr_bool // dtype_boolean
blr_bool, // dtype_boolean
blr_dec64, // dtype_dec64
blr_dec128 // dtype_dec128
};
bool DDL_ids(const Jrd::DsqlCompilerScratch*);

View File

@ -151,7 +151,7 @@ void DSQL_execute(thread_db* tdbb,
if (!*tra_handle &&
statement->getType() != DsqlCompiledStatement::TYPE_START_TRANS &&
statement->getType() != DsqlCompiledStatement::TYPE_SET_SESSION)
statement->getType() != DsqlCompiledStatement::TYPE_SESSION_MANAGEMENT)
{
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-901) <<
Arg::Gds(isc_bad_trans_handle));
@ -548,7 +548,7 @@ void DSQL_execute_immediate(thread_db* tdbb, Jrd::Attachment* attachment, jrd_tr
if (!*tra_handle &&
statement->getType() != DsqlCompiledStatement::TYPE_START_TRANS &&
statement->getType() != DsqlCompiledStatement::TYPE_SET_SESSION)
statement->getType() != DsqlCompiledStatement::TYPE_SESSION_MANAGEMENT)
{
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-901) <<
Arg::Gds(isc_bad_trans_handle));
@ -922,15 +922,7 @@ void DsqlTransactionRequest::execute(thread_db* tdbb, jrd_tra** traHandle,
}
void SetSessionRequest::execute(thread_db* tdbb, jrd_tra** /*traHandle*/,
IMessageMetadata* /*inMetadata*/, const UCHAR* /*inMsg*/,
IMessageMetadata* /*outMetadata*/, UCHAR* /*outMsg*/,
bool /*singleton*/)
{
node->execute(tdbb, this);
}
void SetSessionRequest::dsqlPass(thread_db* tdbb, DsqlCompilerScratch* scratch,
void DsqlSessionManagementRequest::dsqlPass(thread_db* tdbb, DsqlCompilerScratch* scratch,
ntrace_result_t* /*traceResult*/)
{
node = Node::doDsqlPass(scratch, node);
@ -939,6 +931,15 @@ void SetSessionRequest::dsqlPass(thread_db* tdbb, DsqlCompilerScratch* scratch,
req_traced = false;
}
// Execute a dynamic SQL statement.
void DsqlSessionManagementRequest::execute(thread_db* tdbb, jrd_tra** traHandle,
Firebird::IMessageMetadata* inMetadata, const UCHAR* inMsg,
Firebird::IMessageMetadata* outMetadata, UCHAR* outMsg,
bool singleton)
{
node->execute(tdbb, this);
}
/**
@ -1875,8 +1876,6 @@ static void sql_info(thread_db* tdbb,
break;
case DsqlCompiledStatement::TYPE_CREATE_DB:
case DsqlCompiledStatement::TYPE_DDL:
case DsqlCompiledStatement::TYPE_SET_ROLE:
case DsqlCompiledStatement::TYPE_SET_SESSION:
number = isc_info_sql_stmt_ddl;
break;
case DsqlCompiledStatement::TYPE_COMMIT:
@ -1890,6 +1889,9 @@ static void sql_info(thread_db* tdbb,
case DsqlCompiledStatement::TYPE_START_TRANS:
number = isc_info_sql_stmt_start_trans;
break;
case DsqlCompiledStatement::TYPE_SESSION_MANAGEMENT:
number = isc_info_sql_stmt_ddl; // ?????????????????
break;
case DsqlCompiledStatement::TYPE_INSERT:
number = isc_info_sql_stmt_insert;
break;

View File

@ -80,7 +80,7 @@ namespace Jrd
class RseNode;
class StmtNode;
class TransactionNode;
class SetSessionNode;
class SessionManagementNode;
class ValueExprNode;
class ValueListNode;
class WindowClause;
@ -237,6 +237,31 @@ public:
{
}
public:
void setExactPrecision()
{
if (precision != 0)
return;
switch (dtype)
{
case dtype_short:
precision = 4;
break;
case dtype_long:
precision = 9;
break;
case dtype_int64:
precision = 18;
break;
default:
fb_assert(!DTYPE_IS_EXACT(dtype));
}
}
public:
USHORT dtype;
FLD_LENGTH length;
@ -433,7 +458,7 @@ public:
TYPE_SELECT, TYPE_SELECT_UPD, TYPE_INSERT, TYPE_DELETE, TYPE_UPDATE, TYPE_UPDATE_CURSOR,
TYPE_DELETE_CURSOR, TYPE_COMMIT, TYPE_ROLLBACK, TYPE_CREATE_DB, TYPE_DDL, TYPE_START_TRANS,
TYPE_EXEC_PROCEDURE, TYPE_COMMIT_RETAIN, TYPE_ROLLBACK_RETAIN, TYPE_SET_GENERATOR,
TYPE_SAVEPOINT, TYPE_EXEC_BLOCK, TYPE_SELECT_BLOCK, TYPE_SET_ROLE, TYPE_SET_SESSION
TYPE_SAVEPOINT, TYPE_EXEC_BLOCK, TYPE_SELECT_BLOCK, TYPE_SESSION_MANAGEMENT
};
// Statement flags.
@ -686,10 +711,10 @@ private:
NestConst<TransactionNode> node;
};
class SetSessionRequest : public dsql_req
class DsqlSessionManagementRequest : public dsql_req
{
public:
explicit SetSessionRequest(MemoryPool& pool, SetSessionNode* aNode)
explicit DsqlSessionManagementRequest(MemoryPool& pool, SessionManagementNode* aNode)
: dsql_req(pool),
node(aNode)
{
@ -705,7 +730,7 @@ public:
bool singleton);
private:
NestConst<SetSessionNode> node;
NestConst<SessionManagementNode> node;
};
//! Implicit (NATURAL and USING) joins
@ -958,6 +983,23 @@ private:
Firebird::string s;
};
class Lim64String : public Firebird::string
{
public:
Lim64String(Firebird::MemoryPool& p, const Firebird::string& str, int sc)
: Firebird::string(p, str),
scale(sc)
{ }
int getScale()
{
return scale;
}
private:
int scale;
};
} // namespace
/*! \var unsigned DSQL_debug

View File

@ -108,7 +108,7 @@ void GEN_hidden_variables(DsqlCompilerScratch* dsqlScratch)
**/
void GEN_expr(DsqlCompilerScratch* dsqlScratch, ExprNode* node)
{
RseNode* rseNode = node->as<RseNode>();
RseNode* rseNode = nodeAs<RseNode>(node);
if (rseNode)
{
GEN_rse(dsqlScratch, rseNode);
@ -201,6 +201,25 @@ void GEN_port(DsqlCompilerScratch* dsqlScratch, dsql_msg* message)
if (fromCharSet != toCharSet)
parameter->par_desc.setTextType(toCharSet);
}
else if (parameter->par_desc.isDecFloat())
{
const DecimalBinding& b = tdbb->getAttachment()->att_dec_binding;
switch (b.bind)
{
case DecimalBinding::DEC_NATIVE:
break;
case DecimalBinding::DEC_TEXT:
parameter->par_desc.makeText((parameter->par_desc.dsc_dtype == dtype_dec64 ?
IDecFloat16::STRING_SIZE : IDecFloat34::STRING_SIZE) - 1, ttype_ascii);
break;
case DecimalBinding::DEC_DOUBLE:
parameter->par_desc.makeDouble();
break;
case DecimalBinding::DEC_NUMERIC:
parameter->par_desc.makeInt64(b.numScale);
break;
}
}
if (parameter->par_desc.dsc_dtype == dtype_text && parameter->par_index != 0)
{
@ -366,6 +385,14 @@ void GEN_descriptor( DsqlCompilerScratch* dsqlScratch, const dsc* desc, bool tex
dsqlScratch->appendUChar(blr_double);
break;
case dtype_dec64:
dsqlScratch->appendUChar(blr_dec64);
break;
case dtype_dec128:
dsqlScratch->appendUChar(blr_dec128);
break;
case dtype_sql_date:
dsqlScratch->appendUChar(blr_sql_date);
break;
@ -598,7 +625,7 @@ void GEN_sort(DsqlCompilerScratch* dsqlScratch, UCHAR blrVerb, ValueListNode* li
for (const NestConst<ValueExprNode>* const end = list->items.end(); ptr != end; ++ptr)
{
OrderNode* orderNode = (*ptr)->as<OrderNode>();
OrderNode* orderNode = nodeAs<OrderNode>(*ptr);
switch (orderNode->nullsPlacement)
{

View File

@ -118,19 +118,25 @@ ValueExprNode* MAKE_constant(const char* str, dsql_constant_type numeric_flag)
switch (numeric_flag)
{
case CONSTANT_DOUBLE:
case CONSTANT_DECIMAL:
// This is a numeric value which is transported to the engine as
// a string. The engine will convert it. Use dtype_double so that
// the engine can distinguish it from an actual string.
// Note: Due to the size of dsc_scale we are limited to numeric
// constants of less than 256 bytes.
// a string. The engine will convert it. Use dtype_double/dec128
// so that the engine can distinguish it from an actual string.
// Note: Due to the size of dsc_sub_type literal length is limited
// to constants less than 32K - 1 bytes. Not real problem.
literal->litDesc.dsc_dtype = dtype_double;
// Scale has no use for double
literal->litDesc.dsc_scale = static_cast<signed char>(strlen(str));
literal->litDesc.dsc_sub_type = 0;
literal->litDesc.dsc_length = sizeof(double);
literal->litDesc.dsc_address = (UCHAR*) str;
literal->litDesc.dsc_ttype() = ttype_ascii;
{
literal->litDesc.dsc_dtype = numeric_flag == CONSTANT_DOUBLE ? dtype_double : dtype_dec128;
literal->litDesc.dsc_scale = 0;
size_t l = strlen(str);
if (l > MAX_SSHORT)
{
ERRD_post(Arg::Gds(isc_imp_exc) << Arg::Gds(isc_random) << "Numeric literal too long");
}
literal->litDesc.dsc_sub_type = static_cast<SSHORT>(l); // Keep length in sub_type which is unused
literal->litDesc.dsc_length = numeric_flag == CONSTANT_DOUBLE ? sizeof(double) : sizeof(Decimal128);
literal->litDesc.dsc_address = (UCHAR*) str;
}
break;
case CONSTANT_DATE:
@ -169,7 +175,7 @@ ValueExprNode* MAKE_constant(const char* str, dsql_constant_type numeric_flag)
// Now invoke the string_to_date/time/timestamp routines
CVT_move(&tmp, &literal->litDesc, ERRD_post);
CVT_move(&tmp, &literal->litDesc, tdbb->getAttachment()->att_dec_status, ERRD_post);
break;
}

View File

@ -46,6 +46,7 @@ namespace Jrd {
// Parameters to MAKE_constant
enum dsql_constant_type {
CONSTANT_DOUBLE = 1, // stored as a string
CONSTANT_DECIMAL, // stored as a string
CONSTANT_DATE, // stored as a SLONG
CONSTANT_TIME, // stored as a ULONG
CONSTANT_TIMESTAMP, // stored as a QUAD

View File

@ -332,7 +332,8 @@ using namespace Firebird;
%token <metaNamePtr> WORK
%token <metaNamePtr> WRITE
%token <stringPtr> FLOAT_NUMBER
%token <stringPtr> FLOAT_NUMBER DECIMAL_NUMBER LIMIT64_INT
%token <lim64ptr> LIMIT64_NUMBER
%token <metaNamePtr> SYMBOL
%token <int32Val> NUMBER
@ -592,19 +593,25 @@ using namespace Firebird;
// tokens added for Firebird 4.0
%token <metaNamePtr> BINARY
%token <metaNamePtr> BIND
%token <metaNamePtr> COMPARE_DECFLOAT
%token <metaNamePtr> CUME_DIST
%token <metaNamePtr> DECFLOAT
%token <metaNamePtr> DEFINER
%token <metaNamePtr> EXCLUDE
%token <metaNamePtr> FOLLOWING
%token <metaNamePtr> IDLE
%token <metaNamePtr> INVOKER
%token <metaNamePtr> MESSAGE
%token <metaNamePtr> NATIVE
%token <metaNamePtr> NORMALIZE_DECFLOAT
%token <metaNamePtr> NTILE
%token <metaNamePtr> OTHERS
%token <metaNamePtr> OVERRIDING
%token <metaNamePtr> PERCENT_RANK
%token <metaNamePtr> PRECEDING
%token <metaNamePtr> PRIVILEGE
%token <metaNamePtr> QUANTIZE
%token <metaNamePtr> RANGE
%token <metaNamePtr> RDB_ERROR
%token <metaNamePtr> RDB_ROLE_IN_USE
@ -614,6 +621,8 @@ using namespace Firebird;
%token <metaNamePtr> SQL
%token <metaNamePtr> SYSTEM
%token <metaNamePtr> TIES
%token <metaNamePtr> TOTALORDER
%token <metaNamePtr> TRAPS
%token <metaNamePtr> UNBOUNDED
%token <metaNamePtr> VARBINARY
%token <metaNamePtr> WINDOW
@ -673,6 +682,7 @@ using namespace Firebird;
Firebird::QualifiedName* qualifiedNamePtr;
Firebird::string* stringPtr;
Jrd::IntlString* intlStringPtr;
Jrd::Lim64String* lim64ptr;
Jrd::DbFileClause* dbFileClause;
Firebird::Array<NestConst<Jrd::DbFileClause> >* dbFilesClause;
Jrd::ExternalClause* externalClause;
@ -704,6 +714,7 @@ using namespace Firebird;
Jrd::NamedWindowClause* namedWindowClause;
Jrd::NamedWindowsClause* namedWindowsClause;
Jrd::TransactionNode* traNode;
Jrd::SessionManagementNode* mngNode;
Firebird::Array<Jrd::PrivilegeClause>* privilegeArray;
Jrd::GranteeClause* granteeClause;
Firebird::Array<Jrd::GranteeClause>* granteeArray;
@ -762,6 +773,9 @@ using namespace Firebird;
Jrd::SetRoleNode* setRoleNode;
Jrd::SetSessionNode* setSessionNode;
Jrd::CreateAlterRoleNode* createAlterRoleNode;
Jrd::SetRoundNode* setRoundNode;
Jrd::SetTrapsNode* setTrapsNode;
Jrd::SetBindNode* setBindNode;
}
%include types.y
@ -780,7 +794,7 @@ statement
: dml_statement { $$ = newNode<DsqlDmlRequest>($1); }
| ddl_statement { $$ = newNode<DsqlDdlRequest>($1); }
| tra_statement { $$ = newNode<DsqlTransactionRequest>($1); }
| session_statement { $$ = newNode<SetSessionRequest>($1); }
| mng_statement { $$ = newNode<DsqlSessionManagementRequest>($1); }
;
%type <stmtNode> dml_statement
@ -815,6 +829,14 @@ tra_statement
: set_transaction { $$ = $1; }
| commit { $$ = $1; }
| rollback { $$ = $1; }
;
%type <mngNode> mng_statement
mng_statement
: set_round { $$ = $1; }
| set_traps { $$ = $1; }
| set_bind { $$ = $1; }
| session_statement { $$ = $1; }
| set_role { $$ = $1; }
;
@ -1826,6 +1848,10 @@ sequence_value
$$ = -signedNumber;
}
| '-' LIMIT64_INT
{
$$ = MIN_SINT64;
}
;
@ -2349,7 +2375,7 @@ column_constraint($addColumnClause)
const NestConst<ValueExprNode>* ptr = refColumns->items.begin();
for (const NestConst<ValueExprNode>* const end = refColumns->items.end(); ptr != end; ++ptr)
constraint.refColumns.add((*ptr)->as<FieldNode>()->dsqlName);
constraint.refColumns.add(nodeAs<FieldNode>(*ptr)->dsqlName);
}
constraint.index = $5;
@ -2400,7 +2426,7 @@ table_constraint($relationNode)
const NestConst<ValueExprNode>* ptr = columns->items.begin();
for (const NestConst<ValueExprNode>* const end = columns->items.end(); ptr != end; ++ptr)
constraint.columns.add((*ptr)->as<FieldNode>()->dsqlName);
constraint.columns.add(nodeAs<FieldNode>(*ptr)->dsqlName);
constraint.index = $3;
@ -2415,7 +2441,7 @@ table_constraint($relationNode)
const NestConst<ValueExprNode>* ptr = columns->items.begin();
for (const NestConst<ValueExprNode>* const end = columns->items.end(); ptr != end; ++ptr)
constraint.columns.add((*ptr)->as<FieldNode>()->dsqlName);
constraint.columns.add(nodeAs<FieldNode>(*ptr)->dsqlName);
constraint.index = $4;
@ -2431,7 +2457,7 @@ table_constraint($relationNode)
const NestConst<ValueExprNode>* ptr = columns->items.begin();
for (const NestConst<ValueExprNode>* const end = columns->items.end(); ptr != end; ++ptr)
constraint.columns.add((*ptr)->as<FieldNode>()->dsqlName);
constraint.columns.add(nodeAs<FieldNode>(*ptr)->dsqlName);
constraint.refRelation = *$5;
constraint.refAction = $7;
@ -2442,7 +2468,7 @@ table_constraint($relationNode)
const NestConst<ValueExprNode>* ptr = refColumns->items.begin();
for (const NestConst<ValueExprNode>* const end = refColumns->items.end(); ptr != end; ++ptr)
constraint.refColumns.add((*ptr)->as<FieldNode>()->dsqlName);
constraint.refColumns.add(nodeAs<FieldNode>(*ptr)->dsqlName);
}
constraint.index = $8;
@ -3572,78 +3598,45 @@ check_opt
%type <createAlterTriggerNode> trigger_clause
trigger_clause
: symbol_trigger_name trigger_active trigger_type trigger_position trg_sql_security_clause
AS local_declaration_list full_proc_block
: create_trigger_start trg_sql_security_clause AS local_declaration_list full_proc_block
{
$$ = newNode<CreateAlterTriggerNode>(*$1);
$$->active = $2;
$$->type = $3;
$$->position = $4;
$$->ssDefiner = $5;
$$->source = makeParseStr(YYPOSNARG(6), YYPOSNARG(8));
$$->localDeclList = $7;
$$->body = $8;
$$ = $1;
$$->ssDefiner = $2;
$$->source = makeParseStr(YYPOSNARG(3), YYPOSNARG(5));
$$->localDeclList = $4;
$$->body = $5;
}
| symbol_trigger_name trigger_active trigger_type trigger_position
external_clause external_body_clause_opt
| create_trigger_start external_clause external_body_clause_opt
{
$$ = newNode<CreateAlterTriggerNode>(*$1);
$$->active = $2;
$$->type = $3;
$$->position = $4;
$$->external = $5;
if ($6)
$$->source = *$6;
$$ = $1;
$$->external = $2;
if ($3)
$$->source = *$3;
}
| symbol_trigger_name trigger_active trigger_type trigger_position ON symbol_table_name trg_sql_security_clause
AS local_declaration_list full_proc_block
;
%type <createAlterTriggerNode> create_trigger_start
create_trigger_start
: symbol_trigger_name
{ $$ = newNode<CreateAlterTriggerNode>(*$1); }
create_trigger_common(NOTRIAL($2))
{ $$ = $2; }
;
%type create_trigger_common(<createAlterTriggerNode>)
create_trigger_common($trigger)
: trigger_active trigger_type(NOTRIAL($trigger)) trigger_position
{
$$ = newNode<CreateAlterTriggerNode>(*$1);
$$->active = $2;
$$->type = $3;
$$->position = $4;
$$->relationName = *$6;
$$->ssDefiner = $7;
$$->source = makeParseStr(YYPOSNARG(8), YYPOSNARG(10));
$$->localDeclList = $9;
$$->body = $10;
$trigger->active = $1;
$trigger->type = $2;
$trigger->position = $3;
}
| symbol_trigger_name trigger_active trigger_type trigger_position ON symbol_table_name
external_clause external_body_clause_opt
| FOR symbol_table_name trigger_active table_trigger_type trigger_position
{
$$ = newNode<CreateAlterTriggerNode>(*$1);
$$->active = $2;
$$->type = $3;
$$->position = $4;
$$->relationName = *$6;
$$->external = $7;
if ($8)
$$->source = *$8;
}
| symbol_trigger_name FOR symbol_table_name trigger_active trigger_type trigger_position trg_sql_security_clause
AS local_declaration_list full_proc_block
{
$$ = newNode<CreateAlterTriggerNode>(*$1);
$$->active = $4;
$$->type = $5;
$$->position = $6;
$$->relationName = *$3;
$$->ssDefiner = $7;
$$->source = makeParseStr(YYPOSNARG(8), YYPOSNARG(10));
$$->localDeclList = $9;
$$->body = $10;
}
| symbol_trigger_name FOR symbol_table_name trigger_active trigger_type trigger_position
external_clause external_body_clause_opt
{
$$ = newNode<CreateAlterTriggerNode>(*$1);
$$->active = $4;
$$->type = $5;
$$->position = $6;
$$->relationName = *$3;
$$->external = $7;
if ($8)
$$->source = *$8;
$trigger->relationName = *$2;
$trigger->active = $3;
$trigger->type = $4;
$trigger->position = $5;
}
;
@ -3666,11 +3659,22 @@ trigger_active
{ $$ = Nullable<bool>::empty(); }
;
%type <uint64Val> trigger_type
trigger_type
%type <uint64Val> trigger_type(<createAlterTriggerNode>)
trigger_type($trigger)
: table_trigger_type ON symbol_table_name
{
$$ = $1;
$trigger->relationName = *$3;
}
| ON trigger_db_type
{ $$ = $2; }
| trigger_type_prefix trigger_ddl_type
{ $$ = $1 + $2; }
;
%type <uint64Val> table_trigger_type
table_trigger_type
: trigger_type_prefix trigger_type_suffix { $$ = $1 + $2 - 1; }
| ON trigger_db_type { $$ = $2; }
| trigger_type_prefix trigger_ddl_type { $$ = $1 + $2; }
;
%type <uint64Val> trigger_db_type
@ -4466,6 +4470,7 @@ non_charset_simple_type
| binary_character_type
| numeric_type
| float_type
| decfloat_type
| BIGINT
{
$$ = newNode<dsql_fld>();
@ -4733,6 +4738,20 @@ varbinary_character_keyword
// numeric type
%type <legacyField> decfloat_type
decfloat_type
: DECFLOAT '(' signed_long_integer ')'
{
if ($3 != 16 && $3 != 34)
yyabandon(YYPOSNARG(3), -842, isc_decprecision_err); // DecFloat precision must be 16 or 34.
$$ = newNode<dsql_fld>();
$$->precision = $3;
$$->dtype = $3 == 16 ? dtype_dec64 : dtype_dec128;
$$->length = $3 == 16 ? sizeof(Decimal64) : sizeof(Decimal128);
}
;
%type <legacyField> numeric_type
numeric_type
: NUMERIC prec_scale
@ -5017,6 +5036,68 @@ set_role
{ $$ = newNode<SetRoleNode>(); }
;
%type <setRoundNode> set_round
set_round
: SET DECFLOAT ROUND valid_symbol_name
{ $$ = newNode<SetRoundNode>($4); }
;
%type <setTrapsNode> set_traps
set_traps
: SET DECFLOAT TRAPS TO
{ $$ = newNode<SetTrapsNode>(); }
traps_list_opt($5)
{ $$ = $5; }
;
%type <setBindNode> set_bind
set_bind
: SET DECFLOAT BIND
{ $$ = newNode<SetBindNode>(); }
bind_clause($4)
{ $$ = $4; }
;
%type traps_list_opt(<setTrapsNode>)
traps_list_opt($setTrapsNode)
: // nothing
| traps_list($setTrapsNode)
;
%type traps_list(<setTrapsNode>)
traps_list($setTrapsNode)
: trap($setTrapsNode)
| traps_list ',' trap($setTrapsNode)
;
%type trap(<setTrapsNode>)
trap($setTrapsNode)
: valid_symbol_name
{ $setTrapsNode->trap($1); }
;
%type bind_clause(<setBindNode>)
bind_clause($setBindNode)
: NATIVE
// do nothing
| character_keyword
{ $setBindNode->bind.bind = DecimalBinding::DEC_TEXT; }
| DOUBLE PRECISION
{ $setBindNode->bind.bind = DecimalBinding::DEC_DOUBLE; }
| BIGINT scale_clause($setBindNode)
{ $setBindNode->bind.bind = DecimalBinding::DEC_NUMERIC; }
;
%type scale_clause(<setBindNode>)
scale_clause($setBindNode)
: // nothing
| ',' signed_long_integer
{
if ($2 > 18 || $2 < 0)
yyabandon(YYPOSNARG(2), -842, isc_scale_nogt); // Scale must be between 0 and precision
$setBindNode->bind.numScale = -$2;
}
%type <setSessionNode> session_statement
session_statement
: SET SESSION IDLE TIMEOUT long_integer timepart_sesion_idle_tout
@ -5380,7 +5461,7 @@ select_expr_body
{ $$ = $1; }
| select_expr_body UNION distinct_noise query_term
{
UnionSourceNode* node = $1->as<UnionSourceNode>();
UnionSourceNode* node = nodeAs<UnionSourceNode>($1);
if (node && !node->dsqlAll)
node->dsqlClauses->add($4);
else
@ -5392,7 +5473,7 @@ select_expr_body
}
| select_expr_body UNION ALL query_term
{
UnionSourceNode* node = $1->as<UnionSourceNode>();
UnionSourceNode* node = nodeAs<UnionSourceNode>($1);
if (node && node->dsqlAll)
node->dsqlClauses->add($4);
else
@ -7044,16 +7125,30 @@ value_list
%type <valueExprNode> constant
constant
: u_constant
| '-' u_numeric_constant { $$ = newNode<NegateNode>($2); }
| '-' ul_numeric_constant { $$ = newNode<NegateNode>($2); }
| '-' LIMIT64_INT { $$ = MAKE_const_sint64(MIN_SINT64, 0); }
| '-' LIMIT64_NUMBER { $$ = MAKE_const_sint64(MIN_SINT64, $2->getScale()); }
| boolean_literal
;
%type <valueExprNode> u_numeric_constant
u_numeric_constant
: ul_numeric_constant
{ $$ = $1; }
| LIMIT64_NUMBER
{ $$ = MAKE_constant($1->c_str(), CONSTANT_DECIMAL); }
| LIMIT64_INT
{ $$ = MAKE_constant($1->c_str(), CONSTANT_DECIMAL); }
;
%type <valueExprNode> ul_numeric_constant
ul_numeric_constant
: NUMBER
{ $$ = MAKE_const_slong($1); }
| FLOAT_NUMBER
{ $$ = MAKE_constant($1->c_str(), CONSTANT_DOUBLE); }
| DECIMAL_NUMBER
{ $$ = MAKE_constant($1->c_str(), CONSTANT_DECIMAL); }
| NUMBER64BIT
{
SINT64 signedNumber = (SINT64) $1.number;
@ -7586,6 +7681,10 @@ system_function_std_syntax
| TANH
| TRUNC
| UUID_TO_CHAR
| QUANTIZE
| TOTALORDER
| NORMALIZE_DECFLOAT
| COMPARE_DECFLOAT
;
%type <sysFuncCallNode> system_function_special_syntax
@ -7808,10 +7907,10 @@ searched_case
ValueIfNode* last = $2;
ValueIfNode* next;
while ((next = last->falseValue->as<ValueIfNode>()))
while ((next = nodeAs<ValueIfNode>(last->falseValue)))
last = next;
fb_assert(last->falseValue->is<NullNode>());
fb_assert(nodeIs<NullNode>(last->falseValue));
last->falseValue = $4;
$$ = $2;
@ -7828,10 +7927,10 @@ searched_when_clause
ValueIfNode* last = $1;
ValueIfNode* next;
while ((next = last->falseValue->as<ValueIfNode>()))
while ((next = nodeAs<ValueIfNode>(last->falseValue)))
last = next;
fb_assert(last->falseValue->is<NullNode>());
fb_assert(nodeIs<NullNode>(last->falseValue));
last->falseValue = cond;
$$ = $1;
@ -8284,25 +8383,33 @@ non_reserved_word
| SERVERWIDE
| INCREMENT
| TRUSTED
| CUME_DIST // added in FB 4.0
| BIND // added in FB 4.0
| COMPARE_DECFLOAT
| CUME_DIST
| DECFLOAT
| DEFINER
| EXCLUDE
| FOLLOWING
| IDLE
| INVOKER
| MESSAGE
| NATIVE
| NORMALIZE_DECFLOAT
| NTILE
| OTHERS
| OVERRIDING
| PERCENT_RANK
| PRECEDING
| PRIVILEGE
| QUANTIZE
| RANGE
| SECURITY
| SESSION
| SQL
| SYSTEM
| TIES
| TOTALORDER
| TRAPS
| CONSISTENCY
;

View File

@ -351,11 +351,11 @@ dsql_ctx* PASS1_make_context(DsqlCompilerScratch* dsqlScratch, RecordSourceNode*
RelationSourceNode* relNode = NULL;
SelectExprNode* selNode = NULL;
if ((procNode = relationNode->as<ProcedureSourceNode>()))
if ((procNode = nodeAs<ProcedureSourceNode>(relationNode)))
relation_name = procNode->dsqlName.identifier;
else if ((relNode = relationNode->as<RelationSourceNode>()))
else if ((relNode = nodeAs<RelationSourceNode>(relationNode)))
relation_name = relNode->dsqlName;
else if ((selNode = relationNode->as<SelectExprNode>()))
else if ((selNode = nodeAs<SelectExprNode>(relationNode)))
relation_name = selNode->alias.c_str();
SelectExprNode* cte = NULL;
@ -445,11 +445,11 @@ dsql_ctx* PASS1_make_context(DsqlCompilerScratch* dsqlScratch, RecordSourceNode*
// find the context alias name, if it exists.
string str;
if ((procNode = relationNode->as<ProcedureSourceNode>()))
if ((procNode = nodeAs<ProcedureSourceNode>(relationNode)))
str = procNode->alias;
else if ((relNode = relationNode->as<RelationSourceNode>()))
else if ((relNode = nodeAs<RelationSourceNode>(relationNode)))
str = relNode->alias;
else if ((selNode = relationNode->as<SelectExprNode>()))
else if ((selNode = nodeAs<SelectExprNode>(relationNode)))
{
str = selNode->alias;
// ASF: In the case of a UNION contained in a CTE, selNode->querySpec will be a
@ -668,11 +668,11 @@ void PASS1_check_unique_fields_names(StrArray& names, const CompoundStmtNode* fi
const DeclareVariableNode* varNode;
const DeclareCursorNode* cursorNode;
if ((varNode = (*ptr)->as<DeclareVariableNode>()))
if ((varNode = nodeAs<DeclareVariableNode>(*ptr)))
name = varNode->dsqlDef->name.c_str();
else if ((cursorNode = (*ptr)->as<DeclareCursorNode>()))
else if ((cursorNode = nodeAs<DeclareCursorNode>(*ptr)))
name = cursorNode->dsqlName.c_str();
else if ((*ptr)->as<DeclareSubProcNode>() || (*ptr)->as<DeclareSubFuncNode>())
else if (nodeAs<DeclareSubProcNode>(*ptr) || nodeAs<DeclareSubFuncNode>(*ptr))
continue;
fb_assert(name);
@ -796,11 +796,11 @@ bool PASS1_node_match(const ExprNode* node1, const ExprNode* node2, bool ignoreM
if (!node1 || !node2)
return false;
const CastNode* castNode1 = node1->as<CastNode>();
const CastNode* castNode1 = nodeAs<CastNode>(node1);
if (ignoreMapCast && castNode1)
{
const CastNode* castNode2 = node2->as<CastNode>();
const CastNode* castNode2 = nodeAs<CastNode>(node2);
// If node2 is also cast and same type continue with both sources.
if (castNode2 &&
@ -815,11 +815,11 @@ bool PASS1_node_match(const ExprNode* node1, const ExprNode* node2, bool ignoreM
return PASS1_node_match(castNode1->source, node2, ignoreMapCast);
}
const DsqlMapNode* mapNode1 = node1->as<DsqlMapNode>();
const DsqlMapNode* mapNode1 = nodeAs<DsqlMapNode>(node1);
if (ignoreMapCast && mapNode1)
{
const DsqlMapNode* mapNode2 = node2->as<DsqlMapNode>();
const DsqlMapNode* mapNode2 = nodeAs<DsqlMapNode>(node2);
if (mapNode2)
{
@ -832,8 +832,8 @@ bool PASS1_node_match(const ExprNode* node1, const ExprNode* node2, bool ignoreM
return PASS1_node_match(mapNode1->map->map_node, node2, ignoreMapCast);
}
const DsqlAliasNode* aliasNode1 = node1->as<DsqlAliasNode>();
const DsqlAliasNode* aliasNode2 = node2->as<DsqlAliasNode>();
const DsqlAliasNode* aliasNode1 = nodeAs<DsqlAliasNode>(node1);
const DsqlAliasNode* aliasNode2 = nodeAs<DsqlAliasNode>(node2);
// We don't care about the alias itself but only about its field.
if (aliasNode1 || aliasNode2)
@ -850,8 +850,8 @@ bool PASS1_node_match(const ExprNode* node1, const ExprNode* node2, bool ignoreM
// Handle derived fields.
const DerivedFieldNode* derivedField1 = node1->as<DerivedFieldNode>();
const DerivedFieldNode* derivedField2 = node2->as<DerivedFieldNode>();
const DerivedFieldNode* derivedField1 = nodeAs<DerivedFieldNode>(node1);
const DerivedFieldNode* derivedField2 = nodeAs<DerivedFieldNode>(node2);
if (derivedField1 || derivedField2)
{
@ -998,7 +998,7 @@ RseNode* PASS1_derived_table(DsqlCompilerScratch* dsqlScratch, SelectExprNode* i
dsqlScratch->aliasRelationPrefix = pass1_alias_concat(aliasRelationPrefix, alias);
RecordSourceNode* query = input->querySpec;
UnionSourceNode* unionQuery = query->as<UnionSourceNode>();
UnionSourceNode* unionQuery = nodeAs<UnionSourceNode>(query);
RseNode* rse = NULL;
const bool isRecursive = unionQuery && unionQuery->recursive;
USHORT recursive_map_ctx = 0;
@ -1046,7 +1046,7 @@ RseNode* PASS1_derived_table(DsqlCompilerScratch* dsqlScratch, SelectExprNode* i
// the worse thing is that a UNION currently can't be used in
// deciding the JOIN order.
bool foundSubSelect = false;
RseNode* queryNode = query->as<RseNode>();
RseNode* queryNode = nodeAs<RseNode>(query);
if (queryNode)
foundSubSelect = SubSelectFinder::find(queryNode->dsqlSelectList);
@ -1146,7 +1146,7 @@ RseNode* PASS1_derived_table(DsqlCompilerScratch* dsqlScratch, SelectExprNode* i
rse->dsqlSelectList->items[count]);
// Auto-create dummy column name for pass1_any()
if (ignoreColumnChecks && !ExprNode::is<DerivedFieldNode>(select_item))
if (ignoreColumnChecks && !nodeIs<DerivedFieldNode>(select_item))
{
MAKE_desc(dsqlScratch, &select_item->nodDesc, select_item);
@ -1174,7 +1174,7 @@ RseNode* PASS1_derived_table(DsqlCompilerScratch* dsqlScratch, SelectExprNode* i
ValueExprNode* select_item = rse->dsqlSelectList->items[count];
DerivedFieldNode* derivedField;
if ((derivedField = ExprNode::as<DerivedFieldNode>(select_item)))
if ((derivedField = nodeAs<DerivedFieldNode>(select_item)))
derivedField->context = context;
else
{
@ -1190,13 +1190,11 @@ RseNode* PASS1_derived_table(DsqlCompilerScratch* dsqlScratch, SelectExprNode* i
// Check for ambiguous column names inside this derived table.
for (count = 0; count < rse->dsqlSelectList->items.getCount(); ++count)
{
const DerivedFieldNode* selectItem1 =
rse->dsqlSelectList->items[count]->as<DerivedFieldNode>();
const DerivedFieldNode* selectItem1 = nodeAs<DerivedFieldNode>(rse->dsqlSelectList->items[count]);
for (FB_SIZE_T count2 = (count + 1); count2 < rse->dsqlSelectList->items.getCount(); ++count2)
{
const DerivedFieldNode* selectItem2 =
rse->dsqlSelectList->items[count2]->as<DerivedFieldNode>();
const DerivedFieldNode* selectItem2 = nodeAs<DerivedFieldNode>(rse->dsqlSelectList->items[count2]);
if (selectItem1->name == selectItem2->name)
{
@ -1252,10 +1250,10 @@ RseNode* PASS1_derived_table(DsqlCompilerScratch* dsqlScratch, SelectExprNode* i
ValueExprNode* map_item = items->items[0];
DerivedFieldNode* derivedField;
if ((derivedField = ExprNode::as<DerivedFieldNode>(map_item)))
if ((derivedField = nodeAs<DerivedFieldNode>(map_item)))
map_item = derivedField->value;
dsql_ctx* map_context = ExprNode::as<DsqlMapNode>(map_item)->context;
dsql_ctx* map_context = nodeAs<DsqlMapNode>(map_item)->context;
map_context->ctx_flags |= CTX_recursive;
map_context->ctx_recursive = recursive_map_ctx;
@ -1314,7 +1312,7 @@ void PASS1_expand_select_node(DsqlCompilerScratch* dsqlScratch, ExprNode* node,
RelationSourceNode* relNode;
FieldNode* fieldNode;
if ((rseNode = ExprNode::as<RseNode>(node)))
if ((rseNode = nodeAs<RseNode>(node)))
{
ValueListNode* sub_items = rseNode->dsqlSelectList;
@ -1331,7 +1329,7 @@ void PASS1_expand_select_node(DsqlCompilerScratch* dsqlScratch, ExprNode* node,
DerivedFieldNode* derivedField;
if (!(derivedField = select_item->as<DerivedFieldNode>()))
if (!(derivedField = nodeAs<DerivedFieldNode>(select_item)))
{
// Internal dsql error: alias type expected by PASS1_expand_select_node
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) <<
@ -1358,7 +1356,7 @@ void PASS1_expand_select_node(DsqlCompilerScratch* dsqlScratch, ExprNode* node,
}
}
}
else if ((procNode = ExprNode::as<ProcedureSourceNode>(node)))
else if ((procNode = nodeAs<ProcedureSourceNode>(node)))
{
dsql_ctx* context = procNode->dsqlContext;
@ -1378,7 +1376,7 @@ void PASS1_expand_select_node(DsqlCompilerScratch* dsqlScratch, ExprNode* node,
}
}
}
else if ((relNode = ExprNode::as<RelationSourceNode>(node)))
else if ((relNode = nodeAs<RelationSourceNode>(node)))
{
dsql_ctx* context = relNode->dsqlContext;
@ -1398,7 +1396,7 @@ void PASS1_expand_select_node(DsqlCompilerScratch* dsqlScratch, ExprNode* node,
}
}
}
else if ((fieldNode = ExprNode::as<FieldNode>(node)))
else if ((fieldNode = nodeAs<FieldNode>(node)))
{
RecordSourceNode* recSource = NULL;
ValueExprNode* value = fieldNode->internalDsqlPass(dsqlScratch, &recSource);
@ -1455,7 +1453,7 @@ static ValueListNode* pass1_group_by_list(DsqlCompilerScratch* dsqlScratch, Valu
FieldNode* field;
LiteralNode* literal;
if ((field = ExprNode::as<FieldNode>(sub)))
if ((field = nodeAs<FieldNode>(sub)))
{
// check for alias or field node
if (selectList && field->dsqlQualifier.isEmpty() && field->dsqlName.hasData())
@ -1469,7 +1467,7 @@ static ValueListNode* pass1_group_by_list(DsqlCompilerScratch* dsqlScratch, Valu
if (!frnode)
frnode = field->internalDsqlPass(dsqlScratch, NULL);
}
else if ((literal = ExprNode::as<LiteralNode>(sub)) && (literal->litDesc.dsc_dtype == dtype_long))
else if ((literal = nodeAs<LiteralNode>(sub)) && (literal->litDesc.dsc_dtype == dtype_long))
{
const ULONG position = literal->getSlong();
@ -1532,17 +1530,17 @@ ValueExprNode* PASS1_lookup_alias(DsqlCompilerScratch* dsqlScratch, const MetaNa
FieldNode* fieldNode;
DerivedFieldNode* derivedField;
if ((aliasNode = node->as<DsqlAliasNode>()))
if ((aliasNode = nodeAs<DsqlAliasNode>(node)))
{
if (aliasNode->name == name)
matchingNode = node;
}
else if ((fieldNode = node->as<FieldNode>()))
else if ((fieldNode = nodeAs<FieldNode>(node)))
{
if (fieldNode->dsqlField->fld_name == name.c_str())
matchingNode = node;
}
else if ((derivedField = node->as<DerivedFieldNode>()))
else if ((derivedField = nodeAs<DerivedFieldNode>(node)))
{
if (derivedField->name == name)
matchingNode = node;
@ -1559,11 +1557,11 @@ ValueExprNode* PASS1_lookup_alias(DsqlCompilerScratch* dsqlScratch, const MetaNa
TEXT buffer1[256];
buffer1[0] = 0;
if (returnNode->is<DsqlAliasNode>())
if (nodeIs<DsqlAliasNode>(returnNode))
strcat(buffer1, "an alias");
else if (returnNode->is<FieldNode>())
else if (nodeIs<FieldNode>(returnNode))
strcat(buffer1, "a field");
else if (returnNode->is<DerivedFieldNode>())
else if (nodeIs<DerivedFieldNode>(returnNode))
strcat(buffer1, "a derived field");
else
strcat(buffer1, "an item");
@ -1571,11 +1569,11 @@ ValueExprNode* PASS1_lookup_alias(DsqlCompilerScratch* dsqlScratch, const MetaNa
TEXT buffer2[256];
buffer2[0] = 0;
if (matchingNode->is<DsqlAliasNode>())
if (nodeIs<DsqlAliasNode>(matchingNode))
strcat(buffer2, "an alias");
else if (matchingNode->is<FieldNode>())
else if (nodeIs<FieldNode>(matchingNode))
strcat(buffer2, "a field");
else if (matchingNode->is<DerivedFieldNode>())
else if (nodeIs<DerivedFieldNode>(matchingNode))
strcat(buffer2, "a derived field");
else
strcat(buffer2, "an item");
@ -1617,7 +1615,7 @@ static ValueExprNode* pass1_make_derived_field(thread_db* tdbb, DsqlCompilerScra
FieldNode* fieldNode;
DerivedFieldNode* derivedField;
if ((aliasNode = ExprNode::as<DsqlAliasNode>(select_item)))
if ((aliasNode = nodeAs<DsqlAliasNode>(select_item)))
{
// Create a derived field and ignore alias node.
DerivedFieldNode* newField = FB_NEW_POOL(pool) DerivedFieldNode(pool,
@ -1625,25 +1623,25 @@ static ValueExprNode* pass1_make_derived_field(thread_db* tdbb, DsqlCompilerScra
newField->nodDesc = aliasNode->value->nodDesc;
return newField;
}
else if ((subQueryNode = ExprNode::as<SubQueryNode>(select_item)))
else if ((subQueryNode = nodeAs<SubQueryNode>(select_item)))
{
// Try to generate derived field from sub-select
ValueExprNode* derived_field = pass1_make_derived_field(tdbb, dsqlScratch,
subQueryNode->value1);
if ((derivedField = ExprNode::as<DerivedFieldNode>(derived_field)))
if ((derivedField = nodeAs<DerivedFieldNode>(derived_field)))
{
derivedField->value = select_item;
return derived_field;
}
}
else if ((mapNode = ExprNode::as<DsqlMapNode>(select_item)))
else if ((mapNode = nodeAs<DsqlMapNode>(select_item)))
{
// Aggregate's have map on top.
ValueExprNode* derived_field = pass1_make_derived_field(tdbb, dsqlScratch, mapNode->map->map_node);
// If we had succesfully made a derived field node change it with orginal map.
if ((derivedField = ExprNode::as<DerivedFieldNode>(derived_field)))
if ((derivedField = nodeAs<DerivedFieldNode>(derived_field)))
{
derivedField->value = select_item;
derivedField->scope = dsqlScratch->scopeLevel;
@ -1651,7 +1649,7 @@ static ValueExprNode* pass1_make_derived_field(thread_db* tdbb, DsqlCompilerScra
return derived_field;
}
}
else if ((fieldNode = ExprNode::as<FieldNode>(select_item)))
else if ((fieldNode = nodeAs<FieldNode>(select_item)))
{
// Create a derived field and hook in.
@ -1660,7 +1658,7 @@ static ValueExprNode* pass1_make_derived_field(thread_db* tdbb, DsqlCompilerScra
newField->nodDesc = fieldNode->nodDesc;
return newField;
}
else if ((derivedField = ExprNode::as<DerivedFieldNode>(select_item)))
else if ((derivedField = nodeAs<DerivedFieldNode>(select_item)))
{
// Create a derived field that points to a derived field.
@ -1729,7 +1727,7 @@ static RseNode* pass1_rse(DsqlCompilerScratch* dsqlScratch, RecordSourceNode* in
ValueListNode* order, RowsClause* rows, bool updateLock, USHORT flags)
{
string save_alias;
RseNode* rseNode = input->as<RseNode>();
RseNode* rseNode = nodeAs<RseNode>(input);
const bool isRecursive = rseNode && (rseNode->dsqlFlags & RecordSourceNode::DFLAG_RECURSIVE);
AutoSetRestore<USHORT> autoScopeLevel(&dsqlScratch->scopeLevel, dsqlScratch->scopeLevel);
@ -1764,8 +1762,8 @@ static RseNode* pass1_rse_impl(DsqlCompilerScratch* dsqlScratch, RecordSourceNod
thread_db* tdbb = JRD_get_thread_data();
MemoryPool& pool = *tdbb->getDefaultPool();
SelectExprNode* selNode = input->as<SelectExprNode>();
UnionSourceNode* unionNode = input->as<UnionSourceNode>();
SelectExprNode* selNode = nodeAs<SelectExprNode>(input);
UnionSourceNode* unionNode = nodeAs<UnionSourceNode>(input);
if (selNode)
{
@ -1799,7 +1797,7 @@ static RseNode* pass1_rse_impl(DsqlCompilerScratch* dsqlScratch, RecordSourceNod
return pass1_union(dsqlScratch, unionNode, order, rows, updateLock, flags);
}
RseNode* inputRse = input->as<RseNode>();
RseNode* inputRse = nodeAs<RseNode>(input);
fb_assert(inputRse);
// Save the original base of the context stack and process relations
@ -1819,7 +1817,7 @@ static RseNode* pass1_rse_impl(DsqlCompilerScratch* dsqlScratch, RecordSourceNod
if (updateLock &&
(streamList->items.getCount() != 1 ||
!(relNode = streamList->items[0]->as<RelationSourceNode>()) ||
!(relNode = nodeAs<RelationSourceNode>(streamList->items[0])) ||
!(relation = relNode->dsqlContext->ctx_relation) ||
(relation->rel_flags & (REL_view | REL_external))))
{
@ -2308,7 +2306,7 @@ ValueListNode* PASS1_sort(DsqlCompilerScratch* dsqlScratch, ValueListNode* input
for (FB_SIZE_T sortloop = 0; sortloop < input->items.getCount(); ++sortloop)
{
DEV_BLKCHK(input->items[sortloop], dsql_type_nod);
NestConst<OrderNode> node1 = input->items[sortloop]->as<OrderNode>();
NestConst<OrderNode> node1 = nodeAs<OrderNode>(input->items[sortloop]);
if (!node1)
{
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) <<
@ -2320,7 +2318,7 @@ ValueListNode* PASS1_sort(DsqlCompilerScratch* dsqlScratch, ValueListNode* input
// get node of value to be ordered by
NestConst<ValueExprNode> orderValue = node1->value;
NestConst<CollateNode> collateNode = orderValue->as<CollateNode>();
NestConst<CollateNode> collateNode = nodeAs<CollateNode>(orderValue);
if (collateNode)
{
@ -2331,7 +2329,7 @@ ValueListNode* PASS1_sort(DsqlCompilerScratch* dsqlScratch, ValueListNode* input
FieldNode* field;
LiteralNode* literal;
if ((field = orderValue->as<FieldNode>()))
if ((field = nodeAs<FieldNode>(orderValue)))
{
ValueExprNode* aliasNode = NULL;
@ -2346,7 +2344,7 @@ ValueListNode* PASS1_sort(DsqlCompilerScratch* dsqlScratch, ValueListNode* input
orderValue = aliasNode ? aliasNode : field->internalDsqlPass(dsqlScratch, NULL);
}
else if ((literal = orderValue->as<LiteralNode>()) && literal->litDesc.dsc_dtype == dtype_long)
else if ((literal = nodeAs<LiteralNode>(orderValue)) && literal->litDesc.dsc_dtype == dtype_long)
{
const ULONG position = literal->getSlong();
@ -2444,7 +2442,7 @@ static RseNode* pass1_union(DsqlCompilerScratch* dsqlScratch, UnionSourceNode* i
dsqlScratch->scopeLevel--;
if (updateLock)
(*uptr)->as<RseNode>()->flags &= ~RseNode::FLAG_WRITELOCK;
nodeAs<RseNode>(*uptr)->flags &= ~RseNode::FLAG_WRITELOCK;
while (*(dsqlScratch->context) != base)
dsqlScratch->unionContext.push(dsqlScratch->context->pop());
@ -2457,14 +2455,14 @@ static RseNode* pass1_union(DsqlCompilerScratch* dsqlScratch, UnionSourceNode* i
} // end scope block
// generate the list of fields to select.
ValueListNode* items = unionSource->dsqlClauses->items[0]->as<RseNode>()->dsqlSelectList;
ValueListNode* items = nodeAs<RseNode>(unionSource->dsqlClauses->items[0])->dsqlSelectList;
// loop through the list nodes, checking to be sure that they have the
// same number of items
for (FB_SIZE_T i = 1; i < unionSource->dsqlClauses->items.getCount(); ++i)
{
const ValueListNode* nod1 = unionSource->dsqlClauses->items[i]->as<RseNode>()->dsqlSelectList;
const ValueListNode* nod1 = nodeAs<RseNode>(unionSource->dsqlClauses->items[i])->dsqlSelectList;
if (items->items.getCount() != nod1->items.getCount())
{
@ -2495,7 +2493,7 @@ static RseNode* pass1_union(DsqlCompilerScratch* dsqlScratch, UnionSourceNode* i
{
for (FB_SIZE_T i = 0; i < unionSource->dsqlClauses->items.getCount(); ++i)
{
ValueListNode* nod1 = unionSource->dsqlClauses->items[i]->as<RseNode>()->dsqlSelectList;
ValueListNode* nod1 = nodeAs<RseNode>(unionSource->dsqlClauses->items[i])->dsqlSelectList;
MAKE_desc(dsqlScratch, &nod1->items[j]->nodDesc, nod1->items[j]);
tmp_list->items[i] = nod1->items[j];
@ -2520,7 +2518,7 @@ static RseNode* pass1_union(DsqlCompilerScratch* dsqlScratch, UnionSourceNode* i
pass1_union_auto_cast(dsqlScratch, unionSource->dsqlClauses, desc, j);
}
items = unionSource->dsqlClauses->items[0]->as<RseNode>()->dsqlSelectList;
items = nodeAs<RseNode>(unionSource->dsqlClauses->items[0])->dsqlSelectList;
// Create mappings for union.
@ -2559,14 +2557,14 @@ static RseNode* pass1_union(DsqlCompilerScratch* dsqlScratch, UnionSourceNode* i
ptr != end;
++ptr, ++uptr)
{
OrderNode* order1 = (*ptr)->as<OrderNode>();
OrderNode* order1 = nodeAs<OrderNode>(*ptr);
const ValueExprNode* position = order1->value;
const CollateNode* collateNode = position->as<CollateNode>();
const CollateNode* collateNode = nodeAs<CollateNode>(position);
if (collateNode)
position = collateNode->arg;
const LiteralNode* literal = position->as<LiteralNode>();
const LiteralNode* literal = nodeAs<LiteralNode>(position);
if (!literal || literal->litDesc.dsc_dtype != dtype_long)
{
@ -2645,26 +2643,26 @@ static void pass1_union_auto_cast(DsqlCompilerScratch* dsqlScratch, ExprNode* in
RseNode* rseNode;
UnionSourceNode* unionNode;
if ((recSourceList = input->as<RecSourceListNode>()))
if ((recSourceList = nodeAs<RecSourceListNode>(input)))
{
NestConst<RecordSourceNode>* ptr = recSourceList->items.begin();
for (const NestConst<RecordSourceNode>* const end = recSourceList->items.end(); ptr != end; ++ptr)
pass1_union_auto_cast(dsqlScratch, *ptr, desc, position);
}
else if ((rseNode = input->as<RseNode>()) && !rseNode->dsqlExplicitJoin &&
else if ((rseNode = nodeAs<RseNode>(input)) && !rseNode->dsqlExplicitJoin &&
!rseNode->dsqlContext) // not derived table
{
pass1_union_auto_cast(dsqlScratch, rseNode->dsqlStreams, desc, position);
if (rseNode->dsqlStreams->items.getCount() == 1 &&
(unionNode = rseNode->dsqlStreams->items[0]->as<UnionSourceNode>()) &&
(unionNode = nodeAs<UnionSourceNode>(rseNode->dsqlStreams->items[0])) &&
unionNode->dsqlParentRse == rseNode)
{
// We're now in a UNION under a UNION so don't change the existing mappings.
// Only replace the node where the map points to, because they could be changed.
ValueListNode* sub_rse_items =
unionNode->dsqlClauses->items[0]->as<RseNode>()->dsqlSelectList;
dsql_map* map = rseNode->dsqlSelectList->items[position]->as<DsqlMapNode>()->map;
nodeAs<RseNode>(unionNode->dsqlClauses->items[0])->dsqlSelectList;
dsql_map* map = nodeAs<DsqlMapNode>(rseNode->dsqlSelectList->items[position])->map;
map->map_node = sub_rse_items->items[position];
rseNode->dsqlSelectList->items[position]->nodDesc = desc;
}
@ -2697,15 +2695,15 @@ static void pass1_union_auto_cast(DsqlCompilerScratch* dsqlScratch, ExprNode* in
DerivedFieldNode* derivedField;
// Pick a existing cast if available else make a new one.
if ((aliasNode = ExprNode::as<DsqlAliasNode>(select_item)) &&
aliasNode->value && (castNode = aliasNode->value->as<CastNode>()))
if ((aliasNode = nodeAs<DsqlAliasNode>(select_item)) &&
aliasNode->value && (castNode = nodeAs<CastNode>(aliasNode->value)))
{
}
else if ((derivedField = ExprNode::as<DerivedFieldNode>(select_item)) &&
(castNode = derivedField->value->as<CastNode>()))
else if ((derivedField = nodeAs<DerivedFieldNode>(select_item)) &&
(castNode = nodeAs<CastNode>(derivedField->value)))
{
}
else if ((castNode = ExprNode::as<CastNode>(select_item)))
else if ((castNode = nodeAs<CastNode>(select_item)))
{
}
else
@ -2719,9 +2717,9 @@ static void pass1_union_auto_cast(DsqlCompilerScratch* dsqlScratch, ExprNode* in
// We want to leave the ALIAS node on his place, because a UNION
// uses the select_items from the first sub-rse to determine the
// columnname.
if ((aliasNode = ExprNode::as<DsqlAliasNode>(select_item)))
if ((aliasNode = nodeAs<DsqlAliasNode>(select_item)))
castNode->source = aliasNode->value;
else if ((derivedField = ExprNode::as<DerivedFieldNode>(select_item)))
else if ((derivedField = nodeAs<DerivedFieldNode>(select_item)))
castNode->source = derivedField->value;
else
castNode->source = select_item;
@ -2731,7 +2729,7 @@ static void pass1_union_auto_cast(DsqlCompilerScratch* dsqlScratch, ExprNode* in
const ValueExprNode* name_node = select_item;
const DsqlMapNode* mapNode;
while ((mapNode = ExprNode::as<DsqlMapNode>(name_node)))
while ((mapNode = nodeAs<DsqlMapNode>(name_node)))
{
// Skip all the DsqlMapNodes.
name_node = mapNode->map->map_node;
@ -2739,7 +2737,7 @@ static void pass1_union_auto_cast(DsqlCompilerScratch* dsqlScratch, ExprNode* in
const FieldNode* fieldNode;
if ((fieldNode = ExprNode::as<FieldNode>(name_node)))
if ((fieldNode = nodeAs<FieldNode>(name_node)))
{
// Create new node for alias and copy fieldname.
newAliasNode = FB_NEW_POOL(*tdbb->getDefaultPool()) DsqlAliasNode(
@ -2776,13 +2774,13 @@ static void pass1_union_auto_cast(DsqlCompilerScratch* dsqlScratch, ExprNode* in
if (select_item->nodDesc.dsc_flags & DSC_nullable)
castNode->nodDesc.dsc_flags |= DSC_nullable;
if ((aliasNode = ExprNode::as<DsqlAliasNode>(select_item)))
if ((aliasNode = nodeAs<DsqlAliasNode>(select_item)))
{
aliasNode->value = castNode;
aliasNode->value->nodDesc = desc;
select_item->nodDesc = desc;
}
else if ((derivedField = ExprNode::as<DerivedFieldNode>(select_item)))
else if ((derivedField = nodeAs<DerivedFieldNode>(select_item)))
{
derivedField->value = castNode;
derivedField->value->nodDesc = desc;
@ -2805,7 +2803,7 @@ static void pass1_union_auto_cast(DsqlCompilerScratch* dsqlScratch, ExprNode* in
}
}
}
else if ((unionNode = input->as<UnionSourceNode>()))
else if ((unionNode = nodeAs<UnionSourceNode>(input)))
{
recSourceList = unionNode->dsqlClauses;
@ -2884,28 +2882,28 @@ static void remap_streams_to_parent_context(ExprNode* input, dsql_ctx* parent_co
RseNode* rseNode;
UnionSourceNode* unionNode;
if ((listNode = input->as<RecSourceListNode>()))
if ((listNode = nodeAs<RecSourceListNode>(input)))
{
NestConst<RecordSourceNode>* ptr = listNode->items.begin();
for (const NestConst<RecordSourceNode>* const end = listNode->items.end(); ptr != end; ++ptr)
remap_streams_to_parent_context(*ptr, parent_context);
}
else if ((procNode = input->as<ProcedureSourceNode>()))
else if ((procNode = nodeAs<ProcedureSourceNode>(input)))
{
DEV_BLKCHK(procNode->dsqlContext, dsql_type_ctx);
procNode->dsqlContext->ctx_parent = parent_context;
}
else if ((relNode = input->as<RelationSourceNode>()))
else if ((relNode = nodeAs<RelationSourceNode>(input)))
{
DEV_BLKCHK(relNode->dsqlContext, dsql_type_ctx);
relNode->dsqlContext->ctx_parent = parent_context;
}
else if ((rseNode = input->as<RseNode>()))
else if ((rseNode = nodeAs<RseNode>(input)))
remap_streams_to_parent_context(rseNode->dsqlStreams, parent_context);
else if ((unionNode = input->as<UnionSourceNode>()))
else if ((unionNode = nodeAs<UnionSourceNode>(input)))
remap_streams_to_parent_context(unionNode->dsqlClauses, parent_context);
else
fb_assert(input->as<AggregateSourceNode>());
fb_assert(nodeAs<AggregateSourceNode>(input));
}

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