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:
parent
c34a914553
commit
bdc7bd8d3e
1
.gitignore
vendored
1
.gitignore
vendored
@ -17,3 +17,4 @@ libtool
|
||||
*.tmp
|
||||
src/dsql/parse.cpp
|
||||
.vscode/.browse.VC.db
|
||||
extern/decNumber/libdecFloat.a
|
||||
|
148
CHANGELOG.md
148
CHANGELOG.md
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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`
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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))
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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" />
|
||||
|
@ -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>
|
10
configure.ac
10
configure.ac
@ -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
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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);
|
||||
|
2
extern/cloop/src/tests/test1/CTest.c
vendored
2
extern/cloop/src/tests/test1/CTest.c
vendored
@ -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
2
extern/decNumber/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
temp/
|
||||
lib/
|
45
extern/decNumber/ICU-license.html
vendored
Normal file
45
extern/decNumber/ICU-license.html
vendored
Normal 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
11
extern/decNumber/Makefile
vendored
Normal 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
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
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
437
extern/decNumber/decContext.c
vendored
Normal 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
254
extern/decNumber/decContext.h
vendored
Normal 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
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
140
extern/decNumber/decDouble.c
vendored
Normal 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
155
extern/decNumber/decDouble.h
vendored
Normal 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
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
182
extern/decNumber/decNumber.h
vendored
Normal 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
757
extern/decNumber/decNumberLocal.h
vendored
Normal 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
220
extern/decNumber/decPacked.c
vendored
Normal 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
52
extern/decNumber/decPacked.h
vendored
Normal 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
135
extern/decNumber/decQuad.c
vendored
Normal 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
177
extern/decNumber/decQuad.h
vendored
Normal 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
71
extern/decNumber/decSingle.c
vendored
Normal 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
86
extern/decNumber/decSingle.h
vendored
Normal 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
553
extern/decNumber/decimal128.c
vendored
Normal 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
81
extern/decNumber/decimal128.h
vendored
Normal 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
476
extern/decNumber/decimal32.c
vendored
Normal 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
81
extern/decNumber/decimal32.h
vendored
Normal 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
839
extern/decNumber/decimal64.c
vendored
Normal 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
83
extern/decNumber/decimal64.h
vendored
Normal 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
BIN
extern/decNumber/decnumber.pdf
vendored
Normal file
Binary file not shown.
28
extern/decNumber/msvc/decNumber_MSVC12.sln
vendored
Normal file
28
extern/decNumber/msvc/decNumber_MSVC12.sln
vendored
Normal 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
|
267
extern/decNumber/msvc/decNumber_MSVC12.vcxproj
vendored
Normal file
267
extern/decNumber/msvc/decNumber_MSVC12.vcxproj
vendored
Normal 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>
|
84
extern/decNumber/msvc/decNumber_MSVC12.vcxproj.filters
vendored
Normal file
84
extern/decNumber/msvc/decNumber_MSVC12.vcxproj.filters
vendored
Normal 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
81
extern/decNumber/readme.txt
vendored
Normal 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)
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
|
@ -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())
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
986
src/common/DecFloat.cpp
Normal 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
195
src/common/DecFloat.h
Normal 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
|
@ -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)
|
||||
{
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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) <<
|
||||
|
@ -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();
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
/**************************************
|
||||
|
@ -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*);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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*);
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
275
src/dsql/parse.y
275
src/dsql/parse.y
@ -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
|
||||
;
|
||||
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user