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

Decimal floating point numbers - first draft

This commit is contained in:
AlexPeshkoff 2016-11-11 17:59:55 +03:00
parent 05c3ccc6cf
commit 5aede150e3
114 changed files with 23121 additions and 847 deletions

View File

@ -66,7 +66,7 @@ else
GCC=gcc
endif
.PHONY: master_process cross_process firebird Debug Release extern
.PHONY: master_process cross_process firebird Debug Release external
all: firebird
@ -130,10 +130,13 @@ $(GEN_ROOT)/Make.Version : $(SRC_ROOT)/misc/writeBuildNum.sh
# build external software
#
extern:
external:
$(MAKE) -C $(ROOT)/extern/btyacc
$(MAKE) -C $(ROOT)/extern/cloop TARGET=release WITH_FPC=0 BUILD_DIR=$(TMP_ROOT)/cloop OUT_DIR=$(GEN_ROOT)/$(TARGET)/cloop
$(MAKE) -C $(ROOT)/extern/decNumber
ln -sf $(ROOT)/extern/decNumber/libdecFloat.a $(LIB)
ifeq ($(TOMBUILD_FLG),Y)
CFLAGS="$(CFLAGS)" $(MAKE) -C $(ROOT)/extern/libtommath -f makefile.shared GCC=$(GCC)
ln -sf $(TOMMATH_SO).$(TOMMATH_VER) $(LIB)
@ -180,7 +183,7 @@ master_process:
ln -sf $(SRC_ROOT)/include/gen/autoconfig.auto $(SRC_ROOT)/include/gen/autoconfig.h
$(MAKE) updateBuildNum
$(MAKE) export_lists
$(MAKE) extern
$(MAKE) external
$(MAKE) updateCloopInterfaces
$(MAKE) boot
$(MAKE) yvalve
@ -215,7 +218,7 @@ cross1:
ln -sf $(SRC_ROOT)/include/gen/autoconfig.auto $(SRC_ROOT)/include/gen/autoconfig.h
$(MAKE) updateBuildNum
$(MAKE) export_lists
$(MAKE) extern
$(MAKE) external
$(MAKE) updateCloopInterfaces
$(MAKE) boot
$(MAKE) yvalve

View File

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

View File

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

View File

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

View File

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

View File

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

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

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

3908
extern/decNumber/decBasic.c vendored Normal file

File diff suppressed because it is too large Load Diff

1835
extern/decNumber/decCommon.c vendored Normal file

File diff suppressed because it is too large Load Diff

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

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

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

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

1185
extern/decNumber/decDPD.h vendored Normal file

File diff suppressed because it is too large Load Diff

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

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

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

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

8141
extern/decNumber/decNumber.c vendored Normal file

File diff suppressed because it is too large Load Diff

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

BIN
extern/decNumber/decnumber.pdf vendored Normal file

Binary file not shown.

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

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

View File

@ -1664,6 +1664,8 @@ C --
PARAMETER (GDS__dsql_window_duplicate = 335545125)
INTEGER*4 GDS__sql_too_long
PARAMETER (GDS__sql_too_long = 335545126)
INTEGER*4 GDS__decprecision_err
PARAMETER (GDS__decprecision_err = 335545127)
INTEGER*4 GDS__gfix_db_name
PARAMETER (GDS__gfix_db_name = 335740929)
INTEGER*4 GDS__gfix_invalid_sw

View File

@ -1659,6 +1659,8 @@ const
gds_dsql_window_duplicate = 335545125;
isc_sql_too_long = 335545126;
gds_sql_too_long = 335545126;
isc_decprecision_err = 335545127;
gds_decprecision_err = 335545127;
isc_gfix_db_name = 335740929;
gds_gfix_db_name = 335740929;
isc_gfix_invalid_sw = 335740930;

View File

@ -1618,6 +1618,12 @@ 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

View File

@ -157,6 +157,16 @@ ULONG CAN_encode_decode(burp_rel* relation, lstring* buffer, UCHAR* data, bool_t
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;
case dtype_timestamp:
if (!xdr_long(xdrs, &((SLONG*) p)[0]))
return FALSE;

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

@ -0,0 +1,577 @@
/*
* 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 {
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()
{
// Typically excptions 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;
for (USHORT mask = 1; mask; mask <<= 1)
{
if (mask & unmaskedExceptions)
{
decContextRestoreStatus(this, mask, ~0);
const char* statusString = decContextStatusToString(this);
(Arg::Gds(isc_random) << "DecFloat error" <<
Arg::Gds(isc_random) << statusString).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));
} // anonymous namespace
namespace Firebird {
void Decimal64::setScale(DecimalStatus decSt, int scale)
{
if (scale)
{
DecimalContext context(this, decSt);
scale += decDoubleGetExponent(&dec);
decDoubleSetExponent(&dec, &context, scale);
}
}
Decimal64 Decimal64::set(int 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[DECDOUBLE_String];
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(DECDOUBLE_String);
toString(DecimalStatus(0), to.length(), to.begin()); // provide long enough string, i.e. no traps
to.recalculate_length();
}
SCHAR* Decimal64::getBytes()
{
return reinterpret_cast<SCHAR*>(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_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;
}
#ifdef DEV_BUILD
int Decimal64::show()
{
decDoubleShow(&dec, "");
return 0;
}
#endif
Decimal64 Decimal64::neg() const
{
Decimal64 rc;
decDoubleCopyNegate(&rc.dec, &dec);
return rc;
}
Decimal128 Decimal128::set(Decimal64 d64)
{
decDoubleToWider(&d64.dec, &dec);
return *this;
}
Decimal128 Decimal128::set(int 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[DECQUAD_String];
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(DECQUAD_String);
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[DECQUAD_String];
memset(s, 0, sizeof(s));
decQuadToString(&dec, s);
return atof(s);
}
return 0.0;
}
SINT64 Decimal128::toInt64(DecimalStatus decSt, int scale) const
{
Decimal128 wrk(*this);
wrk.setScale(decSt, -scale);
DecimalContext context(this, decSt);
decQuad pow2_32, div, rem;
decQuadFromString(&pow2_32, "4294967296", &context);
decQuadDivideInteger(&div, &wrk.dec, &pow2_32, &context);
decQuadRemainder(&rem, &wrk.dec, &pow2_32, &context);
SINT64 high = decQuadToInt32(&div, &context, DEC_ROUND_DOWN);
high <<= 32;
return high + decQuadToInt32(&rem, &context, DEC_ROUND_DOWN);
}
SCHAR* Decimal128::getBytes()
{
return reinterpret_cast<SCHAR*>(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_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;
}
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;
}
} // namespace Firebird

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

@ -0,0 +1,152 @@
/*
* 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;
};
class Decimal64
{
friend class Decimal128;
public:
Decimal64 set(int 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);
SCHAR* getBytes(); // Use of SCHAR* is XDR requirement
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;
#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);
Decimal128 set(int 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;
SCHAR* getBytes(); // Use of SCHAR* is XDR requirement
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;
#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(int value)
{
set(value, DecimalStatus(0), 0);
}
};
} // namespace Firebird
#endif // FB_DYNAMIC_STRINGS

View File

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

View File

@ -137,6 +137,7 @@ enum EXPECT_DATETIME
static void datetime_to_text(const dsc*, dsc*, Callbacks*);
static void float_to_text(const dsc*, dsc*, Callbacks*);
static void decimal_float_to_text(const dsc*, dsc*, DecimalStatus, Callbacks*);
static void integer_to_text(const dsc*, dsc*, Callbacks*);
static void string_to_datetime(const dsc*, GDS_TIMESTAMP*, const EXPECT_DATETIME, ErrorFunction);
static SINT64 hex_to_value(const char*& string, const char* end);
@ -296,7 +297,38 @@ static void float_to_text(const dsc* from, dsc* to, Callbacks* cb)
intermediate.dsc_length = chars_printed - 1;
}
CVT_move_common(&intermediate, to, cb);
CVT_move_common(&intermediate, to, 0, cb);
}
static void decimal_float_to_text(const dsc* from, dsc* to, DecimalStatus decSt, Callbacks* cb)
{
char temp[50];
try
{
Decimal128 d;
if (from->dsc_dtype == dtype_dec64)
d = *((Decimal64*)from->dsc_address);
else
d = *((Decimal128*)from->dsc_address);
d.toString(decSt, sizeof(temp), temp);
}
catch(const Exception& ex)
{
// reraise using function passed in callbacks
Arg::StatusVector v(ex);
cb->err(v);
}
dsc intermediate;
intermediate.dsc_dtype = dtype_text;
intermediate.dsc_ttype() = ttype_ascii;
intermediate.dsc_address = reinterpret_cast<UCHAR*>(temp);
intermediate.dsc_length = strlen(temp);
CVT_move_common(&intermediate, to, 0, cb);
}
@ -343,7 +375,7 @@ static void integer_to_text(const dsc* from, dsc* to, Callbacks* cb)
intermediate.dsc_scale = scale;
intermediate.dsc_address = (UCHAR*) &n;
CVT_move_common(from, &intermediate, cb);
CVT_move_common(from, &intermediate, 0, cb);
// Check for negation, then convert the number to a string of digits
@ -528,7 +560,7 @@ static void string_to_datetime(const dsc* desc,
VaryStr<100> buffer; // arbitrarily large
const char* p = NULL;
const USHORT length = CVT_make_string(desc, ttype_ascii, &p, &buffer, sizeof(buffer), err);
const USHORT length = CVT_make_string(desc, ttype_ascii, &p, &buffer, sizeof(buffer), 0, err);
const char* const end = p + length;
@ -862,7 +894,7 @@ static void string_to_datetime(const dsc* desc,
}
SLONG CVT_get_long(const dsc* desc, SSHORT scale, ErrorFunction err)
SLONG CVT_get_long(const dsc* desc, SSHORT scale, DecimalStatus decSt, ErrorFunction err)
{
/**************************************
*
@ -878,6 +910,7 @@ SLONG CVT_get_long(const dsc* desc, SSHORT scale, ErrorFunction err)
SLONG value, high;
double d, eps;
Decimal128 d128;
SINT64 val64;
VaryStr<50> buffer; // long enough to represent largest long in ASCII
@ -940,6 +973,15 @@ SLONG CVT_get_long(const dsc* desc, SSHORT scale, ErrorFunction err)
err(Arg::Gds(isc_arith_except) << Arg::Gds(isc_numeric_out_of_range));
break;
case dtype_dec64:
case dtype_dec128:
if (desc->dsc_dtype == dtype_dec64)
d128 = *((Decimal64*) p);
else
d128 = *((Decimal128*) p);
return d128.toInteger(decSt, scale);
case dtype_real:
case dtype_double:
if (desc->dsc_dtype == dtype_real)
@ -986,7 +1028,7 @@ SLONG CVT_get_long(const dsc* desc, SSHORT scale, ErrorFunction err)
case dtype_text:
{
USHORT length =
CVT_make_string(desc, ttype_ascii, &p, &buffer, sizeof(buffer), err);
CVT_make_string(desc, ttype_ascii, &p, &buffer, sizeof(buffer), decSt, err);
scale -= CVT_decompose(p, length, dtype_long, &value, err);
}
break;
@ -1054,7 +1096,7 @@ bool CVT_get_boolean(const dsc* desc, ErrorFunction err)
{
VaryStr<100> buffer; // arbitrarily large
const char* p = NULL;
int len = CVT_make_string(desc, ttype_ascii, &p, &buffer, sizeof(buffer), err);
int len = CVT_make_string(desc, ttype_ascii, &p, &buffer, sizeof(buffer), 0, err);
// Remove heading and trailing spaces.
@ -1082,7 +1124,7 @@ bool CVT_get_boolean(const dsc* desc, ErrorFunction err)
}
double CVT_get_double(const dsc* desc, ErrorFunction err)
double CVT_get_double(const dsc* desc, DecimalStatus decSt, ErrorFunction err)
{
/**************************************
*
@ -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;
@ -1308,7 +1362,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 +1445,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 +1480,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 +1515,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 +1608,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 +1704,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 +1725,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, 0, cb);
return;
}
@ -1695,7 +1760,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, 0, cb->err);
// TMN: Here we should really have the following fb_assert
// fb_assert(lval <= MAX_SSHORT);
*(SSHORT*) p = (SSHORT) lval;
@ -1705,11 +1770,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, 0, 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, 0, cb->err);
return;
case dtype_quad:
@ -1719,12 +1784,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, 0, cb->err);
return;
case dtype_real:
{
double d_value = CVT_get_double(from, cb->err);
double d_value = CVT_get_double(from, 0, 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 +1801,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, 0, cb);
if (len == to->dsc_length)
{
@ -1751,14 +1816,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 +1852,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 +1907,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 +2050,7 @@ 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);
}
@ -1984,6 +2059,7 @@ USHORT CVT_make_string(const dsc* desc,
const char** address,
vary* temp,
USHORT length,
DecimalStatus decSt,
ErrorFunction err)
{
/**************************************
@ -2035,7 +2111,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 +2381,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 +2447,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 +2455,178 @@ 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<50> 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_string(desc, ttype_ascii, &p, &buffer, sizeof(buffer) - 1, 0, err);
buffer.vary_string[buffer.vary_length] = 0;
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 6 4
*
**************************************
*
* Functional description
* Convert something arbitrary to a DecFloat(34) / (128 bit).
*
**************************************/
VaryStr<50> buffer; // long enough to represent largest decimal float 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_string(desc, ttype_ascii, &p, &buffer, sizeof(buffer) - 1, 0, err);
buffer.vary_string[buffer.vary_length] = 0;
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_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 +2672,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 +2680,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), 0, err);
scale -= CVT_decompose(p, length, dtype_quad, &value.gds_quad_high, err);
}
break;
@ -2452,6 +2695,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 +2718,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 +2760,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 +2816,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 +2985,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 +3012,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 +3029,5 @@ void CVT_move(const dsc* from, dsc* to, ErrorFunction err)
*
**************************************/
CommonCallbacks callbacks(err);
CVT_move_common(from, to, &callbacks);
CVT_move_common(from, to, decSt, &callbacks);
}

View File

@ -29,6 +29,8 @@
#ifndef COMMON_CVT_H
#define COMMON_CVT_H
#include "../common/DecFloat.h"
namespace Jrd {
class CharSet;
@ -70,16 +72,18 @@ 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);
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_move_common(const dsc*, dsc*, Firebird::DecimalStatus, Firebird::Callbacks*);
void CVT_move(const dsc*, dsc*, Firebird::DecimalStatus, ErrorFunction);
SSHORT CVT_decompose(const char*, USHORT, SSHORT, SLONG*, ErrorFunction);
USHORT CVT_get_string_ptr(const dsc*, USHORT*, UCHAR**, vary*, USHORT, ErrorFunction);
USHORT CVT_get_string_ptr_common(const dsc*, USHORT*, UCHAR**, vary*, USHORT, Firebird::Callbacks*);
SINT64 CVT_get_int64(const dsc*, SSHORT, ErrorFunction);
SQUAD CVT_get_quad(const dsc*, SSHORT, ErrorFunction);
USHORT CVT_get_string_ptr(const dsc*, USHORT*, UCHAR**, vary*, USHORT, Firebird::DecimalStatus, ErrorFunction);
USHORT CVT_get_string_ptr_common(const dsc*, USHORT*, UCHAR**, vary*, USHORT, Firebird::DecimalStatus, Firebird::Callbacks*);
SINT64 CVT_get_int64(const dsc*, SSHORT, Firebird::DecimalStatus, ErrorFunction);
SQUAD CVT_get_quad(const dsc*, SSHORT, Firebird::DecimalStatus, ErrorFunction);
#endif //COMMON_CVT_H

View File

@ -64,7 +64,9 @@ static const USHORT _DSC_convert_to_text_length[DTYPE_TYPE_MAX] =
9, // dtype_array FFFF:FFFF
20, // dtype_int64 -9223372036854775808
0, // dtype_dbkey
5 // dtype_boolean
5, // dtype_boolean
23, // dtype_dec64 1 + 1 + 1 + 1 + 16(34) + 3(4)
42 // dtype_dec128 +- . e +- coeff + exp
};
// blr to dsc type conversions
@ -89,7 +91,9 @@ static const USHORT DSC_blr_type_mapping[] =
blr_blob,
blr_int64,
blr_null,
blr_bool
blr_bool,
blr_dec64,
blr_dec128
};
// Unimplemented names are in lowercase & <brackets>
@ -117,7 +121,9 @@ static const TEXT* const DSC_dtype_names[] =
"ARRAY",
"BIGINT",
"DB_KEY",
"BOOLEAN"
"BOOLEAN",
"DECFLOAT(16)",
"DECFLOAT(34)"
};
@ -135,7 +141,7 @@ const BYTE DSC_add_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
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_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}
};
@ -330,7 +352,7 @@ const BYTE DSC_sub_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
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_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}
};
@ -525,7 +564,7 @@ const BYTE DSC_multiply_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
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_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}
};
@ -720,7 +775,7 @@ const BYTE DSC_multiply_blr4_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
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_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_DEC64;
*sqlScale = 0;
break;
case dtype_dec128:
*sqlType = SQL_DEC128;
*sqlScale = 0;
break;
default:
status_exception::raise(
Arg::Gds(isc_sqlerr) << Arg::Num(-804) <<

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -26,12 +26,11 @@
#include "firebird.h"
#include <string.h>
//#include "../remote/remote.h"
#include "../common/xdr.h"
//#include "../remote/proto_proto.h"
#include "../common/xdr_proto.h"
#include "../yvalve/gds_proto.h"
#include "../common/gdsassert.h"
#include "../common/DecFloat.h"
inline UCHAR* XDR_ALLOC(ULONG size)
{
@ -261,6 +260,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]))
@ -339,6 +350,46 @@ bool_t xdr_double(XDR* xdrs, double* ip)
}
#ifndef WORDS_BIGENDIAN // Only little-endian HW is currently supported! FixMe!!!
bool_t xdr_dec64(XDR* xdrs, Firebird::Decimal64* ip)
{
switch (xdrs->x_op)
{
case XDR_ENCODE:
return PUTBYTES(xdrs, ip->getBytes(), sizeof(*ip));
case XDR_DECODE:
return GETBYTES(xdrs, ip->getBytes(), sizeof(*ip));
case XDR_FREE:
return TRUE;
}
return FALSE;
}
bool_t xdr_dec128(XDR* xdrs, Firebird::Decimal128* ip)
{
switch (xdrs->x_op)
{
case XDR_ENCODE:
return PUTBYTES(xdrs, ip->getBytes(), sizeof(*ip));
case XDR_DECODE:
return GETBYTES(xdrs, ip->getBytes(), sizeof(*ip));
case XDR_FREE:
return TRUE;
}
return FALSE;
}
#endif
bool_t xdr_enum(XDR* xdrs, xdr_op* ip)
{
/**************************************

View File

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

View File

@ -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)
{
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) /
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)
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) /
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_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;
if (nodFlags & FLAG_DECFLOAT)
temp.makeDecimal128(&dec);
else
temp.makeDouble(&d);
EVL_make_value(tdbb, &temp, impure);
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)
{
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 = 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,11 +1712,34 @@ 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) /
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);
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);
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->x2 - impure2->x * impure2->x / 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->y2 - impure2->y * impure2->y / 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);
@ -1547,11 +1747,15 @@ dsc* CorrAggNode::aggExecute(thread_db* tdbb, jrd_req* request) const
return NULL;
d = covarPop / divisor;
}
break;
}
}
dsc temp;
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)
{
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,19 @@ 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 +1908,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,15 +1946,90 @@ 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;
if (nodFlags & FLAG_DECFLOAT)
{
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;
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);
Decimal128 d;
switch (type)
{
case TYPE_REGR_AVGX:
d = avgX;
break;
case TYPE_REGR_AVGY:
d = avgY;
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_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_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;
@ -1762,11 +2084,10 @@ dsc* RegrAggNode::aggExecute(thread_db* tdbb, jrd_req* request) const
break;
}
dsc temp;
temp.makeDouble(&d);
}
EVL_make_value(tdbb, &temp, impure);
return &impure->vlu_desc;
}

View File

@ -186,9 +186,16 @@ public:
TYPE_VAR_POP
};
struct StdDevImpure
union StdDevImpure
{
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
{
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
{
struct
{
double x, x2, y, y2, xy;
} dbl;
struct
{
Firebird::Decimal128 x, x2, y, y2, xy;
} dec;
};
explicit RegrAggNode(MemoryPool& pool, RegrType aType,

View File

@ -798,7 +798,7 @@ 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
@ -836,7 +836,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:
@ -879,7 +879,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);
@ -945,7 +945,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)
@ -1154,7 +1154,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)

View File

@ -48,6 +48,7 @@
#include "../jrd/mov_proto.h"
#include "../jrd/pag_proto.h"
#include "../jrd/par_proto.h"
#include "../jrd/cvt2_proto.h"
#include "../dsql/ddl_proto.h"
#include "../dsql/errd_proto.h"
#include "../dsql/gen_proto.h"
@ -647,6 +648,14 @@ void ArithmeticNode::makeDialect1(dsc* desc, dsc& desc1, dsc& desc2)
desc->dsc_length = sizeof(double);
break;
case dtype_dec64:
case dtype_dec128:
desc->dsc_dtype = dtype_dec128;
desc->dsc_sub_type = 0;
desc->dsc_scale = 0;
desc->dsc_length = sizeof(Decimal128);
break;
default:
desc->dsc_dtype = dtype_long;
desc->dsc_sub_type = 0;
@ -670,6 +679,13 @@ void ArithmeticNode::makeDialect1(dsc* desc, dsc& desc1, dsc& desc2)
switch (dtype)
{
case dtype_dec128:
desc->dsc_dtype = dtype_dec128;
desc->dsc_sub_type = 0;
desc->dsc_scale = 0;
desc->dsc_length = sizeof(Decimal128);
break;
case dtype_double:
desc->dsc_dtype = dtype_double;
desc->dsc_sub_type = 0;
@ -709,7 +725,16 @@ void ArithmeticNode::makeDialect1(dsc* desc, dsc& desc1, dsc& desc2)
dtype = MAX(dtype1, dtype2);
if (!DTYPE_IS_NUMERIC(dtype))
if (DTYPE_IS_DECFLOAT(dtype))
{
desc->dsc_dtype = dtype_dec128;
desc->dsc_length = sizeof(Decimal128);
desc->dsc_scale = 0;
desc->dsc_flags = (desc1.dsc_flags | desc2.dsc_flags) & DSC_nullable;
break;
}
if (!DTYPE_IS_NUMERIC(type))
{
ERRD_post(Arg::Gds(isc_expression_eval_err) <<
Arg::Gds(isc_dsql_mustuse_numeric_div_dial1));
@ -755,6 +780,8 @@ void ArithmeticNode::makeDialect3(dsc* desc, dsc& desc1, dsc& desc2)
// <timestamp> arithmetic, but returns a <double>
if (DTYPE_IS_EXACT(dtype1) && DTYPE_IS_EXACT(dtype2))
dtype = dtype_int64;
else if (desc1.isDecOrInt() && desc2.isDecOrInt())
dtype = dtype_dec128;
else if (DTYPE_IS_NUMERIC(dtype1) && DTYPE_IS_NUMERIC(dtype2))
{
fb_assert(DTYPE_IS_APPROX(dtype1) || DTYPE_IS_APPROX(dtype2));
@ -771,7 +798,7 @@ void ArithmeticNode::makeDialect3(dsc* desc, dsc& desc1, dsc& desc2)
if (dtype_int64 == dtype2)
dtype2 = dtype_double;
dtype = MAX(dtype1, dtype2);
dtype = CVT2_compare_priority[dtype1] > CVT2_compare_priority[dtype2] ? dtype1 : dtype2;
}
desc->dsc_flags = (desc1.dsc_flags | desc2.dsc_flags) & DSC_nullable;
@ -875,6 +902,14 @@ void ArithmeticNode::makeDialect3(dsc* desc, dsc& desc1, dsc& desc2)
desc->dsc_length = sizeof(double);
break;
case dtype_dec64:
case dtype_dec128:
desc->dsc_dtype = dtype_dec128;
desc->dsc_sub_type = 0;
desc->dsc_scale = 0;
desc->dsc_length = sizeof(Decimal128);
break;
case dtype_short:
case dtype_long:
case dtype_int64:
@ -920,6 +955,13 @@ void ArithmeticNode::makeDialect3(dsc* desc, dsc& desc1, dsc& desc2)
switch (dtype)
{
case dtype_dec128:
desc->dsc_dtype = dtype_dec128;
desc->dsc_sub_type = 0;
desc->dsc_scale = 0;
desc->dsc_length = sizeof(Decimal128);
break;
case dtype_double:
desc->dsc_dtype = dtype_double;
desc->dsc_sub_type = 0;
@ -973,6 +1015,11 @@ void ArithmeticNode::makeDialect3(dsc* desc, dsc& desc1, dsc& desc2)
desc->dsc_scale = 0;
break;
case dtype_dec128:
desc->dsc_length = sizeof(Decimal128);
desc->dsc_scale = 0;
break;
default:
ERRD_post(Arg::Gds(isc_expression_eval_err) <<
Arg::Gds(isc_dsql_invalid_type_div_dial3));
@ -1168,6 +1215,16 @@ void ArithmeticNode::getDescDialect1(thread_db* /*tdbb*/, dsc* desc, dsc& desc1,
desc->dsc_flags = 0;
return;
case dtype_dec64:
case dtype_dec128:
nodFlags |= FLAG_DECFLOAT;
desc->dsc_dtype = dtype_dec128;
desc->dsc_length = sizeof(Decimal128);
desc->dsc_scale = 0;
desc->dsc_sub_type = 0;
desc->dsc_flags = 0;
break;
case dtype_unknown:
desc->dsc_dtype = dtype_unknown;
desc->dsc_length = 0;
@ -1210,6 +1267,15 @@ void ArithmeticNode::getDescDialect1(thread_db* /*tdbb*/, dsc* desc, dsc& desc1,
desc->dsc_flags = 0;
return;
case dtype_dec128:
nodFlags |= FLAG_DECFLOAT;
desc->dsc_dtype = dtype_dec128;
desc->dsc_length = sizeof(Decimal128);
desc->dsc_scale = 0;
desc->dsc_sub_type = 0;
desc->dsc_flags = 0;
break;
case dtype_unknown:
desc->dsc_dtype = dtype_unknown;
desc->dsc_length = 0;
@ -1230,6 +1296,16 @@ void ArithmeticNode::getDescDialect1(thread_db* /*tdbb*/, dsc* desc, dsc& desc1,
break;
case blr_divide:
if (desc1.isDecOrInt() && desc2.isDecOrInt())
{
desc->dsc_dtype = dtype_dec128;
desc->dsc_length = sizeof(Decimal128);
desc->dsc_scale = 0;
desc->dsc_sub_type = 0;
desc->dsc_flags = 0;
break;
}
// for compatibility with older versions of the product, we accept
// text types for division in blr_version4 (dialect <= 1) only
if (!(DTYPE_IS_NUMERIC(desc1.dsc_dtype) || DTYPE_IS_TEXT(desc1.dsc_dtype)))
@ -1270,7 +1346,7 @@ void ArithmeticNode::getDescDialect3(thread_db* /*tdbb*/, dsc* desc, dsc& desc1,
USHORT dtype1 = desc1.dsc_dtype;
USHORT dtype2 = desc2.dsc_dtype;
// In Dialect 2 or 3, strings can never partipate in addition / sub
// In Dialect 2 or 3, strings can never participate in addition / sub
// (use a specific cast instead)
if (DTYPE_IS_TEXT(dtype1) || DTYPE_IS_TEXT(dtype2))
ERR_post(Arg::Gds(isc_expression_eval_err));
@ -1281,6 +1357,8 @@ void ArithmeticNode::getDescDialect3(thread_db* /*tdbb*/, dsc* desc, dsc& desc1,
if (DTYPE_IS_EXACT(desc1.dsc_dtype) && DTYPE_IS_EXACT(desc2.dsc_dtype))
dtype = dtype_int64;
else if (desc1.isDecOrInt() && desc2.isDecOrInt())
dtype = dtype_dec128;
else if (DTYPE_IS_NUMERIC(desc1.dsc_dtype) && DTYPE_IS_NUMERIC(desc2.dsc_dtype))
dtype = dtype_double;
else
@ -1411,6 +1489,16 @@ void ArithmeticNode::getDescDialect3(thread_db* /*tdbb*/, dsc* desc, dsc& desc1,
desc->dsc_flags = 0;
return;
case dtype_dec64:
case dtype_dec128:
nodFlags |= FLAG_DECFLOAT;
desc->dsc_dtype = dtype_dec128;
desc->dsc_length = sizeof(Decimal128);
desc->dsc_scale = 0;
desc->dsc_sub_type = 0;
desc->dsc_flags = 0;
return;
case dtype_short:
case dtype_long:
case dtype_int64:
@ -1460,6 +1548,15 @@ void ArithmeticNode::getDescDialect3(thread_db* /*tdbb*/, dsc* desc, dsc& desc1,
desc->dsc_flags = 0;
return;
case dtype_dec128:
nodFlags |= FLAG_DECFLOAT;
desc->dsc_dtype = dtype_dec128;
desc->dsc_length = sizeof(Decimal128);
desc->dsc_scale = 0;
desc->dsc_sub_type = 0;
desc->dsc_flags = 0;
return;
case dtype_int64:
desc->dsc_dtype = dtype_int64;
desc->dsc_length = sizeof(SINT64);
@ -1590,7 +1687,7 @@ dsc* ArithmeticNode::execute(thread_db* tdbb, jrd_req* request) const
case blr_divide:
{
const double divisor = MOV_get_double(desc2);
const double divisor = MOV_get_double(tdbb, desc2);
if (divisor == 0)
{
@ -1598,7 +1695,7 @@ dsc* ArithmeticNode::execute(thread_db* tdbb, jrd_req* request) const
Arg::Gds(isc_exception_float_divide_by_zero));
}
impure->vlu_misc.vlu_double = MOV_get_double(desc1) / divisor;
impure->vlu_misc.vlu_double = MOV_get_double(tdbb, desc1) / divisor;
if (isinf(impure->vlu_misc.vlu_double))
{
@ -1642,6 +1739,7 @@ dsc* ArithmeticNode::execute(thread_db* tdbb, jrd_req* request) const
dsc* ArithmeticNode::add(const dsc* desc, impure_value* value, const ValueExprNode* node, const UCHAR blrOp)
{
const ArithmeticNode* arithmeticNode = node->as<ArithmeticNode>();
thread_db* tdbb = JRD_get_thread_data();
#ifdef DEV_BUILD
const SubQueryNode* subQueryNode = node->as<SubQueryNode>();
@ -1662,12 +1760,31 @@ dsc* ArithmeticNode::add(const dsc* desc, impure_value* value, const ValueExprNo
return arithmeticNode->addDateTime(desc, value);
}
// Handle decimal arithmetic
if (node->nodFlags & FLAG_DECFLOAT)
{
const Decimal128 d1 = MOV_get_dec128(tdbb, desc);
const Decimal128 d2 = MOV_get_dec128(tdbb, &value->vlu_desc);
DecimalStatus decSt = tdbb->getAttachment()->att_dec_status;
value->vlu_misc.vlu_dec128 = (blrOp == blr_subtract) ? d2.sub(decSt, d1) : d1.add(decSt, d2);
result->dsc_dtype = dtype_dec128;
result->dsc_length = sizeof(Decimal128);
result->dsc_scale = 0;
result->dsc_sub_type = 0;
result->dsc_address = (UCHAR*) &value->vlu_misc.vlu_dec128;
return result;
}
// Handle floating arithmetic
if (node->nodFlags & FLAG_DOUBLE)
{
const double d1 = MOV_get_double(desc);
const double d2 = MOV_get_double(&value->vlu_desc);
const double d1 = MOV_get_double(tdbb, desc);
const double d2 = MOV_get_double(tdbb, &value->vlu_desc);
value->vlu_misc.vlu_double = (blrOp == blr_subtract) ? d2 - d1 : d1 + d2;
@ -1688,8 +1805,8 @@ dsc* ArithmeticNode::add(const dsc* desc, impure_value* value, const ValueExprNo
// CVC: Maybe we should upgrade the sum to double if it doesn't fit?
// This is what was done for multiplicaton in dialect 1.
const SLONG l1 = MOV_get_long(desc, node->nodScale);
const SINT64 l2 = MOV_get_long(&value->vlu_desc, node->nodScale);
const SLONG l1 = MOV_get_long(tdbb, desc, node->nodScale);
const SINT64 l2 = MOV_get_long(tdbb, &value->vlu_desc, node->nodScale);
const SINT64 rc = (blrOp == blr_subtract) ? l2 - l1 : l2 + l1;
if (rc < MIN_SLONG || rc > MAX_SLONG)
@ -1721,12 +1838,33 @@ dsc* ArithmeticNode::add2(const dsc* desc, impure_value* value, const ValueExprN
return arithmeticNode->addDateTime(desc, value);
}
thread_db* tdbb = JRD_get_thread_data();
// Handle decimal arithmetic
if (node->nodFlags & FLAG_DECFLOAT)
{
const Decimal128 d1 = MOV_get_dec128(tdbb, desc);
const Decimal128 d2 = MOV_get_dec128(tdbb, &value->vlu_desc);
DecimalStatus decSt = tdbb->getAttachment()->att_dec_status;
value->vlu_misc.vlu_dec128 = (blrOp == blr_subtract) ? d2.sub(decSt, d1) : d1.add(decSt, d2);
result->dsc_dtype = dtype_dec128;
result->dsc_length = sizeof(Decimal128);
result->dsc_scale = 0;
result->dsc_sub_type = 0;
result->dsc_address = (UCHAR*) &value->vlu_misc.vlu_dec128;
return result;
}
// Handle floating arithmetic
if (node->nodFlags & FLAG_DOUBLE)
{
const double d1 = MOV_get_double(desc);
const double d2 = MOV_get_double(&value->vlu_desc);
const double d1 = MOV_get_double(tdbb, desc);
const double d2 = MOV_get_double(tdbb, &value->vlu_desc);
value->vlu_misc.vlu_double = (blrOp == blr_subtract) ? d2 - d1 : d1 + d2;
@ -1744,8 +1882,8 @@ dsc* ArithmeticNode::add2(const dsc* desc, impure_value* value, const ValueExprN
// Everything else defaults to int64
SINT64 i1 = MOV_get_int64(desc, node->nodScale);
const SINT64 i2 = MOV_get_int64(&value->vlu_desc, node->nodScale);
SINT64 i1 = MOV_get_int64(tdbb, desc, node->nodScale);
const SINT64 i2 = MOV_get_int64(tdbb, &value->vlu_desc, node->nodScale);
result->dsc_dtype = dtype_int64;
result->dsc_length = sizeof(SINT64);
@ -1785,14 +1923,34 @@ dsc* ArithmeticNode::add2(const dsc* desc, impure_value* value, const ValueExprN
// This function can be removed when dialect-3 becomes the lowest supported dialect. (Version 7.0?)
dsc* ArithmeticNode::multiply(const dsc* desc, impure_value* value) const
{
thread_db* tdbb = JRD_get_thread_data();
DEV_BLKCHK(node, type_nod);
// Handle decimal arithmetic
if (nodFlags & FLAG_DECFLOAT)
{
const Decimal128 d1 = MOV_get_dec128(tdbb, desc);
const Decimal128 d2 = MOV_get_dec128(tdbb, &value->vlu_desc);
DecimalStatus decSt = tdbb->getAttachment()->att_dec_status;
value->vlu_misc.vlu_dec128 = d1.mul(decSt, d2);
value->vlu_desc.dsc_dtype = dtype_dec128;
value->vlu_desc.dsc_length = sizeof(Decimal128);
value->vlu_desc.dsc_scale = 0;
value->vlu_desc.dsc_sub_type = 0;
value->vlu_desc.dsc_address = (UCHAR*) &value->vlu_misc.vlu_dec128;
return &value->vlu_desc;
}
// Handle floating arithmetic
if (nodFlags & FLAG_DOUBLE)
{
const double d1 = MOV_get_double(desc);
const double d2 = MOV_get_double(&value->vlu_desc);
const double d1 = MOV_get_double(tdbb, desc);
const double d2 = MOV_get_double(tdbb, &value->vlu_desc);
value->vlu_misc.vlu_double = d1 * d2;
if (isinf(value->vlu_misc.vlu_double))
@ -1820,8 +1978,8 @@ dsc* ArithmeticNode::multiply(const dsc* desc, impure_value* value) const
// SLONG l1, l2;
//{
const SSHORT scale = NUMERIC_SCALE(value->vlu_desc);
const SINT64 i1 = MOV_get_long(desc, nodScale - scale);
const SINT64 i2 = MOV_get_long(&value->vlu_desc, scale);
const SINT64 i1 = MOV_get_long(tdbb, desc, nodScale - scale);
const SINT64 i2 = MOV_get_long(tdbb, &value->vlu_desc, scale);
value->vlu_desc.dsc_dtype = dtype_long;
value->vlu_desc.dsc_length = sizeof(SLONG);
value->vlu_desc.dsc_scale = nodScale;
@ -1833,7 +1991,7 @@ dsc* ArithmeticNode::multiply(const dsc* desc, impure_value* value) const
value->vlu_desc.dsc_address = (UCHAR*) &value->vlu_misc.vlu_int64;
value->vlu_desc.dsc_dtype = dtype_int64;
value->vlu_desc.dsc_length = sizeof(SINT64);
value->vlu_misc.vlu_double = MOV_get_double(&value->vlu_desc);
value->vlu_misc.vlu_double = MOV_get_double(tdbb, &value->vlu_desc);
/* This is the Borland solution instead of the five lines above.
d1 = MOV_get_double (desc);
d2 = MOV_get_double (&value->vlu_desc);
@ -1859,14 +2017,34 @@ dsc* ArithmeticNode::multiply(const dsc* desc, impure_value* value) const
// Multiply two numbers, with dialect-3 semantics, implementing blr_version5 ... blr_multiply.
dsc* ArithmeticNode::multiply2(const dsc* desc, impure_value* value) const
{
thread_db* tdbb = JRD_get_thread_data();
DEV_BLKCHK(node, type_nod);
// Handle decimal arithmetic
if (nodFlags & FLAG_DECFLOAT)
{
const Decimal128 d1 = MOV_get_dec128(tdbb, desc);
const Decimal128 d2 = MOV_get_dec128(tdbb, &value->vlu_desc);
DecimalStatus decSt = tdbb->getAttachment()->att_dec_status;
value->vlu_misc.vlu_dec128 = d1.mul(decSt, d2);
value->vlu_desc.dsc_dtype = dtype_dec128;
value->vlu_desc.dsc_length = sizeof(Decimal128);
value->vlu_desc.dsc_scale = 0;
value->vlu_desc.dsc_sub_type = 0;
value->vlu_desc.dsc_address = (UCHAR*) &value->vlu_misc.vlu_dec128;
return &value->vlu_desc;
}
// Handle floating arithmetic
if (nodFlags & FLAG_DOUBLE)
{
const double d1 = MOV_get_double(desc);
const double d2 = MOV_get_double(&value->vlu_desc);
const double d1 = MOV_get_double(tdbb, desc);
const double d2 = MOV_get_double(tdbb, &value->vlu_desc);
value->vlu_misc.vlu_double = d1 * d2;
if (isinf(value->vlu_misc.vlu_double))
@ -1886,8 +2064,8 @@ dsc* ArithmeticNode::multiply2(const dsc* desc, impure_value* value) const
// Everything else defaults to int64
const SSHORT scale = NUMERIC_SCALE(value->vlu_desc);
const SINT64 i1 = MOV_get_int64(desc, nodScale - scale);
const SINT64 i2 = MOV_get_int64(&value->vlu_desc, scale);
const SINT64 i1 = MOV_get_int64(tdbb, desc, nodScale - scale);
const SINT64 i2 = MOV_get_int64(tdbb, &value->vlu_desc, scale);
/*
We need to report an overflow if
@ -1935,19 +2113,39 @@ dsc* ArithmeticNode::multiply2(const dsc* desc, impure_value* value) const
// blr_version5 ... blr_average ....
dsc* ArithmeticNode::divide2(const dsc* desc, impure_value* value) const
{
thread_db* tdbb = JRD_get_thread_data();
DEV_BLKCHK(node, type_nod);
// Handle decimal arithmetic
if (nodFlags & FLAG_DECFLOAT)
{
const Decimal128 d1 = MOV_get_dec128(tdbb, desc);
const Decimal128 d2 = MOV_get_dec128(tdbb, &value->vlu_desc);
DecimalStatus decSt = tdbb->getAttachment()->att_dec_status;
value->vlu_misc.vlu_dec128 = d2.div(decSt, d1);
value->vlu_desc.dsc_dtype = dtype_dec128;
value->vlu_desc.dsc_length = sizeof(Decimal128);
value->vlu_desc.dsc_scale = 0;
value->vlu_desc.dsc_sub_type = 0;
value->vlu_desc.dsc_address = (UCHAR*) &value->vlu_misc.vlu_dec128;
return &value->vlu_desc;
}
// Handle floating arithmetic
if (nodFlags & FLAG_DOUBLE)
{
const double d2 = MOV_get_double(desc);
const double d2 = MOV_get_double(tdbb, desc);
if (d2 == 0.0)
{
ERR_post(Arg::Gds(isc_arith_except) <<
Arg::Gds(isc_exception_float_divide_by_zero));
}
const double d1 = MOV_get_double(&value->vlu_desc);
const double d1 = MOV_get_double(tdbb, &value->vlu_desc);
value->vlu_misc.vlu_double = d1 / d2;
if (isinf(value->vlu_misc.vlu_double))
{
@ -1998,14 +2196,14 @@ dsc* ArithmeticNode::divide2(const dsc* desc, impure_value* value) const
* Who'da thunk that 9th-grade algebra would prove so useful.
* -- Chris Jewell, December 1998
*/
SINT64 i2 = MOV_get_int64(desc, desc->dsc_scale);
SINT64 i2 = MOV_get_int64(tdbb, desc, desc->dsc_scale);
if (i2 == 0)
{
ERR_post(Arg::Gds(isc_arith_except) <<
Arg::Gds(isc_exception_integer_divide_by_zero));
}
SINT64 i1 = MOV_get_int64(&value->vlu_desc, nodScale - desc->dsc_scale);
SINT64 i1 = MOV_get_int64(tdbb, &value->vlu_desc, nodScale - desc->dsc_scale);
// MIN_SINT64 / -1 = (MAX_SINT64 + 1), which overflows in SINT64.
if ((i1 == MIN_SINT64) && (i2 == -1))
@ -2141,6 +2339,7 @@ dsc* ArithmeticNode::addSqlDate(const dsc* desc, impure_value* value) const
fb_assert(blrOp == blr_add || blrOp == blr_subtract);
dsc* result = &value->vlu_desc;
thread_db* tdbb = JRD_get_thread_data();
fb_assert(value->vlu_desc.dsc_dtype == dtype_sql_date || desc->dsc_dtype == dtype_sql_date);
@ -2153,7 +2352,7 @@ dsc* ArithmeticNode::addSqlDate(const dsc* desc, impure_value* value) const
op1_is_date = true;
}
else
d1 = MOV_get_int64(&value->vlu_desc, 0);
d1 = MOV_get_int64(tdbb, &value->vlu_desc, 0);
SINT64 d2;
// Coerce operand2 to a count of days
@ -2164,7 +2363,7 @@ dsc* ArithmeticNode::addSqlDate(const dsc* desc, impure_value* value) const
op2_is_date = true;
}
else
d2 = MOV_get_int64(desc, 0);
d2 = MOV_get_int64(tdbb, desc, 0);
if (blrOp == blr_subtract && op1_is_date && op2_is_date)
{
@ -2210,6 +2409,7 @@ dsc* ArithmeticNode::addSqlTime(const dsc* desc, impure_value* value) const
fb_assert(blrOp == blr_add || blrOp == blr_subtract);
dsc* result = &value->vlu_desc;
thread_db* tdbb = JRD_get_thread_data();
fb_assert(value->vlu_desc.dsc_dtype == dtype_sql_time || desc->dsc_dtype == dtype_sql_time);
@ -2223,7 +2423,7 @@ dsc* ArithmeticNode::addSqlTime(const dsc* desc, impure_value* value) const
fb_assert(d1 >= 0 && d1 < ISC_TICKS_PER_DAY);
}
else
d1 = MOV_get_int64(&value->vlu_desc, ISC_TIME_SECONDS_PRECISION_SCALE);
d1 = MOV_get_int64(tdbb, &value->vlu_desc, ISC_TIME_SECONDS_PRECISION_SCALE);
SINT64 d2;
// Coerce operand2 to a count of seconds
@ -2235,7 +2435,7 @@ dsc* ArithmeticNode::addSqlTime(const dsc* desc, impure_value* value) const
fb_assert(d2 >= 0 && d2 < ISC_TICKS_PER_DAY);
}
else
d2 = MOV_get_int64(desc, ISC_TIME_SECONDS_PRECISION_SCALE);
d2 = MOV_get_int64(tdbb, desc, ISC_TIME_SECONDS_PRECISION_SCALE);
if (blrOp == blr_subtract && op1_is_time && op2_is_time)
{
@ -4101,7 +4301,7 @@ dsc* DecodeNode::execute(thread_db* tdbb, jrd_req* request) const
{
dsc* desc = EVL_expr(tdbb, request, condition);
if (desc && !(request->req_flags & req_null) && MOV_compare(testDesc, desc) == 0)
if (desc && !(request->req_flags & req_null) && MOV_compare(tdbb, testDesc, desc) == 0)
return EVL_expr(tdbb, request, *valuesPtr);
++valuesPtr;
@ -6090,7 +6290,7 @@ dsc* GenIdNode::execute(thread_db* tdbb, jrd_req* request) const
if (request->req_flags & req_null)
return NULL;
change = MOV_get_int64(value, 0);
change = MOV_get_int64(tdbb, value, 0);
}
if (sysGen && change != 0)
@ -6447,7 +6647,7 @@ DmlNode* LiteralNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch*
l = csb->csb_blr_reader.getWord();
q = csb->csb_blr_reader.getPos();
dtype = CVT_get_numeric(q, l, &scale, (double*) p);
dtype = CVT_get_numeric(q, l, &scale, (double*) p); // use decfloat to pass literal ???
node->litDesc.dsc_dtype = dtype;
switch (dtype)
@ -6805,8 +7005,9 @@ bool LiteralNode::sameAs(const ExprNode* other, bool ignoreStreams) const
const LiteralNode* const otherNode = other->as<LiteralNode>();
fb_assert(otherNode);
thread_db* tdbb = JRD_get_thread_data();
return !MOV_compare(&litDesc, &otherNode->litDesc);
return !MOV_compare(tdbb, &litDesc, &otherNode->litDesc);
}
ValueExprNode* LiteralNode::pass2(thread_db* tdbb, CompilerScratch* csb)
@ -7365,7 +7566,7 @@ void NegateNode::make(DsqlCompilerScratch* dsqlScratch, dsc* desc)
void NegateNode::getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc)
{
arg->getDesc(tdbb, csb, desc);
nodFlags = arg->nodFlags & FLAG_DOUBLE;
nodFlags = arg->nodFlags & (FLAG_DOUBLE | FLAG_DECFLOAT);
if (desc->dsc_dtype == dtype_quad)
IBERROR(224); // msg 224 quad word arithmetic not supported
@ -7422,6 +7623,14 @@ dsc* NegateNode::execute(thread_db* tdbb, jrd_req* request) const
impure->vlu_misc.vlu_double = -impure->vlu_misc.vlu_double;
break;
case dtype_dec64:
impure->vlu_misc.vlu_dec64 = impure->vlu_misc.vlu_dec64.neg();
break;
case dtype_dec128:
impure->vlu_misc.vlu_dec128 = impure->vlu_misc.vlu_dec128.neg();
break;
case dtype_int64:
if (impure->vlu_misc.vlu_int64 == MIN_SINT64)
ERR_post(Arg::Gds(isc_exception_integer_overflow));
@ -7429,7 +7638,7 @@ dsc* NegateNode::execute(thread_db* tdbb, jrd_req* request) const
break;
default:
impure->vlu_misc.vlu_double = -MOV_get_double(&impure->vlu_desc);
impure->vlu_misc.vlu_double = -MOV_get_double(tdbb, &impure->vlu_desc);
impure->vlu_desc.dsc_dtype = DEFAULT_DOUBLE;
impure->vlu_desc.dsc_length = sizeof(double);
impure->vlu_desc.dsc_scale = 0;
@ -8266,7 +8475,7 @@ dsc* ParameterNode::execute(thread_db* tdbb, jrd_req* request) const
if (argFlag)
{
desc = EVL_expr(tdbb, request, argFlag);
if (MOV_get_long(desc, 0))
if (MOV_get_long(tdbb, desc, 0))
request->req_flags |= req_null;
}
@ -9005,7 +9214,7 @@ dsc* ScalarNode::execute(thread_db* tdbb, jrd_req* request) const
const dsc* temp = EVL_expr(tdbb, request, subscript);
if (temp && !(request->req_flags & req_null))
numSubscripts[iter++] = MOV_get_long(temp, 0);
numSubscripts[iter++] = MOV_get_long(tdbb, temp, 0);
else
return NULL;
}
@ -9253,7 +9462,7 @@ dsc* StrCaseNode::execute(thread_db* tdbb, jrd_req* request) const
USHORT ttype;
dsc desc;
desc.dsc_length = MOV_get_string_ptr(value, &ttype, &ptr, &temp, sizeof(temp));
desc.dsc_length = MOV_get_string_ptr(tdbb, value, &ttype, &ptr, &temp, sizeof(temp));
desc.dsc_dtype = dtype_text;
desc.dsc_address = NULL;
desc.setTextType(ttype);
@ -9483,7 +9692,7 @@ dsc* StrLenNode::execute(thread_db* tdbb, jrd_req* request) const
USHORT ttype;
UCHAR* p;
length = MOV_get_string_ptr(value, &ttype, &p, &temp, sizeof(temp));
length = MOV_get_string_ptr(tdbb, value, &ttype, &p, &temp, sizeof(temp));
switch (blrSubOp)
{
@ -9689,6 +9898,17 @@ void SubQueryNode::getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc)
if (blrOp == blr_average)
{
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 (!(DTYPE_IS_NUMERIC(desc->dsc_dtype) || DTYPE_IS_TEXT(desc->dsc_dtype)))
{
if (desc->dsc_dtype != dtype_unknown)
@ -9738,6 +9958,16 @@ void SubQueryNode::getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc)
nodFlags |= FLAG_DOUBLE;
return;
case dtype_dec64:
case dtype_dec128:
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;
case dtype_sql_time:
case dtype_sql_date:
case dtype_timestamp:
@ -9808,13 +10038,12 @@ ValueExprNode* SubQueryNode::pass2(thread_db* tdbb, CompilerScratch* csb)
impureOffset = CMP_impure(csb, sizeof(impure_value_ex));
if (blrOp == blr_average)
nodFlags |= FLAG_DOUBLE;
else if (blrOp == blr_total)
{
dsc desc;
getDesc(tdbb, csb, &desc);
}
if (blrOp == blr_average && !(nodFlags & FLAG_DECFLOAT))
nodFlags |= FLAG_DOUBLE;
// Bind values of invariant nodes to top-level RSE (if present).
if ((nodFlags & FLAG_INVARIANT) && csb->csb_current_nodes.hasData())
@ -9903,7 +10132,7 @@ dsc* SubQueryNode::execute(thread_db* tdbb, jrd_req* request) const
int result;
if (flag || ((result = MOV_compare(value, desc)) < 0 && blrOp == blr_minimum) ||
if (flag || ((result = MOV_compare(tdbb, value, desc)) < 0 && blrOp == blr_minimum) ||
(blrOp != blr_minimum && result > 0))
{
flag = 0;
@ -9940,7 +10169,7 @@ dsc* SubQueryNode::execute(thread_db* tdbb, jrd_req* request) const
if (!count)
break;
d = MOV_get_double(&impure->vlu_desc);
d = MOV_get_double(tdbb, &impure->vlu_desc);
impure->vlu_misc.vlu_double = d / count;
impure->vlu_desc.dsc_dtype = DEFAULT_DOUBLE;
impure->vlu_desc.dsc_length = sizeof(double);
@ -10138,10 +10367,10 @@ void SubstringNode::getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc)
{
if (offsetNode->is<LiteralNode>() && desc1.dsc_dtype == dtype_long)
{
SLONG offset = MOV_get_long(&desc1, 0);
SLONG offset = MOV_get_long(tdbb, &desc1, 0);
if (decrementNode && decrementNode->is<LiteralNode>() && desc3.dsc_dtype == dtype_long)
offset -= MOV_get_long(&desc3, 0);
offset -= MOV_get_long(tdbb, &desc3, 0);
if (offset < 0)
ERR_post(Arg::Gds(isc_bad_substring_offset) << Arg::Num(offset + 1));
@ -10149,7 +10378,7 @@ void SubstringNode::getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc)
if (length->is<LiteralNode>() && desc2.dsc_dtype == dtype_long)
{
const SLONG len = MOV_get_long(&desc2, 0);
const SLONG len = MOV_get_long(tdbb, &desc2, 0);
if (len < 0)
ERR_post(Arg::Gds(isc_bad_substring_length) << Arg::Num(len));
@ -10203,8 +10432,8 @@ dsc* SubstringNode::execute(thread_db* tdbb, jrd_req* request) const
dsc* SubstringNode::perform(thread_db* tdbb, impure_value* impure, const dsc* valueDsc,
const dsc* startDsc, const dsc* lengthDsc)
{
const SLONG sStart = MOV_get_long(startDsc, 0);
const SLONG sLength = MOV_get_long(lengthDsc, 0);
const SLONG sStart = MOV_get_long(tdbb, startDsc, 0);
const SLONG sLength = MOV_get_long(tdbb, lengthDsc, 0);
if (sStart < 0)
status_exception::raise(Arg::Gds(isc_bad_substring_offset) << Arg::Num(sStart + 1));
@ -10295,7 +10524,7 @@ dsc* SubstringNode::perform(thread_db* tdbb, impure_value* impure, const dsc* va
// they aren't accepted, so they will cause error() to be called anyway.
VaryStr<32> temp;
USHORT ttype;
desc.dsc_length = MOV_get_string_ptr(valueDsc, &ttype, &desc.dsc_address,
desc.dsc_length = MOV_get_string_ptr(tdbb, valueDsc, &ttype, &desc.dsc_address,
&temp, sizeof(temp));
desc.setTextType(ttype);
@ -12073,6 +12302,7 @@ static SINT64 getDayFraction(const dsc* d)
{
dsc result;
double result_days;
thread_db* tdbb = JRD_get_thread_data();
result.dsc_dtype = dtype_double;
result.dsc_scale = 0;
@ -12082,7 +12312,7 @@ static SINT64 getDayFraction(const dsc* d)
result.dsc_address = reinterpret_cast<UCHAR*>(&result_days);
// Convert the input number to a double
CVT_move(d, &result);
CVT_move(d, &result, tdbb->getAttachment()->att_dec_status);
// There's likely some loss of precision here due to rounding of number
@ -12114,6 +12344,7 @@ static SINT64 getDayFraction(const dsc* d)
// This is derived from the ISC_TIME_SECONDS_PRECISION.
static SINT64 getTimeStampToIscTicks(const dsc* d)
{
thread_db* tdbb = JRD_get_thread_data();
dsc result;
GDS_TIMESTAMP result_timestamp;
@ -12124,7 +12355,7 @@ static SINT64 getTimeStampToIscTicks(const dsc* d)
result.dsc_length = sizeof(GDS_TIMESTAMP);
result.dsc_address = reinterpret_cast<UCHAR*>(&result_timestamp);
CVT_move(d, &result);
CVT_move(d, &result, tdbb->getAttachment()->att_dec_status);
return ((SINT64) result_timestamp.timestamp_date) * ISC_TICKS_PER_DAY +
(SINT64) result_timestamp.timestamp_time;

View File

@ -470,7 +470,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),

View File

@ -1187,7 +1187,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)
{
@ -7503,7 +7503,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);
@ -9242,7 +9242,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;

View File

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

View File

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

View File

@ -366,6 +366,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;

View File

@ -169,7 +169,7 @@ ValueExprNode* MAKE_constant(const char* str, dsql_constant_type numeric_flag)
// Now invoke the string_to_date/time/timestamp routines
CVT_move(&tmp, &literal->litDesc, ERRD_post);
CVT_move(&tmp, &literal->litDesc, tdbb->getAttachment()->att_dec_status, ERRD_post);
break;
}

View File

@ -611,6 +611,7 @@ using namespace Firebird;
%token <metaNamePtr> TIES
%token <metaNamePtr> UNBOUNDED
%token <metaNamePtr> WINDOW
%token <metaNamePtr> DECFLOAT
// precedence declarations for expression evaluation
@ -4029,6 +4030,7 @@ keyword_or_column
| VAR_POP
| UNBOUNDED // added in FB 4.0
| WINDOW
| DECFLOAT
;
col_opt
@ -4385,6 +4387,7 @@ non_charset_simple_type
: national_character_type
| numeric_type
| float_type
| decfloat_type
| BIGINT
{
$$ = newNode<dsql_fld>();
@ -4610,6 +4613,27 @@ national_character_keyword
// numeric type
%type <legacyField> decfloat_type
decfloat_type
: DECFLOAT
{
$$ = newNode<dsql_fld>();
$$->dtype = dtype_dec64;
$$->length = sizeof(Decimal64);
$$->precision = 16;
}
| DECFLOAT '(' signed_long_integer ')'
{
if ($3 != 16 && $3 != 34)
yyabandon(-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

View File

@ -78,6 +78,8 @@ typedef struct
#define SQL_TYPE_TIME 560
#define SQL_TYPE_DATE 570
#define SQL_INT64 580
#define SQL_DEC64 32760
#define SQL_DEC128 32762
#define SQL_BOOLEAN 32764
#define SQL_NULL 32766

View File

@ -49,7 +49,7 @@ static void post_error(const Firebird::Arg::StatusVector&);
void MOVG_move(const dsc* from, dsc* to)
{
CVT_move(from, to, post_error);
CVT_move(from, to, 0, post_error);
}

View File

@ -828,6 +828,7 @@ static const struct {
{"dsql_window_cant_overr_frame", 335545124},
{"dsql_window_duplicate", 335545125},
{"sql_too_long", 335545126},
{"decprecision_err", 335545127},
{"gfix_db_name", 335740929},
{"gfix_invalid_sw", 335740930},
{"gfix_incmp_sw", 335740932},

View File

@ -862,6 +862,7 @@ const ISC_STATUS isc_dsql_window_cant_overr_order = 335545123L;
const ISC_STATUS isc_dsql_window_cant_overr_frame = 335545124L;
const ISC_STATUS isc_dsql_window_duplicate = 335545125L;
const ISC_STATUS isc_sql_too_long = 335545126L;
const ISC_STATUS isc_decprecision_err = 335545127L;
const ISC_STATUS isc_gfix_db_name = 335740929L;
const ISC_STATUS isc_gfix_invalid_sw = 335740930L;
const ISC_STATUS isc_gfix_incmp_sw = 335740932L;
@ -1334,7 +1335,7 @@ const ISC_STATUS isc_trace_switch_user_only = 337182757L;
const ISC_STATUS isc_trace_switch_param_miss = 337182758L;
const ISC_STATUS isc_trace_param_act_notcompat = 337182759L;
const ISC_STATUS isc_trace_mandatory_switch_miss = 337182760L;
const ISC_STATUS isc_err_max = 1278;
const ISC_STATUS isc_err_max = 1279;
#else /* c definitions */
@ -2166,6 +2167,7 @@ const ISC_STATUS isc_err_max = 1278;
#define isc_dsql_window_cant_overr_frame 335545124L
#define isc_dsql_window_duplicate 335545125L
#define isc_sql_too_long 335545126L
#define isc_decprecision_err 335545127L
#define isc_gfix_db_name 335740929L
#define isc_gfix_invalid_sw 335740930L
#define isc_gfix_incmp_sw 335740932L
@ -2638,7 +2640,7 @@ const ISC_STATUS isc_err_max = 1278;
#define isc_trace_switch_param_miss 337182758L
#define isc_trace_param_act_notcompat 337182759L
#define isc_trace_mandatory_switch_miss 337182760L
#define isc_err_max 1278
#define isc_err_max 1279
#endif

View File

@ -831,6 +831,7 @@ Data source : @4"}, /* eds_statement */
{335545124, "Cannot override the window @1 because it has a frame clause. Tip: it can be used without parenthesis in OVER"}, /* dsql_window_cant_overr_frame */
{335545125, "Duplicate window definition for @1"}, /* dsql_window_duplicate */
{335545126, "SQL statement is too long. Maximum size is @1 bytes."}, /* sql_too_long */
{335545127, "DecFloat precision must be 16 or 34"}, /* decprecision_err */
{335740929, "data base file name (@1) already given"}, /* gfix_db_name */
{335740930, "invalid switch @1"}, /* gfix_invalid_sw */
{335740932, "incompatible switch combination"}, /* gfix_incmp_sw */

View File

@ -827,6 +827,7 @@ static const struct {
{335545124, -833}, /* 804 dsql_window_cant_overr_frame */
{335545125, -833}, /* 805 dsql_window_duplicate */
{335545126, -902}, /* 806 sql_too_long */
{335545127, -842}, /* 807 decprecision_err */
{335740929, -901}, /* 1 gfix_db_name */
{335740930, -901}, /* 2 gfix_invalid_sw */
{335740932, -901}, /* 4 gfix_incmp_sw */

View File

@ -827,6 +827,7 @@ static const struct {
{335545124, "42000"}, // 804 dsql_window_cant_overr_frame
{335545125, "42000"}, // 805 dsql_window_duplicate
{335545126, "54001"}, // 806 sql_too_long
{335545127, "HY104"}, // 807 decprecision_err
{335740929, "00000"}, // 1 gfix_db_name
{335740930, "00000"}, // 2 gfix_invalid_sw
{335740932, "00000"}, // 4 gfix_incmp_sw

View File

@ -2219,6 +2219,8 @@ static processing_state add_row(TEXT* tabname)
SINT64 n;
float* fvalue;
double* dvalue;
Firebird::Decimal64* d64value;
Firebird::Decimal128* d128value;
UCHAR* boolean;
ISC_QUAD* blobid;
vary* avary;
@ -2285,6 +2287,32 @@ static processing_state add_row(TEXT* tabname)
}
break;
case SQL_DEC64:
d64value = (Firebird::Decimal64*) datap;
try
{
d64value->set(lastInputLine, isqlGlob.decStatus);
}
catch (const Firebird::Exception&)
{
STDERROUT("Input parsing problem");
done = true;
}
break;
case SQL_DEC128:
d128value = (Firebird::Decimal128*) datap;
try
{
d128value->set(lastInputLine, isqlGlob.decStatus);
}
catch (const Firebird::Exception&)
{
STDERROUT("Input parsing problem");
done = true;
}
break;
case SQL_TYPE_DATE:
if (3 != sscanf(lastInputLine, "%d/%d/%d", &times.tm_year,
&times.tm_mon, &times.tm_mday) ||
@ -2974,6 +3002,8 @@ static processing_state bulk_insert_hack(const char* command)
vary* avary;
char* achar;
tm times;
Firebird::Decimal64* d64value;
Firebird::Decimal128* d128value;
// Initialize the time structure.
memset(&times, 0, sizeof(times));
char msec_str[5] = "";
@ -3033,6 +3063,32 @@ static processing_state bulk_insert_hack(const char* command)
}
break;
case SQL_DEC64:
d64value = (Firebird::Decimal64*) datap;
try
{
d64value->set(lastPos, isqlGlob.decStatus);
}
catch (const Firebird::Exception&)
{
STDERROUT("Input parsing problem");
done = true;
}
break;
case SQL_DEC128:
d128value = (Firebird::Decimal128*) datap;
try
{
d128value->set(lastPos, isqlGlob.decStatus);
}
catch (const Firebird::Exception&)
{
STDERROUT("Input parsing problem");
done = true;
}
break;
case SQL_TYPE_DATE:
if (3 != sscanf(lastPos, "%d-%d-%d", &times.tm_year,
&times.tm_mon, &times.tm_mday) ||
@ -7152,6 +7208,30 @@ static unsigned print_item(TEXT** s, const IsqlVar* var, const unsigned length)
}
break;
case SQL_DEC64:
{
char decStr[DECDOUBLE_String];
var->value.asDec64->toString(isqlGlob.decStatus, sizeof(decStr), decStr);
if (setValues.List)
isqlGlob.printf("%*.*s%s", sizeof(decStr) - 1, sizeof(decStr) - 1, decStr, NEWLINE);
else
sprintf(p, "%*.*s ", sizeof(decStr) - 1, sizeof(decStr) - 1, decStr);
}
break;
case SQL_DEC128:
{
char decStr[DECQUAD_String];
var->value.asDec128->toString(isqlGlob.decStatus, sizeof(decStr), decStr);
if (setValues.List)
isqlGlob.printf("%*.*s%s", sizeof(decStr) - 1, sizeof(decStr) - 1, decStr, NEWLINE);
else
sprintf(p, "%*.*s ", sizeof(decStr) - 1, sizeof(decStr) - 1, decStr);
}
break;
case SQL_TEXT:
str2 = var->value.asChar;
// See if it is character set OCTETS
@ -7955,6 +8035,12 @@ static unsigned process_message_display(Firebird::IMessageMetadata* message, uns
case SQL_DOUBLE:
disp_length = DOUBLE_LEN;
break;
case SQL_DEC64:
disp_length = DECDOUBLE_String - 1;
break;
case SQL_DEC128:
disp_length = DECQUAD_String - 1;
break;
case SQL_TEXT:
alignment = 1;
data_length++;
@ -8598,6 +8684,10 @@ static const char* sqltype_to_string(unsigned sqltype)
return "FLOAT";
case SQL_DOUBLE:
return "DOUBLE";
case SQL_DEC64:
return "DECFLOAT(16)";
case SQL_DEC128:
return "DECFLOAT(34)";
case SQL_D_FLOAT:
return "D_FLOAT";
case SQL_TIMESTAMP:

View File

@ -35,6 +35,7 @@
#include "../jrd/flags.h"
#include <stdlib.h>
#include "../common/DecFloat.h"
// Define lengths used in isql.e
@ -294,6 +295,8 @@ const int BLOB = 261;
//const int SQL_TIME = 13;
const int BIGINT = 16;
const int BOOLEAN_TYPE = 23;
const int DEC64_TYPE = 24;
const int DEC128_TYPE = 25;
static const sqltypes Column_types[] = {
{SMALLINT, "SMALLINT"}, // keyword
@ -311,6 +314,8 @@ static const sqltypes Column_types[] = {
{blr_timestamp, "TIMESTAMP"}, // keyword
{BIGINT, "BIGINT"}, // keyword
{BOOLEAN_TYPE, "BOOLEAN"}, // keyword
{DEC64_TYPE, "DECIMAL(16)"},
{DEC128_TYPE, "DECIMAL(34)"},
{0, ""}
};
@ -379,8 +384,13 @@ public:
USHORT major_ods;
USHORT minor_ods;
USHORT att_charset;
Firebird::DecimalStatus decStatus;
void printf(const char* buffer, ...);
void prints(const char* buffer);
IsqlGlobals()
: decStatus(DEC_Errors)
{ }
};
extern IsqlGlobals isqlGlob;
@ -434,6 +444,8 @@ struct IsqlVar
ISC_QUAD* blobid;
vary* asVary;
char* asChar;
Firebird::Decimal64* asDec64;
Firebird::Decimal128* asDec128;
void* setPtr;
};
TypeMix value;

View File

@ -202,6 +202,7 @@ Jrd::Attachment::Attachment(MemoryPool* pool, Database* dbb)
att_functions(*pool),
att_internal(*pool),
att_dyn_req(*pool),
att_dec_status(DEC_Errors),
att_charsets(*pool),
att_charset_ids(*pool),
att_pools(*pool)

View File

@ -302,6 +302,7 @@ public:
Firebird::Array<JrdStatement*> att_internal; // internal statements
Firebird::Array<JrdStatement*> att_dyn_req; // internal dyn statements
Firebird::ICryptKeyCallback* att_crypt_callback; // callback for DB crypt
Firebird::DecimalStatus att_dec_status; // error handling and rounding
jrd_req* findSystemRequest(thread_db* tdbb, USHORT id, USHORT which);

View File

@ -306,7 +306,7 @@ void DataTypeUtilBase::makeSubstr(dsc* result, const dsc* value, const dsc* offs
if (length->dsc_address) // constant
{
SLONG constant = CVT_get_long(length, 0, ERR_post);
SLONG constant = CVT_get_long(length, 0, JRD_get_thread_data()->getAttachment()->att_dec_status, ERR_post);
fb_assert(constant >= 0);
len = MIN(len, MIN(MAX_STR_SIZE, ULONG(constant)) * maxBytesPerChar(result->getCharSet()));
}

View File

@ -99,6 +99,16 @@ namespace
item.length = sizeof(double);
break;
case dtype_dec64:
item.type = SQL_DEC64;
item.length = sizeof(Decimal64);
break;
case dtype_dec128:
item.type = SQL_DEC128;
item.length = sizeof(Decimal128);
break;
case dtype_sql_date:
item.type = SQL_TYPE_DATE;
item.length = sizeof(SLONG);

View File

@ -107,6 +107,7 @@ double fbcot(double value) throw();
// generic setParams functions
void setParamsDouble(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, int argsCount, dsc** args);
void setParamsDblDec(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, int argsCount, dsc** args);
void setParamsFromList(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, int argsCount, dsc** args);
void setParamsInteger(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, int argsCount, dsc** args);
void setParamsSecondInteger(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, int argsCount, dsc** args);
@ -124,6 +125,7 @@ void setParamsUuidToChar(DataTypeUtilBase* dataTypeUtil, const SysFunction* func
// generic make functions
void makeDoubleResult(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args);
void makeDblDecResult(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args);
void makeFromListResult(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args);
void makeInt64Result(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args);
void makeLongResult(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args);
@ -142,6 +144,7 @@ void makeLeftRight(DataTypeUtilBase* dataTypeUtil, const SysFunction* function,
void makeMod(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args);
void makeOverlay(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args);
void makePad(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args);
void makePi(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args);
void makeReplace(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args);
void makeReverse(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args);
void makeRound(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args);
@ -303,6 +306,38 @@ void setParamsDouble(DataTypeUtilBase*, const SysFunction*, int argsCount, dsc**
}
template <typename DSC>
bool areParamsDouble(int argsCount, DSC** args)
{
bool decSeen = false;
for (int i = 0; i < argsCount; ++i)
{
if (args[i]->isApprox())
return true;
if (args[i]->isDecFloat())
decSeen = true;
}
return !decSeen;
}
void setParamsDblDec(DataTypeUtilBase*, const SysFunction*, int argsCount, dsc** args)
{
bool fDbl = areParamsDouble(argsCount, args);
for (int i = 0; i < argsCount; ++i)
{
if (args[i]->isUnknown())
{
if (fDbl)
args[i]->makeDouble();
else
args[i]->makeDecimal128();
}
}
}
void setParamsFromList(DataTypeUtilBase* dataTypeUtil, const SysFunction* function,
int argsCount, dsc** args)
{
@ -356,7 +391,7 @@ void setParamsDateAdd(DataTypeUtilBase*, const SysFunction*, int argsCount, dsc*
if (argsCount >= 1 && args[0]->isUnknown())
{
if (args[1]->dsc_address && // constant
CVT_get_long(args[1], 0, ERR_post) == blr_extract_millisecond)
CVT_get_long(args[1], 0, JRD_get_thread_data()->getAttachment()->att_dec_status, ERR_post) == blr_extract_millisecond)
{
args[0]->makeInt64(ISC_TIME_SECONDS_PRECISION_SCALE + 3);
}
@ -488,6 +523,30 @@ void makeDoubleResult(DataTypeUtilBase*, const SysFunction*, dsc* result,
}
void makeDblDecResult(DataTypeUtilBase*, const SysFunction*, dsc* result,
int argsCount, const dsc** args)
{
if (argsCount == 0 || areParamsDouble(argsCount, args))
result->makeDouble();
else
result->makeDecimal128();
bool isNullable;
if (initResult(result, argsCount, args, &isNullable))
return;
result->setNullable(isNullable);
}
void makePi(DataTypeUtilBase*, const SysFunction*, dsc* result, int, const dsc**)
{
result->makeDecimal128();
result->clearNull();
result->setNullable(false);
}
void makeFromListResult(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result,
int argsCount, const dsc** args)
{
@ -593,6 +652,8 @@ void makeAbs(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* r
case dtype_real:
case dtype_double:
case dtype_int64:
case dtype_dec64:
case dtype_dec128:
*result = *value;
break;
@ -734,6 +795,11 @@ void makeCeilFloor(DataTypeUtilBase*, const SysFunction* function, dsc* result,
result->makeInt64(0);
break;
case dtype_dec128:
case dtype_dec64:
result->makeDecimal128(0);
break;
default:
result->makeDouble();
break;
@ -906,7 +972,7 @@ void makePad(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* r
if (length->dsc_address) // constant
{
result->dsc_length = static_cast<USHORT>(sizeof(USHORT)) + dataTypeUtil->fixLength(result,
CVT_get_long(length, 0, ERR_post) *
CVT_get_long(length, 0, JRD_get_thread_data()->getAttachment()->att_dec_status, ERR_post) *
dataTypeUtil->maxBytesPerChar(result->getCharSet()));
}
else
@ -1017,7 +1083,8 @@ void makeRound(DataTypeUtilBase*, const SysFunction* function, dsc* result,
return;
}
if (value1->isExact() || value1->dsc_dtype == dtype_real || value1->dsc_dtype == dtype_double)
if (value1->isExact() || value1->dsc_dtype == dtype_real || value1->dsc_dtype == dtype_double ||
value1->dsc_dtype == dtype_dec64 || value1->dsc_dtype == dtype_dec128)
{
*result = *value1;
if (argsCount == 1)
@ -1109,7 +1176,7 @@ dsc* evlStdMath(thread_db* tdbb, const SysFunction* function, const NestValueArr
if (request->req_flags & req_null) // return NULL if value is NULL
return NULL;
const double v = MOV_get_double(value);
const double v = MOV_get_double(tdbb, value);
double rc;
// CVC: Apparently, gcc has built-in inverse hyperbolic functions, but since
@ -1221,10 +1288,18 @@ dsc* evlAbs(thread_db* tdbb, const SysFunction*, const NestValueArray& args, imp
impure->vlu_misc.vlu_double = fabs(impure->vlu_misc.vlu_double);
break;
case dtype_dec64:
impure->vlu_misc.vlu_dec64 = impure->vlu_misc.vlu_dec64.abs();
break;
case dtype_dec128:
impure->vlu_misc.vlu_dec128 = impure->vlu_misc.vlu_dec128.abs();
break;
case dtype_short:
case dtype_long:
case dtype_int64:
impure->vlu_misc.vlu_int64 = MOV_get_int64(value, value->dsc_scale);
impure->vlu_misc.vlu_int64 = MOV_get_int64(tdbb, value, value->dsc_scale);
if (impure->vlu_misc.vlu_int64 == MIN_SINT64)
status_exception::raise(Arg::Gds(isc_arith_except) << Arg::Gds(isc_numeric_out_of_range));
@ -1235,7 +1310,7 @@ dsc* evlAbs(thread_db* tdbb, const SysFunction*, const NestValueArray& args, imp
break;
default:
impure->vlu_misc.vlu_double = fabs(MOV_get_double(&impure->vlu_desc));
impure->vlu_misc.vlu_double = fabs(MOV_get_double(tdbb, &impure->vlu_desc));
impure->vlu_desc.makeDouble(&impure->vlu_misc.vlu_double);
break;
}
@ -1255,7 +1330,7 @@ dsc* evlAsciiChar(thread_db* tdbb, const SysFunction*, const NestValueArray& arg
if (request->req_flags & req_null) // return NULL if value is NULL
return NULL;
const SLONG code = MOV_get_long(value, 0);
const SLONG code = MOV_get_long(tdbb, value, 0);
if (!(code >= 0 && code <= 255))
status_exception::raise(Arg::Gds(isc_arith_except) << Arg::Gds(isc_numeric_out_of_range));
@ -1316,8 +1391,8 @@ dsc* evlAtan2(thread_db* tdbb, const SysFunction* function, const NestValueArray
if (request->req_flags & req_null) // return NULL if desc2 is NULL
return NULL;
double value1 = MOV_get_double(desc1);
double value2 = MOV_get_double(desc2);
double value1 = MOV_get_double(tdbb, desc1);
double value2 = MOV_get_double(tdbb, desc2);
if (value1 == 0 && value2 == 0)
{
@ -1349,24 +1424,24 @@ dsc* evlBin(thread_db* tdbb, const SysFunction* function, const NestValueArray&
if (i == 0)
{
if ((Function)(IPTR) function->misc == funBinNot)
impure->vlu_misc.vlu_int64 = ~MOV_get_int64(value, 0);
impure->vlu_misc.vlu_int64 = ~MOV_get_int64(tdbb, value, 0);
else
impure->vlu_misc.vlu_int64 = MOV_get_int64(value, 0);
impure->vlu_misc.vlu_int64 = MOV_get_int64(tdbb, value, 0);
}
else
{
switch ((Function)(IPTR) function->misc)
{
case funBinAnd:
impure->vlu_misc.vlu_int64 &= MOV_get_int64(value, 0);
impure->vlu_misc.vlu_int64 &= MOV_get_int64(tdbb, value, 0);
break;
case funBinOr:
impure->vlu_misc.vlu_int64 |= MOV_get_int64(value, 0);
impure->vlu_misc.vlu_int64 |= MOV_get_int64(tdbb, value, 0);
break;
case funBinXor:
impure->vlu_misc.vlu_int64 ^= MOV_get_int64(value, 0);
impure->vlu_misc.vlu_int64 ^= MOV_get_int64(tdbb, value, 0);
break;
default:
@ -1397,7 +1472,7 @@ dsc* evlBinShift(thread_db* tdbb, const SysFunction* function, const NestValueAr
if (request->req_flags & req_null) // return NULL if value2 is NULL
return NULL;
const SINT64 shift = MOV_get_int64(value2, 0);
const SINT64 shift = MOV_get_int64(tdbb, value2, 0);
if (shift < 0)
{
status_exception::raise(Arg::Gds(isc_expression_eval_err) <<
@ -1407,7 +1482,7 @@ dsc* evlBinShift(thread_db* tdbb, const SysFunction* function, const NestValueAr
const SINT64 rotshift = shift % sizeof(SINT64);
SINT64 tempbits = 0;
const SINT64 target = MOV_get_int64(value1, 0);
const SINT64 target = MOV_get_int64(tdbb, value1, 0);
switch ((Function)(IPTR) function->misc)
{
@ -1464,8 +1539,8 @@ dsc* evlCeil(thread_db* tdbb, const SysFunction*, const NestValueArray& args,
for (int i = -impure->vlu_desc.dsc_scale; i > 0; --i)
scale *= 10;
const SINT64 v1 = MOV_get_int64(&impure->vlu_desc, impure->vlu_desc.dsc_scale);
const SINT64 v2 = MOV_get_int64(&impure->vlu_desc, 0) * scale;
const SINT64 v1 = MOV_get_int64(tdbb, &impure->vlu_desc, impure->vlu_desc.dsc_scale);
const SINT64 v2 = MOV_get_int64(tdbb, &impure->vlu_desc, 0) * scale;
impure->vlu_misc.vlu_int64 = v1 / scale;
@ -1481,13 +1556,23 @@ dsc* evlCeil(thread_db* tdbb, const SysFunction*, const NestValueArray& args,
break;
default:
impure->vlu_misc.vlu_double = MOV_get_double(&impure->vlu_desc);
impure->vlu_misc.vlu_double = MOV_get_double(tdbb, &impure->vlu_desc);
// fall through
case dtype_double:
impure->vlu_misc.vlu_double = ceil(impure->vlu_misc.vlu_double);
impure->vlu_desc.makeDouble(&impure->vlu_misc.vlu_double);
break;
case dtype_dec64:
impure->vlu_misc.vlu_dec64 = impure->vlu_misc.vlu_dec64.ceil(tdbb->getAttachment()->att_dec_status);
impure->vlu_desc.makeDecimal64(&impure->vlu_misc.vlu_dec64);
break;
case dtype_dec128:
impure->vlu_misc.vlu_dec128 = impure->vlu_misc.vlu_dec128.ceil(tdbb->getAttachment()->att_dec_status);
impure->vlu_desc.makeDecimal128(&impure->vlu_misc.vlu_dec128);
break;
}
return &impure->vlu_desc;
@ -1520,7 +1605,7 @@ dsc* evlCharToUuid(thread_db* tdbb, const SysFunction* function, const NestValue
}
UCHAR* data_temp;
USHORT len = MOV_get_string(value, &data_temp, NULL, 0);
USHORT len = MOV_get_string(tdbb, value, &data_temp, NULL, 0);
const UCHAR* data;
if (len > GUID_BODY_SIZE)
@ -1649,7 +1734,7 @@ dsc* evlDateAdd(thread_db* tdbb, const SysFunction* function, const NestValueArr
if (request->req_flags & req_null) // return NULL if valueDsc is NULL
return NULL;
const SLONG part = MOV_get_long(partDsc, 0);
const SLONG part = MOV_get_long(tdbb, partDsc, 0);
TimeStamp timestamp;
@ -1699,7 +1784,7 @@ dsc* evlDateAdd(thread_db* tdbb, const SysFunction* function, const NestValueArr
static const SSHORT milliScale = ISC_TIME_SECONDS_PRECISION_SCALE + 3;
static const int milliPow = NoThrowTimeStamp::POW_10_TABLE[-milliScale];
const SINT64 quantity = MOV_get_int64(quantityDsc,
const SINT64 quantity = MOV_get_int64(tdbb, quantityDsc,
(part == blr_extract_millisecond ? milliScale : 0));
switch (part)
@ -1909,7 +1994,7 @@ dsc* evlDateDiff(thread_db* tdbb, const SysFunction* function, const NestValueAr
timestamp1.decode(&times1);
timestamp2.decode(&times2);
const SLONG part = MOV_get_long(partDsc, 0);
const SLONG part = MOV_get_long(tdbb, partDsc, 0);
switch (part)
{
@ -2060,7 +2145,19 @@ dsc* evlExp(thread_db* tdbb, const SysFunction*, const NestValueArray& args,
if (request->req_flags & req_null) // return NULL if value is NULL
return NULL;
const double rc = exp(MOV_get_double(value));
if (value->isDecFloat())
{
DecimalStatus decSt = tdbb->getAttachment()->att_dec_status;
impure->vlu_misc.vlu_dec128 = MOV_get_dec128(tdbb, value);
Decimal128 e;
e.set("2.718281828459045235360287471352662497757", decSt);
impure->vlu_misc.vlu_dec128 = e.pow(decSt, impure->vlu_misc.vlu_dec128);
impure->vlu_desc.makeDecimal128(&impure->vlu_misc.vlu_dec128);
}
else
{
const double rc = exp(MOV_get_double(tdbb, value));
if (rc == HUGE_VAL) // unlikely to trap anything
status_exception::raise(Arg::Gds(isc_arith_except) << Arg::Gds(isc_exception_float_overflow));
if (isinf(rc))
@ -2068,6 +2165,7 @@ dsc* evlExp(thread_db* tdbb, const SysFunction*, const NestValueArray& args,
impure->vlu_misc.vlu_double = rc;
impure->vlu_desc.makeDouble(&impure->vlu_misc.vlu_double);
}
return &impure->vlu_desc;
}
@ -2098,8 +2196,8 @@ dsc* evlFloor(thread_db* tdbb, const SysFunction*, const NestValueArray& args,
for (int i = -impure->vlu_desc.dsc_scale; i > 0; --i)
scale *= 10;
const SINT64 v1 = MOV_get_int64(&impure->vlu_desc, impure->vlu_desc.dsc_scale);
const SINT64 v2 = MOV_get_int64(&impure->vlu_desc, 0) * scale;
const SINT64 v1 = MOV_get_int64(tdbb, &impure->vlu_desc, impure->vlu_desc.dsc_scale);
const SINT64 v2 = MOV_get_int64(tdbb, &impure->vlu_desc, 0) * scale;
impure->vlu_misc.vlu_int64 = v1 / scale;
@ -2115,13 +2213,23 @@ dsc* evlFloor(thread_db* tdbb, const SysFunction*, const NestValueArray& args,
break;
default:
impure->vlu_misc.vlu_double = MOV_get_double(&impure->vlu_desc);
impure->vlu_misc.vlu_double = MOV_get_double(tdbb, &impure->vlu_desc);
// fall through
case dtype_double:
impure->vlu_misc.vlu_double = floor(impure->vlu_misc.vlu_double);
impure->vlu_desc.makeDouble(&impure->vlu_misc.vlu_double);
break;
case dtype_dec64:
impure->vlu_misc.vlu_dec64 = impure->vlu_misc.vlu_dec64.floor(tdbb->getAttachment()->att_dec_status);
impure->vlu_desc.makeDecimal64(&impure->vlu_misc.vlu_dec64);
break;
case dtype_dec128:
impure->vlu_misc.vlu_dec128 = impure->vlu_misc.vlu_dec128.floor(tdbb->getAttachment()->att_dec_status);
impure->vlu_desc.makeDecimal128(&impure->vlu_misc.vlu_dec128);
break;
}
return &impure->vlu_desc;
@ -2560,7 +2668,37 @@ dsc* evlLnLog10(thread_db* tdbb, const SysFunction* function, const NestValueArr
if (request->req_flags & req_null) // return NULL if value is NULL
return NULL;
const double v = MOV_get_double(value);
if (value->isDecFloat())
{
DecimalStatus decSt = tdbb->getAttachment()->att_dec_status;
Decimal128 d = MOV_get_dec128(tdbb, value);
if (d.compare(decSt, CDecimal128(0)) <= 0)
{
status_exception::raise(Arg::Gds(isc_expression_eval_err) <<
Arg::Gds(isc_sysf_argmustbe_positive) <<
Arg::Str(function->name));
}
switch ((Function)(IPTR) function->misc)
{
case funLnat:
d = d.ln(decSt);
break;
case funLog10:
d = d.log10(decSt);
break;
default:
fb_assert(0);
return NULL;
}
impure->vlu_misc.vlu_dec128 = d;
impure->vlu_desc.makeDecimal128(&impure->vlu_misc.vlu_dec128);
}
else
{
const double v = MOV_get_double(tdbb, value);
if (v <= 0)
{
@ -2586,6 +2724,7 @@ dsc* evlLnLog10(thread_db* tdbb, const SysFunction* function, const NestValueArr
impure->vlu_misc.vlu_double = rc;
impure->vlu_desc.makeDouble(&impure->vlu_misc.vlu_double);
}
return &impure->vlu_desc;
}
@ -2598,16 +2737,42 @@ dsc* evlLog(thread_db* tdbb, const SysFunction* function, const NestValueArray&
jrd_req* request = tdbb->getRequest();
const dsc* value1 = EVL_expr(tdbb, request, args[0]);
if (request->req_flags & req_null) // return NULL if value1 is NULL
const dsc* value[2];
value[0] = EVL_expr(tdbb, request, args[0]);
if (request->req_flags & req_null) // return NULL if value is NULL
return NULL;
const dsc* value2 = EVL_expr(tdbb, request, args[1]);
if (request->req_flags & req_null) // return NULL if value2 is NULL
value[1] = EVL_expr(tdbb, request, args[1]);
if (request->req_flags & req_null) // return NULL if value is NULL
return NULL;
const double v1 = MOV_get_double(value1);
const double v2 = MOV_get_double(value2);
if (!areParamsDouble(2, value))
{
DecimalStatus decSt = tdbb->getAttachment()->att_dec_status;
Decimal128 v1 = MOV_get_dec128(tdbb, value[0]);
Decimal128 v2 = MOV_get_dec128(tdbb, value[1]);
if (v1.compare(decSt, CDecimal128(0)) <= 0)
{
status_exception::raise(Arg::Gds(isc_expression_eval_err) <<
Arg::Gds(isc_sysf_basemustbe_positive) <<
Arg::Str(function->name));
}
if (v2.compare(decSt, CDecimal128(0)) <= 0)
{
status_exception::raise(Arg::Gds(isc_expression_eval_err) <<
Arg::Gds(isc_sysf_argmustbe_positive) <<
Arg::Str(function->name));
}
impure->vlu_misc.vlu_dec128 = v2.ln(decSt).div(decSt, v1.ln(decSt));
impure->vlu_desc.makeDecimal128(&impure->vlu_misc.vlu_dec128);
}
else
{
const double v1 = MOV_get_double(tdbb, value[0]);
const double v2 = MOV_get_double(tdbb, value[1]);
if (v1 <= 0)
{
@ -2625,6 +2790,7 @@ dsc* evlLog(thread_db* tdbb, const SysFunction* function, const NestValueArray&
impure->vlu_misc.vlu_double = log(v2) / log(v1);
impure->vlu_desc.makeDouble(&impure->vlu_misc.vlu_double);
}
return &impure->vlu_desc;
}
@ -2652,12 +2818,12 @@ dsc* evlMaxMinValue(thread_db* tdbb, const SysFunction* function, const NestValu
switch ((Function)(IPTR) function->misc)
{
case funMaxValue:
if (MOV_compare(value, result) > 0)
if (MOV_compare(tdbb, value, result) > 0)
result = value;
break;
case funMinValue:
if (MOV_compare(value, result) < 0)
if (MOV_compare(tdbb, value, result) < 0)
result = value;
break;
@ -2689,12 +2855,12 @@ dsc* evlMod(thread_db* tdbb, const SysFunction*, const NestValueArray& args,
EVL_make_value(tdbb, value1, impure);
impure->vlu_desc.dsc_scale = 0;
const SINT64 divisor = MOV_get_int64(value2, 0);
const SINT64 divisor = MOV_get_int64(tdbb, value2, 0);
if (divisor == 0)
status_exception::raise(Arg::Gds(isc_arith_except) << Arg::Gds(isc_exception_integer_divide_by_zero));
const SINT64 result = MOV_get_int64(value1, 0) % divisor;
const SINT64 result = MOV_get_int64(tdbb, value1, 0) % divisor;
switch (impure->vlu_desc.dsc_dtype)
{
@ -2748,7 +2914,7 @@ dsc* evlOverlay(thread_db* tdbb, const SysFunction* function, const NestValueArr
if (request->req_flags & req_null) // return NULL if lengthDsc is NULL
return NULL;
const SLONG auxlen = MOV_get_long(lengthDsc, 0);
const SLONG auxlen = MOV_get_long(tdbb, lengthDsc, 0);
if (auxlen < 0)
{
@ -2761,7 +2927,7 @@ dsc* evlOverlay(thread_db* tdbb, const SysFunction* function, const NestValueArr
length = auxlen;
}
SLONG from = MOV_get_long(fromDsc, 0);
SLONG from = MOV_get_long(tdbb, fromDsc, 0);
if (from <= 0)
{
@ -2919,7 +3085,7 @@ dsc* evlPad(thread_db* tdbb, const SysFunction* function, const NestValueArray&
if (request->req_flags & req_null) // return NULL if padLenDsc is NULL
return NULL;
const SLONG padLenArg = MOV_get_long(padLenDsc, 0);
const SLONG padLenArg = MOV_get_long(tdbb, padLenDsc, 0);
if (padLenArg < 0)
{
status_exception::raise(Arg::Gds(isc_expression_eval_err) <<
@ -3067,13 +3233,14 @@ dsc* evlPad(thread_db* tdbb, const SysFunction* function, const NestValueArray&
}
dsc* evlPi(thread_db* /*tdbb*/, const SysFunction*, const NestValueArray& args,
dsc* evlPi(thread_db* tdbb, const SysFunction*, const NestValueArray& args,
impure_value* impure)
{
fb_assert(args.getCount() == 0);
impure->vlu_misc.vlu_double = 3.14159265358979323846;
impure->vlu_desc.makeDouble(&impure->vlu_misc.vlu_double);
impure->vlu_misc.vlu_dec128.set("3.141592653589793238462643383279502884197",
tdbb->getAttachment()->att_dec_status);
impure->vlu_desc.makeDecimal128(&impure->vlu_misc.vlu_dec128);
return &impure->vlu_desc;
}
@ -3102,7 +3269,7 @@ dsc* evlPosition(thread_db* tdbb, const SysFunction* function, const NestValueAr
if (request->req_flags & req_null) // return NULL if value3 is NULL
return NULL;
start = MOV_get_long(value3, 0);
start = MOV_get_long(tdbb, value3, 0);
if (start <= 0)
{
status_exception::raise(Arg::Gds(isc_expression_eval_err) <<
@ -3212,18 +3379,30 @@ dsc* evlPower(thread_db* tdbb, const SysFunction* function, const NestValueArray
jrd_req* request = tdbb->getRequest();
const dsc* value1 = EVL_expr(tdbb, request, args[0]);
if (request->req_flags & req_null) // return NULL if value1 is NULL
const dsc* value[2];
value[0] = EVL_expr(tdbb, request, args[0]);
if (request->req_flags & req_null) // return NULL if value is NULL
return NULL;
const dsc* value2 = EVL_expr(tdbb, request, args[1]);
if (request->req_flags & req_null) // return NULL if value2 is NULL
value[1] = EVL_expr(tdbb, request, args[1]);
if (request->req_flags & req_null) // return NULL if value is NULL
return NULL;
if (!areParamsDouble(2, value))
{
DecimalStatus decSt = tdbb->getAttachment()->att_dec_status;
impure->vlu_misc.vlu_dec128 = MOV_get_dec128(tdbb, value[0]);
Decimal128 v2 = MOV_get_dec128(tdbb, value[1]);
impure->vlu_misc.vlu_dec128 = impure->vlu_misc.vlu_dec128.pow(decSt, v2);
impure->vlu_desc.makeDecimal128(&impure->vlu_misc.vlu_dec128);
}
else
{
impure->vlu_desc.makeDouble(&impure->vlu_misc.vlu_double);
const double v1 = MOV_get_double(value1);
const double v2 = MOV_get_double(value2);
const double v1 = MOV_get_double(tdbb, value[0]);
const double v2 = MOV_get_double(tdbb, value[1]);
if (v1 == 0 && v2 < 0)
{
@ -3233,9 +3412,9 @@ dsc* evlPower(thread_db* tdbb, const SysFunction* function, const NestValueArray
}
if (v1 < 0 &&
(!value2->isExact() ||
MOV_get_int64(value2, 0) * SINT64(CVT_power_of_ten(-value2->dsc_scale)) !=
MOV_get_int64(value2, value2->dsc_scale)))
(!value[1]->isExact() ||
MOV_get_int64(tdbb, value[1], 0) * SINT64(CVT_power_of_ten(-value[1]->dsc_scale)) !=
MOV_get_int64(tdbb, value[1], value[1]->dsc_scale)))
{
status_exception::raise(Arg::Gds(isc_expression_eval_err) <<
Arg::Gds(isc_sysf_invalid_negpowfp) <<
@ -3247,6 +3426,7 @@ dsc* evlPower(thread_db* tdbb, const SysFunction* function, const NestValueArray
status_exception::raise(Arg::Gds(isc_arith_except) << Arg::Gds(isc_exception_float_overflow));
impure->vlu_misc.vlu_double = rc;
}
return &impure->vlu_desc;
}
@ -3572,7 +3752,7 @@ dsc* evlRight(thread_db* tdbb, const SysFunction*, const NestValueArray& args,
start = charSet->length(start, p, true);
}
start -= MOV_get_long(len, 0);
start -= MOV_get_long(tdbb, len, 0);
start = MAX(0, start);
dsc startDsc;
@ -3601,7 +3781,7 @@ dsc* evlRound(thread_db* tdbb, const SysFunction* function, const NestValueArray
if (request->req_flags & req_null) // return NULL if scaleDsc is NULL
return NULL;
scale = -MOV_get_long(scaleDsc, 0);
scale = -MOV_get_long(tdbb, scaleDsc, 0);
if (!(scale >= MIN_SCHAR && scale <= MAX_SCHAR))
{
status_exception::raise(Arg::Gds(isc_expression_eval_err) <<
@ -3610,7 +3790,7 @@ dsc* evlRound(thread_db* tdbb, const SysFunction* function, const NestValueArray
}
}
impure->vlu_misc.vlu_int64 = MOV_get_int64(value, scale);
impure->vlu_misc.vlu_int64 = MOV_get_int64(tdbb, value, scale);
impure->vlu_desc.makeInt64(scale, &impure->vlu_misc.vlu_int64);
return &impure->vlu_desc;
@ -3628,7 +3808,7 @@ dsc* evlSign(thread_db* tdbb, const SysFunction*, const NestValueArray& args,
if (request->req_flags & req_null) // return NULL if value is NULL
return NULL;
const double val = MOV_get_double(value);
const double val = MOV_get_double(tdbb, value);
if (val > 0)
impure->vlu_misc.vlu_short = 1;
@ -3654,7 +3834,23 @@ dsc* evlSqrt(thread_db* tdbb, const SysFunction* function, const NestValueArray&
if (request->req_flags & req_null) // return NULL if value is NULL
return NULL;
impure->vlu_misc.vlu_double = MOV_get_double(value);
if (value->isDecFloat())
{
DecimalStatus decSt = tdbb->getAttachment()->att_dec_status;
impure->vlu_misc.vlu_dec128 = MOV_get_dec128(tdbb, value);
if (impure->vlu_misc.vlu_dec128.compare(decSt, CDecimal128(0)) < 0)
{
status_exception::raise(Arg::Gds(isc_expression_eval_err) <<
Arg::Gds(isc_sysf_argmustbe_nonneg) << Arg::Str(function->name));
}
impure->vlu_misc.vlu_dec128 = impure->vlu_misc.vlu_dec128.sqrt(decSt);
impure->vlu_desc.makeDecimal128(&impure->vlu_misc.vlu_dec128);
}
else
{
impure->vlu_misc.vlu_double = MOV_get_double(tdbb, value);
if (impure->vlu_misc.vlu_double < 0)
{
@ -3664,6 +3860,7 @@ dsc* evlSqrt(thread_db* tdbb, const SysFunction* function, const NestValueArray&
impure->vlu_misc.vlu_double = sqrt(impure->vlu_misc.vlu_double);
impure->vlu_desc.makeDouble(&impure->vlu_misc.vlu_double);
}
return &impure->vlu_desc;
}
@ -3687,7 +3884,7 @@ dsc* evlTrunc(thread_db* tdbb, const SysFunction* function, const NestValueArray
if (request->req_flags & req_null) // return NULL if scaleDsc is NULL
return NULL;
resultScale = -MOV_get_long(scaleDsc, 0);
resultScale = -MOV_get_long(tdbb, scaleDsc, 0);
if (!(resultScale >= MIN_SCHAR && resultScale <= MAX_SCHAR))
{
status_exception::raise(Arg::Gds(isc_expression_eval_err) <<
@ -3699,7 +3896,7 @@ dsc* evlTrunc(thread_db* tdbb, const SysFunction* function, const NestValueArray
if (value->isExact())
{
SSHORT scale = value->dsc_scale;
impure->vlu_misc.vlu_int64 = MOV_get_int64(value, scale);
impure->vlu_misc.vlu_int64 = MOV_get_int64(tdbb, value, scale);
if (resultScale < scale)
resultScale = scale;
@ -3719,7 +3916,7 @@ dsc* evlTrunc(thread_db* tdbb, const SysFunction* function, const NestValueArray
}
else
{
impure->vlu_misc.vlu_double = MOV_get_double(value);
impure->vlu_misc.vlu_double = MOV_get_double(tdbb, value);
SINT64 v = 1;
@ -3775,7 +3972,7 @@ dsc* evlUuidToChar(thread_db* tdbb, const SysFunction* function, const NestValue
}
UCHAR* data;
const USHORT len = MOV_get_string(value, &data, NULL, 0);
const USHORT len = MOV_get_string(tdbb, value, &data, NULL, 0);
if (len != sizeof(Guid))
{
@ -3849,7 +4046,7 @@ dsc* evlSystemPrivilege(thread_db* tdbb, const SysFunction*, const NestValueArra
const SysFunction SysFunction::functions[] =
{
{"ABS", 1, 1, setParamsDouble, makeAbs, evlAbs, NULL},
{"ABS", 1, 1, setParamsDblDec, makeAbs, evlAbs, NULL},
{"ACOS", 1, 1, setParamsDouble, makeDoubleResult, evlStdMath, (void*) trfAcos},
{"ACOSH", 1, 1, setParamsDouble, makeDoubleResult, evlStdMath, (void*) trfAcosh},
{"ASCII_CHAR", 1, 1, setParamsInteger, makeAsciiChar, evlAsciiChar, NULL},
@ -3867,30 +4064,30 @@ const SysFunction SysFunction::functions[] =
{"BIN_SHL_ROT", 2, 2, setParamsInteger, makeBinShift, evlBinShift, (void*) funBinShlRot},
{"BIN_SHR_ROT", 2, 2, setParamsInteger, makeBinShift, evlBinShift, (void*) funBinShrRot},
{"BIN_XOR", 2, -1, setParamsInteger, makeBin, evlBin, (void*) funBinXor},
{"CEIL", 1, 1, setParamsDouble, makeCeilFloor, evlCeil, NULL},
{"CEILING", 1, 1, setParamsDouble, makeCeilFloor, evlCeil, NULL},
{"CEIL", 1, 1, setParamsDblDec, makeCeilFloor, evlCeil, NULL},
{"CEILING", 1, 1, setParamsDblDec, makeCeilFloor, evlCeil, NULL},
{"CHAR_TO_UUID", 1, 1, setParamsCharToUuid, makeUuid, evlCharToUuid, NULL},
{"COS", 1, 1, setParamsDouble, makeDoubleResult, evlStdMath, (void*) trfCos},
{"COSH", 1, 1, setParamsDouble, makeDoubleResult, evlStdMath, (void*) trfCosh},
{"COT", 1, 1, setParamsDouble, makeDoubleResult, evlStdMath, (void*) trfCot},
{"DATEADD", 3, 3, setParamsDateAdd, makeDateAdd, evlDateAdd, NULL},
{"DATEDIFF", 3, 3, setParamsDateDiff, makeInt64Result, evlDateDiff, NULL},
{"EXP", 1, 1, setParamsDouble, makeDoubleResult, evlExp, NULL},
{"FLOOR", 1, 1, setParamsDouble, makeCeilFloor, evlFloor, NULL},
{"EXP", 1, 1, setParamsDblDec, makeDblDecResult, evlExp, NULL},
{"FLOOR", 1, 1, setParamsDblDec, makeCeilFloor, evlFloor, NULL},
{"GEN_UUID", 0, 0, NULL, makeUuid, evlGenUuid, NULL},
{"HASH", 1, 1, NULL, makeInt64Result, evlHash, NULL},
{"LEFT", 2, 2, setParamsSecondInteger, makeLeftRight, evlLeft, NULL},
{"LN", 1, 1, setParamsDouble, makeDoubleResult, evlLnLog10, (void*) funLnat},
{"LOG", 2, 2, setParamsDouble, makeDoubleResult, evlLog, NULL},
{"LOG10", 1, 1, setParamsDouble, makeDoubleResult, evlLnLog10, (void*) funLog10},
{"LN", 1, 1, setParamsDblDec, makeDblDecResult, evlLnLog10, (void*) funLnat},
{"LOG", 2, 2, setParamsDblDec, makeDblDecResult, evlLog, NULL},
{"LOG10", 1, 1, setParamsDblDec, makeDblDecResult, evlLnLog10, (void*) funLog10},
{"LPAD", 2, 3, setParamsSecondInteger, makePad, evlPad, (void*) funLPad},
{"MAXVALUE", 1, -1, setParamsFromList, makeFromListResult, evlMaxMinValue, (void*) funMaxValue},
{"MINVALUE", 1, -1, setParamsFromList, makeFromListResult, evlMaxMinValue, (void*) funMinValue},
{"MOD", 2, 2, setParamsFromList, makeMod, evlMod, NULL},
{"OVERLAY", 3, 4, setParamsOverlay, makeOverlay, evlOverlay, NULL},
{"PI", 0, 0, NULL, makeDoubleResult, evlPi, NULL},
{"PI", 0, 0, NULL, makePi, evlPi, NULL},
{"POSITION", 2, 3, setParamsPosition, makeLongResult, evlPosition, NULL},
{"POWER", 2, 2, setParamsDouble, makeDoubleResult, evlPower, NULL},
{"POWER", 2, 2, setParamsDblDec, makeDblDecResult, evlPower, NULL},
{"RAND", 0, 0, NULL, makeDoubleResult, evlRand, NULL},
{RDB_GET_CONTEXT, 2, 2, setParamsGetSetContext, makeGetSetContext, evlGetContext, NULL},
{"RDB$ROLE_IN_USE", 1, 1, setParamsAsciiVal, makeBooleanResult, evlRoleInUse, NULL},
@ -3901,10 +4098,10 @@ const SysFunction SysFunction::functions[] =
{"RIGHT", 2, 2, setParamsSecondInteger, makeLeftRight, evlRight, NULL},
{"ROUND", 1, 2, setParamsRoundTrunc, makeRound, evlRound, NULL},
{"RPAD", 2, 3, setParamsSecondInteger, makePad, evlPad, (void*) funRPad},
{"SIGN", 1, 1, setParamsDouble, makeShortResult, evlSign, NULL},
{"SIGN", 1, 1, setParamsDblDec, makeShortResult, evlSign, NULL},
{"SIN", 1, 1, setParamsDouble, makeDoubleResult, evlStdMath, (void*) trfSin},
{"SINH", 1, 1, setParamsDouble, makeDoubleResult, evlStdMath, (void*) trfSinh},
{"SQRT", 1, 1, setParamsDouble, makeDoubleResult, evlSqrt, NULL},
{"SQRT", 1, 1, setParamsDblDec, makeDblDecResult, evlSqrt, NULL},
{"TAN", 1, 1, setParamsDouble, makeDoubleResult, evlStdMath, (void*) trfTan},
{"TANH", 1, 1, setParamsDouble, makeDoubleResult, evlStdMath, (void*) trfTanh},
{"TRUNC", 1, 2, setParamsRoundTrunc, makeTrunc, evlTrunc, NULL},

View File

@ -70,7 +70,7 @@ void VirtualTable::erase(thread_db* tdbb, record_param* rpb)
// Ignore attempt to stop system attachment
dsc sysFlag;
if (EVL_field(relation, rpb->rpb_record, f_mon_att_sys_flag, &sysFlag) &&
MOV_get_long(&sysFlag, 0) != 0)
MOV_get_long(tdbb, &sysFlag, 0) != 0)
{
return;
}
@ -90,7 +90,7 @@ void VirtualTable::erase(thread_db* tdbb, record_param* rpb)
return;
}
const SINT64 id = MOV_get_int64(&desc, 0);
const SINT64 id = MOV_get_int64(tdbb, &desc, 0);
// Post a blocking request
Lock temp_lock(tdbb, sizeof(SINT64), lock_type);

View File

@ -32,6 +32,7 @@
Maximum alignments for corresponding data types are defined in dsc.h
*/
#include "../common/DecFloat.h"
#include "../jrd/blr.h"
/* The following macro must be defined as the highest-numericly-valued
@ -67,7 +68,9 @@ static const USHORT gds_cvt_blr_dtype[DTYPE_BLR_MAX + 1] =
dtype_int64, /* blr_int64 == 16 */
0, 0, 0, 0, 0, 0,
dtype_boolean, // blr_bool == 23
0, 0, 0,
dtype_dec64, /* blr_dec64 == 24 */
dtype_dec128, /* blr_dec128 == 25 */
0,
dtype_double, /* blr_double == 27 */
0, 0, 0, 0, 0, 0, 0,
dtype_timestamp, /* blr_timestamp == 35 */
@ -103,7 +106,9 @@ static const USHORT type_alignments[DTYPE_TYPE_MAX] =
sizeof(SLONG), /* dtype_array */
sizeof(SINT64), /* dtype_int64 */
sizeof(ULONG), /* dtype_dbkey */
sizeof(UCHAR) /* dtype_boolean */
sizeof(UCHAR), /* dtype_boolean */
sizeof(Firebird::Decimal64),/* dtype_dec64 */
sizeof(Firebird::Decimal64) /* dtype_dec128 */
};
static const USHORT type_lengths[DTYPE_TYPE_MAX] =
@ -129,7 +134,9 @@ static const USHORT type_lengths[DTYPE_TYPE_MAX] =
sizeof(ISC_QUAD), /* dtype_array */
sizeof(SINT64), /* dtype_int64 */
sizeof(RecordNumber::Packed), /*dtype_dbkey */
sizeof(UCHAR) /* dtype_boolean */
sizeof(UCHAR), /* dtype_boolean */
sizeof(Firebird::Decimal64),/* dtype_dec64 */
sizeof(Firebird::Decimal128)/* dtype_dec128 */
};
@ -158,7 +165,9 @@ static const USHORT type_significant_bits[DTYPE_TYPE_MAX] =
sizeof(ISC_QUAD) * 8, /* dtype_array */
sizeof(SINT64) * 8, /* dtype_int64 */
0, // dtype_dbkey
0 // dtype_boolean
0, // dtype_boolean
0, // dtype_dec64
0 // dtype_dec128
};
#endif /* JRD_ALIGN_H */

View File

@ -2791,7 +2791,7 @@ static void slice_callback(array_slice* arg, ULONG /*count*/, DSC* descriptors)
DynamicVaryStr<1024> tmp_buffer;
const USHORT tmp_len = array_desc->dsc_length;
const char* p;
const USHORT len = MOV_make_string(slice_desc, INTL_TEXT_TYPE(*array_desc), &p,
const USHORT len = MOV_make_string(tdbb, slice_desc, INTL_TEXT_TYPE(*array_desc), &p,
tmp_buffer.getBuffer(tmp_len), tmp_len);
memcpy(array_desc->dsc_address, &len, sizeof(USHORT));
memcpy(array_desc->dsc_address + sizeof(USHORT), p, (int) len);

View File

@ -67,6 +67,8 @@
#define blr_column_name (unsigned char)21
#define blr_column_name2 (unsigned char)22
#define blr_bool (unsigned char)23
#define blr_dec64 (unsigned char)24
#define blr_dec128 (unsigned char)25
// first sub parameter for blr_domain_name[2]
#define blr_domain_type_of (unsigned char)0

View File

@ -2218,7 +2218,7 @@ bool BTR_types_comparable(const dsc& target, const dsc& source)
return (source.dsc_dtype <= dtype_long || source.dsc_dtype == dtype_int64);
if (DTYPE_IS_NUMERIC(target.dsc_dtype))
return (source.dsc_dtype <= dtype_double || source.dsc_dtype == dtype_int64);
return (source.dsc_dtype <= dtype_double || source.dsc_dtype == dtype_int64); //!!!!!!!!
if (target.dsc_dtype == dtype_sql_date)
return (source.dsc_dtype <= dtype_sql_date || source.dsc_dtype == dtype_timestamp);
@ -2446,7 +2446,7 @@ static void compress(thread_db* tdbb,
length = INTL_string_to_key(tdbb, itype, desc, &to, key_type);
}
else
length = MOV_get_string(desc, &ptr, &buffer, MAX_KEY);
length = MOV_get_string(tdbb, desc, &ptr, &buffer, MAX_KEY);
if (length)
{
@ -2500,7 +2500,7 @@ static void compress(thread_db* tdbb,
if (itype == idx_numeric)
{
temp.temp_double = MOV_get_double(desc);
temp.temp_double = MOV_get_double(tdbb, desc);
temp_is_negative = (temp.temp_double < 0);
#ifdef DEBUG_INDEXKEY
@ -2510,7 +2510,7 @@ static void compress(thread_db* tdbb,
else if (itype == idx_numeric2)
{
int64_key_op = true;
temp.temp_int64_key = make_int64_key(MOV_get_int64(desc, desc->dsc_scale), desc->dsc_scale);
temp.temp_int64_key = make_int64_key(MOV_get_int64(tdbb, desc, desc->dsc_scale), desc->dsc_scale);
temp_copy_length = sizeof(temp.temp_int64_key.d_part);
temp_is_negative = (temp.temp_int64_key.d_part < 0);
@ -2585,7 +2585,7 @@ static void compress(thread_db* tdbb,
}
else
{
temp.temp_double = MOV_get_double(desc);
temp.temp_double = MOV_get_double(tdbb, desc);
temp_is_negative = (temp.temp_double < 0);
#ifdef DEBUG_INDEXKEY

View File

@ -3,16 +3,16 @@
*** DO NOT EDIT ***
TO CHANGE ANY INFORMATION IN HERE PLEASE
EDIT src/misc/writeBuildNum.sh
FORMAL BUILD NUMBER:449
FORMAL BUILD NUMBER:450
*/
#define PRODUCT_VER_STRING "4.0.0.449"
#define FILE_VER_STRING "WI-T4.0.0.449"
#define LICENSE_VER_STRING "WI-T4.0.0.449"
#define FILE_VER_NUMBER 4, 0, 0, 449
#define PRODUCT_VER_STRING "4.0.0.450"
#define FILE_VER_STRING "WI-T4.0.0.450"
#define LICENSE_VER_STRING "WI-T4.0.0.450"
#define FILE_VER_NUMBER 4, 0, 0, 450
#define FB_MAJOR_VER "4"
#define FB_MINOR_VER "0"
#define FB_REV_NO "0"
#define FB_BUILD_NO "449"
#define FB_BUILD_NO "450"
#define FB_BUILD_TYPE "T"
#define FB_BUILD_SUFFIX "Firebird 4.0 Unstable"

View File

@ -136,7 +136,7 @@ double CVT_date_to_double(const dsc* desc)
temp_desc.dsc_length = sizeof(temp);
date = temp;
temp_desc.dsc_address = (UCHAR*) date;
CVT_move(desc, &temp_desc);
CVT_move(desc, &temp_desc, 0);
}
}
@ -262,7 +262,7 @@ UCHAR CVT_get_numeric(const UCHAR* string, const USHORT length, SSHORT* scale, d
((value < 0) && (sign != -1))) // MAX_SINT64+1 wrapped around
{
// convert to double
*ptr = CVT_get_double(&desc, ERR_post);
*ptr = CVT_get_double(&desc, 0, ERR_post);
return dtype_double;
}
@ -313,7 +313,7 @@ GDS_DATE CVT_get_sql_date(const dsc* desc)
memset(&temp_desc, 0, sizeof(temp_desc));
temp_desc.dsc_dtype = dtype_sql_date;
temp_desc.dsc_address = (UCHAR *) &value;
CVT_move(desc, &temp_desc);
CVT_move(desc, &temp_desc, 0);
return value;
}
@ -338,7 +338,7 @@ GDS_TIME CVT_get_sql_time(const dsc* desc)
memset(&temp_desc, 0, sizeof(temp_desc));
temp_desc.dsc_dtype = dtype_sql_time;
temp_desc.dsc_address = (UCHAR *) &value;
CVT_move(desc, &temp_desc);
CVT_move(desc, &temp_desc, 0);
return value;
}
@ -363,7 +363,7 @@ GDS_TIMESTAMP CVT_get_timestamp(const dsc* desc)
memset(&temp_desc, 0, sizeof(temp_desc));
temp_desc.dsc_dtype = dtype_timestamp;
temp_desc.dsc_address = (UCHAR *) &value;
CVT_move(desc, &temp_desc);
CVT_move(desc, &temp_desc, 0);
return value;
}

View File

@ -65,11 +65,10 @@ using namespace Firebird;
comparison purpose, even though isc_int64 had to get number 19, which
is otherwise too high.
This table is used in CVT2_compare, is indexed by dsc_dtype, and
returns the relative priority of types for use when different types
are compared.
This table is indexed by dsc_dtype, and returns the relative priority
of types for use when different types are compared.
*/
static const BYTE compare_priority[] =
const BYTE CVT2_compare_priority[] =
{
dtype_unknown, // dtype_unknown through dtype_varying
dtype_text, // have their natural values stored
@ -80,18 +79,20 @@ static const BYTE compare_priority[] =
dtype_byte, // their natural values in the table
dtype_short,
dtype_long,
dtype_quad + 1, // quad through array all move up
dtype_real + 1, // by one to make room for int64
dtype_double + 1, // at its proper place in the table.
dtype_d_float + 1,
dtype_sql_date + 1,
dtype_sql_time + 1,
dtype_timestamp + 1,
dtype_blob + 1,
dtype_array + 1,
dtype_quad + 1, // Move quad up by one to make room for int64 at its proper place in the table.
dtype_real + 3, // Also leave space for dec64 and dec 128.
dtype_double + 3,
dtype_d_float + 3,
dtype_sql_date + 3,
dtype_sql_time + 3,
dtype_timestamp + 3,
dtype_blob + 3,
dtype_array + 3,
dtype_long + 1, // int64 goes right after long
dtype_dbkey, // compares with nothing except itself
dtype_boolean // compares with nothing except itself
dtype_boolean, // compares with nothing except itself
dtype_quad + 2, // dec64 and dec128 go after quad before real
dtype_quad + 3
};
static inline int QUAD_COMPARE(const SQUAD* arg1, const SQUAD* arg2)
@ -177,7 +178,7 @@ bool CVT2_get_binary_comparable_desc(dsc* result, const dsc* arg1, const dsc* ar
else
{
// Arguments are of different data types
*result = (compare_priority[arg1->dsc_dtype] > compare_priority[arg2->dsc_dtype]) ? *arg1 : *arg2;
*result = (CVT2_compare_priority[arg1->dsc_dtype] > CVT2_compare_priority[arg2->dsc_dtype]) ? *arg1 : *arg2;
if (arg1->isExact() && arg2->isExact())
result->dsc_scale = MIN(arg1->dsc_scale, arg2->dsc_scale);
@ -187,7 +188,7 @@ bool CVT2_get_binary_comparable_desc(dsc* result, const dsc* arg1, const dsc* ar
}
int CVT2_compare(const dsc* arg1, const dsc* arg2)
int CVT2_compare(const dsc* arg1, const dsc* arg2, Firebird::DecimalStatus decSt)
{
/**************************************
*
@ -285,6 +286,12 @@ int CVT2_compare(const dsc* arg1, const dsc* arg2)
return 1;
return -1;
case dtype_dec64:
return ((Decimal64*) p1)->compare(decSt, *(Decimal64*) p2);
case dtype_dec128:
return ((Decimal128*) p1)->compare(decSt, *(Decimal128*) p2);
case dtype_boolean:
return *p1 == *p2 ? 0 : *p1 < *p2 ? -1 : 1;
@ -342,8 +349,8 @@ int CVT2_compare(const dsc* arg1, const dsc* arg2)
UCHAR* p1 = NULL;
UCHAR* p2 = NULL;
USHORT t1, t2; // unused later
USHORT length = CVT_get_string_ptr(arg1, &t1, &p1, NULL, 0);
USHORT length2 = CVT_get_string_ptr(arg2, &t2, &p2, NULL, 0);
USHORT length = CVT_get_string_ptr(arg1, &t1, &p1, NULL, 0, decSt);
USHORT length2 = CVT_get_string_ptr(arg2, &t2, &p2, NULL, 0, decSt);
int fill = length - length2;
const UCHAR pad = charset1 == ttype_binary || charset2 == ttype_binary ? '\0' : ' ';
@ -391,8 +398,8 @@ int CVT2_compare(const dsc* arg1, const dsc* arg2)
// Handle heterogeneous compares
if (compare_priority[arg1->dsc_dtype] < compare_priority[arg2->dsc_dtype])
return -CVT2_compare(arg2, arg1);
if (CVT2_compare_priority[arg1->dsc_dtype] < CVT2_compare_priority[arg2->dsc_dtype])
return -CVT2_compare(arg2, arg1, decSt);
// At this point, the type of arg1 is guaranteed to be "greater than" arg2,
// in the sense that it is the preferred type for comparing the two.
@ -407,8 +414,8 @@ int CVT2_compare(const dsc* arg1, const dsc* arg2)
SLONG datetime[2];
desc.dsc_length = sizeof(datetime);
desc.dsc_address = (UCHAR*) datetime;
CVT_move(arg2, &desc);
return CVT2_compare(arg1, &desc);
CVT_move(arg2, &desc, 0);
return CVT2_compare(arg1, &desc, 0);
}
case dtype_sql_time:
@ -419,8 +426,8 @@ int CVT2_compare(const dsc* arg1, const dsc* arg2)
SLONG atime;
desc.dsc_length = sizeof(atime);
desc.dsc_address = (UCHAR*) &atime;
CVT_move(arg2, &desc);
return CVT2_compare(arg1, &desc);
CVT_move(arg2, &desc, 0);
return CVT2_compare(arg1, &desc, 0);
}
case dtype_sql_date:
@ -431,8 +438,8 @@ int CVT2_compare(const dsc* arg1, const dsc* arg2)
SLONG date;
desc.dsc_length = sizeof(date);
desc.dsc_address = (UCHAR*) &date;
CVT_move(arg2, &desc);
return CVT2_compare(arg1, &desc);
CVT_move(arg2, &desc, 0);
return CVT2_compare(arg1, &desc, 0);
}
case dtype_short:
@ -442,8 +449,8 @@ int CVT2_compare(const dsc* arg1, const dsc* arg2)
scale = MIN(arg1->dsc_scale, arg2->dsc_scale);
else
scale = arg1->dsc_scale;
const SLONG temp1 = CVT_get_long(arg1, scale, ERR_post);
const SLONG temp2 = CVT_get_long(arg2, scale, ERR_post);
const SLONG temp1 = CVT_get_long(arg1, scale, decSt, ERR_post);
const SLONG temp2 = CVT_get_long(arg2, scale, decSt, ERR_post);
if (temp1 == temp2)
return 0;
if (temp1 > temp2)
@ -460,8 +467,8 @@ int CVT2_compare(const dsc* arg1, const dsc* arg2)
scale = MIN(arg1->dsc_scale, arg2->dsc_scale);
else
scale = arg1->dsc_scale;
const SINT64 temp1 = CVT_get_int64(arg1, scale, ERR_post);
const SINT64 temp2 = CVT_get_int64(arg2, scale, ERR_post);
const SINT64 temp1 = CVT_get_int64(arg1, scale, decSt, ERR_post);
const SINT64 temp2 = CVT_get_int64(arg2, scale, decSt, ERR_post);
if (temp1 == temp2)
return 0;
if (temp1 > temp2)
@ -476,15 +483,15 @@ int CVT2_compare(const dsc* arg1, const dsc* arg2)
scale = MIN(arg1->dsc_scale, arg2->dsc_scale);
else
scale = arg1->dsc_scale;
const SQUAD temp1 = CVT_get_quad(arg1, scale, ERR_post);
const SQUAD temp2 = CVT_get_quad(arg2, scale, ERR_post);
const SQUAD temp1 = CVT_get_quad(arg1, scale, decSt, ERR_post);
const SQUAD temp2 = CVT_get_quad(arg2, scale, decSt, ERR_post);
return QUAD_COMPARE(&temp1, &temp2);
}
case dtype_real:
{
const float temp1 = (float) CVT_get_double(arg1, ERR_post);
const float temp2 = (float) CVT_get_double(arg2, ERR_post);
const float temp1 = (float) CVT_get_double(arg1, decSt, ERR_post);
const float temp2 = (float) CVT_get_double(arg2, decSt, ERR_post);
if (temp1 == temp2)
return 0;
if (temp1 > temp2)
@ -494,8 +501,8 @@ int CVT2_compare(const dsc* arg1, const dsc* arg2)
case dtype_double:
{
const double temp1 = CVT_get_double(arg1, ERR_post);
const double temp2 = CVT_get_double(arg2, ERR_post);
const double temp1 = CVT_get_double(arg1, decSt, ERR_post);
const double temp2 = CVT_get_double(arg2, decSt, ERR_post);
if (temp1 == temp2)
return 0;
if (temp1 > temp2)
@ -503,8 +510,22 @@ int CVT2_compare(const dsc* arg1, const dsc* arg2)
return -1;
}
case dtype_dec64:
{
const Decimal64 temp1 = CVT_get_dec64(arg1, decSt, ERR_post);
const Decimal64 temp2 = CVT_get_dec64(arg2, decSt, ERR_post);
return temp1.compare(decSt, temp2);
}
case dtype_dec128:
{
const Decimal128 temp1 = CVT_get_dec128(arg1, decSt, ERR_post);
const Decimal128 temp2 = CVT_get_dec128(arg2, decSt, ERR_post);
return temp1.compare(decSt, temp2);
}
case dtype_blob:
return CVT2_blob_compare(arg1, arg2);
return CVT2_blob_compare(arg1, arg2, decSt);
case dtype_array:
ERR_post(Arg::Gds(isc_wish_list) << Arg::Gds(isc_blobnotsup) << "compare");
@ -515,7 +536,7 @@ int CVT2_compare(const dsc* arg1, const dsc* arg2)
{
UCHAR* p = NULL;
USHORT t; // unused later
USHORT length = CVT_get_string_ptr(arg2, &t, &p, NULL, 0);
USHORT length = CVT_get_string_ptr(arg2, &t, &p, NULL, 0, decSt);
USHORT l = MIN(arg1->dsc_length, length);
int rc = memcmp(arg1->dsc_address, p, l);
@ -548,7 +569,7 @@ int CVT2_compare(const dsc* arg1, const dsc* arg2)
}
int CVT2_blob_compare(const dsc* arg1, const dsc* arg2)
int CVT2_blob_compare(const dsc* arg1, const dsc* arg2, DecimalStatus decSt)
{
/**************************************
*
@ -709,7 +730,7 @@ int CVT2_blob_compare(const dsc* arg1, const dsc* arg2)
UCHAR* p;
MoveBuffer temp_str;
l2 = CVT2_make_string2(arg2, ttype1, &p, temp_str);
l2 = CVT2_make_string2(arg2, ttype1, &p, temp_str, decSt);
blb* blob1 = blb::open(tdbb, tdbb->getRequest()->req_transaction, (bid*) arg1->dsc_address);
@ -734,7 +755,7 @@ int CVT2_blob_compare(const dsc* arg1, const dsc* arg2)
}
USHORT CVT2_make_string2(const dsc* desc, USHORT to_interp, UCHAR** address, Jrd::MoveBuffer& temp)
USHORT CVT2_make_string2(const dsc* desc, USHORT to_interp, UCHAR** address, MoveBuffer& temp, DecimalStatus decSt)
{
/**************************************
*
@ -813,7 +834,7 @@ USHORT CVT2_make_string2(const dsc* desc, USHORT to_interp, UCHAR** address, Jrd
vary* vtmp = reinterpret_cast<vary*>(temp_desc.dsc_address);
temp_desc.dsc_dtype = dtype_varying;
temp_desc.setTextType(to_interp);
CVT_move(desc, &temp_desc);
CVT_move(desc, &temp_desc, decSt);
*address = reinterpret_cast<UCHAR*>(vtmp->vary_string);
return vtmp->vary_length;

View File

@ -26,9 +26,11 @@
#include "../jrd/jrd.h"
extern const BYTE CVT2_compare_priority[];
bool CVT2_get_binary_comparable_desc(dsc*, const dsc*, const dsc*);
int CVT2_compare(const dsc*, const dsc*);
int CVT2_blob_compare(const dsc*, const dsc*);
USHORT CVT2_make_string2(const dsc*, USHORT, UCHAR**, Jrd::MoveBuffer&);
int CVT2_compare(const dsc*, const dsc*, Firebird::DecimalStatus);
int CVT2_blob_compare(const dsc*, const dsc*, Firebird::DecimalStatus);
USHORT CVT2_make_string2(const dsc*, USHORT, UCHAR**, Jrd::MoveBuffer&, Firebird::DecimalStatus);
#endif // JRD_CVT2_PROTO_H

View File

@ -65,15 +65,15 @@ namespace Jrd
};
}
inline void CVT_move(const dsc* from, dsc* to)
inline void CVT_move(const dsc* from, dsc* to, Firebird::DecimalStatus decSt)
{
CVT_move_common(from, to, &Jrd::EngineCallbacks::instance);
CVT_move_common(from, to, decSt, &Jrd::EngineCallbacks::instance);
}
inline USHORT CVT_get_string_ptr(const dsc* desc, USHORT* ttype, UCHAR** address,
vary* temp, USHORT length)
vary* temp, USHORT length, Firebird::DecimalStatus decSt)
{
return CVT_get_string_ptr_common(desc, ttype, address, temp, length,
return CVT_get_string_ptr_common(desc, ttype, address, temp, length, decSt,
&Jrd::EngineCallbacks::instance);
}

View File

@ -6448,7 +6448,7 @@ static string get_string(const dsc* desc)
// Find the actual length of the string, searching until the claimed
// end of the string, or the terminating \0, whichever comes first.
USHORT length = MOV_make_string(desc, ttype_metadata, &str, &temp, sizeof(temp));
USHORT length = MOV_make_string(JRD_get_thread_data(), desc, ttype_metadata, &str, &temp, sizeof(temp));
const char* p = str;
const char* const q = str + length;

View File

@ -261,7 +261,7 @@ RecordBitmap** EVL_bitmap(thread_db* tdbb, const InversionNode* node, RecordBitm
(desc->isText() || desc->isDbKey()))
{
UCHAR* ptr = NULL;
const int length = MOV_get_string(desc, &ptr, NULL, 0);
const int length = MOV_get_string(tdbb, desc, &ptr, NULL, 0);
if (length == sizeof(RecordNumber::Packed))
{
@ -426,6 +426,14 @@ void EVL_make_value(thread_db* tdbb, const dsc* desc, impure_value* value, Memor
value->vlu_misc.vlu_double = *((double*) from.dsc_address);
return;
case dtype_dec64:
value->vlu_misc.vlu_dec64 = *((Decimal64*) from.dsc_address);
return;
case dtype_dec128:
value->vlu_misc.vlu_dec128 = *((Decimal128*) from.dsc_address);
return;
case dtype_timestamp:
case dtype_quad:
value->vlu_misc.vlu_dbkey[0] = ((SLONG*) from.dsc_address)[0];
@ -459,7 +467,7 @@ void EVL_make_value(thread_db* tdbb, const dsc* desc, impure_value* value, Memor
// temporary buffer. Since this will always be the result of a conversion,
// this isn't a serious problem.
const USHORT length = MOV_get_string_ptr(&from, &ttype, &address, &temp, sizeof(temp));
const USHORT length = MOV_get_string_ptr(tdbb, &from, &ttype, &address, &temp, sizeof(temp));
// Allocate a string block of sufficient size.
@ -539,7 +547,7 @@ void EVL_validate(thread_db* tdbb, const Item& item, const ItemInfo* itemInfo, d
if (!fieldInfo.validationExpr->execute(tdbb, request) && !(request->req_flags & req_null))
{
const USHORT length = desc_is_null ? 0 :
MOV_make_string(desc, ttype_dynamic, &value, &temp, sizeof(temp) - 1);
MOV_make_string(tdbb, desc, ttype_dynamic, &value, &temp, sizeof(temp) - 1);
if (desc_is_null)
value = NULL_STRING_MARK;

View File

@ -280,7 +280,7 @@ void EXE_assignment(thread_db* tdbb, const ValueExprNode* to, dsc* from_desc, bo
SSHORT null = from_null ? -1 : 0;
if (!null && missing && MOV_compare(missing, from_desc) == 0)
if (!null && missing && MOV_compare(tdbb, missing, from_desc) == 0)
null = -1;
USHORT* impure_flags = NULL;

View File

@ -346,7 +346,7 @@ void EXT_fini(jrd_rel* relation, bool close_only)
}
bool EXT_get(thread_db* /*tdbb*/, record_param* rpb, FB_UINT64& position)
bool EXT_get(thread_db* tdbb, record_param* rpb, FB_UINT64& position)
{
/**************************************
*
@ -439,7 +439,7 @@ bool EXT_get(thread_db* /*tdbb*/, record_param* rpb, FB_UINT64& position)
desc = *desc_ptr;
desc.dsc_address = record->getData() + (IPTR) desc.dsc_address;
if (!MOV_compare(&literal->litDesc, &desc))
if (!MOV_compare(tdbb, &literal->litDesc, &desc))
continue;
}

View File

@ -63,7 +63,6 @@ static RegisterFBProvider reg;
static bool isConnectionBrokenError(FbStatusVector* status);
static void parseSQLDA(XSQLDA* xsqlda, UCharBuffer& buff, Firebird::Array<dsc>& descs);
static UCHAR sqlTypeToDscType(SSHORT sqlType);
// IscProvider
@ -1597,7 +1596,7 @@ static void parseSQLDA(XSQLDA* xsqlda, UCharBuffer& buff, Firebird::Array<dsc> &
for (int i = 0; i < xsqlda->sqld; xVar++, i++)
{
const UCHAR dtype = sqlTypeToDscType(xVar->sqltype & ~1);
const UCHAR dtype = fb_utils::sqlTypeToDscType(xVar->sqltype & ~1);
xVar->sqltype |= 1;
if (type_alignments[dtype])
@ -1622,7 +1621,7 @@ static void parseSQLDA(XSQLDA* xsqlda, UCharBuffer& buff, Firebird::Array<dsc> &
for (int i = 0; i < xsqlda->sqld; xVar++, i++)
{
const UCHAR dtype = sqlTypeToDscType(xVar->sqltype & ~1);
const UCHAR dtype = fb_utils::sqlTypeToDscType(xVar->sqltype & ~1);
if (type_alignments[dtype])
offset = FB_ALIGN(offset, type_alignments[dtype]);
@ -1659,47 +1658,5 @@ static void parseSQLDA(XSQLDA* xsqlda, UCharBuffer& buff, Firebird::Array<dsc> &
}
static 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;
default:
return dtype_unknown;
}
}
} // namespace EDS

View File

@ -486,7 +486,7 @@ void FUN_evaluate(thread_db* tdbb, const Function* function, const NestValueArra
{
case dtype_short:
{
const SSHORT s = MOV_get_long(input, (SSHORT) parameter->prm_desc.dsc_scale);
const SSHORT s = MOV_get_long(tdbb, input, (SSHORT) parameter->prm_desc.dsc_scale);
if (parameter->prm_fun_mechanism == FUN_value)
{
// For (apparent) portability reasons, SHORT by value
@ -505,7 +505,7 @@ void FUN_evaluate(thread_db* tdbb, const Function* function, const NestValueArra
break;
case dtype_long:
l = MOV_get_long(input, (SSHORT) parameter->prm_desc.dsc_scale);
l = MOV_get_long(tdbb, input, (SSHORT) parameter->prm_desc.dsc_scale);
if (parameter->prm_fun_mechanism == FUN_value)
{
*arg_ptr++ = (UDF_ARG)(IPTR) l;
@ -540,7 +540,7 @@ void FUN_evaluate(thread_db* tdbb, const Function* function, const NestValueArra
case dtype_int64:
{
SINT64* pi64;
const SINT64 i64 = MOV_get_int64(input, (SSHORT) parameter->prm_desc.dsc_scale);
const SINT64 i64 = MOV_get_int64(tdbb, input, (SSHORT) parameter->prm_desc.dsc_scale);
if (parameter->prm_fun_mechanism == FUN_value)
{
@ -556,7 +556,7 @@ void FUN_evaluate(thread_db* tdbb, const Function* function, const NestValueArra
case dtype_real:
{
const float f = (float) MOV_get_double(input);
const float f = (float) MOV_get_double(tdbb, input);
if (parameter->prm_fun_mechanism == FUN_value)
{
// For (apparent) portability reasons, FLOAT by value
@ -576,7 +576,7 @@ void FUN_evaluate(thread_db* tdbb, const Function* function, const NestValueArra
break;
case dtype_double:
d = MOV_get_double(input);
d = MOV_get_double(tdbb, input);
double* dp;
if (parameter->prm_fun_mechanism == FUN_value)
{
@ -589,6 +589,36 @@ void FUN_evaluate(thread_db* tdbb, const Function* function, const NestValueArra
*dp = d;
break;
case dtype_dec64:
{
const Decimal64 d = MOV_get_dec64(tdbb, input);
if (parameter->prm_fun_mechanism == FUN_value)
{
Decimal64* dp = reinterpret_cast<Decimal64*>(arg_ptr);
*dp++ = d;
arg_ptr = reinterpret_cast<UDF_ARG*>(dp);
continue;
}
Decimal64* fp = (Decimal64*) temp_ptr;
*fp = d;
}
break;
case dtype_dec128:
{
const Decimal128 d = MOV_get_dec128(tdbb, input);
if (parameter->prm_fun_mechanism == FUN_value)
{
Decimal128* dp = reinterpret_cast<Decimal128*>(arg_ptr);
*dp++ = d;
arg_ptr = reinterpret_cast<UDF_ARG*>(dp);
continue;
}
Decimal128* fp = (Decimal128*) temp_ptr;
*fp = d;
}
break;
case dtype_text:
case dtype_dbkey:
case dtype_cstring:
@ -742,8 +772,9 @@ void FUN_evaluate(thread_db* tdbb, const Function* function, const NestValueArra
}
else
{
if (value->vlu_desc.dsc_dtype == dtype_double)
switch(value->vlu_desc.dsc_dtype)
{
case dtype_double:
if (isinf(value->vlu_misc.vlu_double))
{
status_exception::raise(Arg::Gds(isc_expression_eval_err) <<
@ -756,6 +787,37 @@ void FUN_evaluate(thread_db* tdbb, const Function* function, const NestValueArra
Arg::Gds(isc_udf_fp_nan) <<
Arg::Str(function->getName().toString()));
}
break;
case dtype_dec64:
if (value->vlu_misc.vlu_dec64.isInf())
{
status_exception::raise(Arg::Gds(isc_expression_eval_err) <<
Arg::Gds(isc_udf_fp_overflow) <<
Arg::Str(function->getName().toString()));
}
else if (value->vlu_misc.vlu_dec64.isNan())
{
status_exception::raise(Arg::Gds(isc_expression_eval_err) <<
Arg::Gds(isc_udf_fp_nan) <<
Arg::Str(function->getName().toString()));
}
break;
case dtype_dec128:
if (value->vlu_misc.vlu_dec128.isInf())
{
status_exception::raise(Arg::Gds(isc_expression_eval_err) <<
Arg::Gds(isc_udf_fp_overflow) <<
Arg::Str(function->getName().toString()));
}
else if (value->vlu_misc.vlu_dec128.isNan())
{
status_exception::raise(Arg::Gds(isc_expression_eval_err) <<
Arg::Gds(isc_udf_fp_nan) <<
Arg::Str(function->getName().toString()));
}
break;
}
request->req_flags &= ~req_null;
}
@ -1050,6 +1112,14 @@ static void invoke(thread_db* tdbb,
value->vlu_misc.vlu_double = CALL_UDF<double>(tdbb, function->fun_entrypoint, args);
break;
case dtype_dec64:
value->vlu_misc.vlu_dec64 = CALL_UDF<Decimal64>(tdbb, function->fun_entrypoint, args);
break;
case dtype_dec128:
value->vlu_misc.vlu_dec128 = CALL_UDF<Decimal128>(tdbb, function->fun_entrypoint, args);
break;
case dtype_timestamp:
default:
udfError = UeUnsupDtype;

View File

@ -1102,7 +1102,7 @@ static idx_e check_duplicates(thread_db* tdbb,
bool flag_rec = false;
const dsc* desc_rec = BTR_eval_expression(tdbb, insertion_idx, rpb.rpb_record, flag_rec);
if (flag_rec && flag_idx && (MOV_compare(desc_rec, &desc1) == 0))
if (flag_rec && flag_idx && (MOV_compare(tdbb, desc_rec, &desc1) == 0))
{
result = idx_e_duplicate;
break;
@ -1123,7 +1123,7 @@ static idx_e check_duplicates(thread_db* tdbb,
field_id = record_idx->idx_rpt[i].idx_field;
const bool flag_idx = EVL_field(relation_2, record, field_id, &desc2);
if (flag_rec != flag_idx || (flag_rec && (MOV_compare(&desc1, &desc2) != 0) ))
if (flag_rec != flag_idx || (flag_rec && (MOV_compare(tdbb, &desc1, &desc2) != 0) ))
break;
all_nulls = all_nulls && !flag_rec && !flag_idx;
@ -1556,7 +1556,7 @@ void IDX_modify_flag_uk_modified(thread_db* tdbb,
const bool flag_org = EVL_field(org_rpb->rpb_relation, org_rpb->rpb_record, idx_desc->idx_field, &desc1);
const bool flag_new = EVL_field(new_rpb->rpb_relation, new_rpb->rpb_record, idx_desc->idx_field, &desc2);
if (flag_org != flag_new || MOV_compare(&desc1, &desc2) != 0)
if (flag_org != flag_new || MOV_compare(tdbb, &desc1, &desc2) != 0)
{
new_rpb->rpb_flags |= rpb_uk_modified;
CCH_RELEASE(tdbb, &window);

View File

@ -610,11 +610,11 @@ int INTL_compare(thread_db* tdbb, const dsc* pText1, const dsc* pText2, ErrorFun
UCHAR* p1;
USHORT t1;
ULONG length1 = CVT_get_string_ptr(pText1, &t1, &p1, NULL, 0, err);
ULONG length1 = CVT_get_string_ptr(pText1, &t1, &p1, NULL, 0, tdbb->getAttachment()->att_dec_status, err);
UCHAR* p2;
USHORT t2;
ULONG length2 = CVT_get_string_ptr(pText2, &t2, &p2, NULL, 0, err);
ULONG length2 = CVT_get_string_ptr(pText2, &t2, &p2, NULL, 0, tdbb->getAttachment()->att_dec_status, err);
// YYY - by SQL II compare_type must be explicit in the
// SQL statement if there is any doubt
@ -820,7 +820,7 @@ int INTL_convert_string(dsc* to, const dsc* from, ErrorFunction err)
UCHAR* from_ptr;
USHORT from_type;
const USHORT from_len = CVT_get_string_ptr(from, &from_type, &from_ptr, NULL, 0, err);
const USHORT from_len = CVT_get_string_ptr(from, &from_type, &from_ptr, NULL, 0, tdbb->getAttachment()->att_dec_status, err);
const ULONG to_size = TEXT_LEN(to);
ULONG from_fill, to_fill;

View File

@ -42,7 +42,7 @@
using namespace Firebird;
int MOV_compare(const dsc* arg1, const dsc* arg2)
int MOV_compare(Jrd::thread_db* tdbb, const dsc* arg1, const dsc* arg2)
{
/**************************************
*
@ -55,7 +55,7 @@ int MOV_compare(const dsc* arg1, const dsc* arg2)
*
**************************************/
return CVT2_compare(arg1, arg2);
return CVT2_compare(arg1, arg2, tdbb->getAttachment()->att_dec_status);
}
@ -102,7 +102,7 @@ bool MOV_get_boolean(const dsc* desc)
}
double MOV_get_double(const dsc* desc)
double MOV_get_double(Jrd::thread_db* tdbb, const dsc* desc)
{
/**************************************
*
@ -115,11 +115,11 @@ double MOV_get_double(const dsc* desc)
*
**************************************/
return CVT_get_double(desc, ERR_post);
return CVT_get_double(desc, tdbb->getAttachment()->att_dec_status, ERR_post);
}
SLONG MOV_get_long(const dsc* desc, SSHORT scale)
SLONG MOV_get_long(Jrd::thread_db* tdbb, const dsc* desc, SSHORT scale)
{
/**************************************
*
@ -133,11 +133,11 @@ SLONG MOV_get_long(const dsc* desc, SSHORT scale)
*
**************************************/
return CVT_get_long(desc, scale, ERR_post);
return CVT_get_long(desc, scale, tdbb->getAttachment()->att_dec_status, ERR_post);
}
SINT64 MOV_get_int64(const dsc* desc, SSHORT scale)
SINT64 MOV_get_int64(Jrd::thread_db* tdbb, const dsc* desc, SSHORT scale)
{
/**************************************
*
@ -151,11 +151,11 @@ SINT64 MOV_get_int64(const dsc* desc, SSHORT scale)
*
**************************************/
return CVT_get_int64(desc, scale, ERR_post);
return CVT_get_int64(desc, scale, tdbb->getAttachment()->att_dec_status, ERR_post);
}
void MOV_get_metaname(const dsc* desc, MetaName& name)
void MOV_get_metaname(Jrd::thread_db* tdbb, const dsc* desc, MetaName& name)
{
/**************************************
*
@ -172,7 +172,7 @@ void MOV_get_metaname(const dsc* desc, MetaName& name)
USHORT ttype;
UCHAR* ptr = NULL;
const USHORT length = CVT_get_string_ptr(desc, &ttype, &ptr, NULL, 0);
const USHORT length = CVT_get_string_ptr(desc, &ttype, &ptr, NULL, 0, tdbb->getAttachment()->att_dec_status);
fb_assert(length && ptr);
fb_assert(length <= MAX_SQL_IDENTIFIER_LEN);
@ -182,7 +182,7 @@ void MOV_get_metaname(const dsc* desc, MetaName& name)
}
SQUAD MOV_get_quad(const dsc* desc, SSHORT scale)
SQUAD MOV_get_quad(Jrd::thread_db* tdbb, const dsc* desc, SSHORT scale)
{
/**************************************
*
@ -196,11 +196,12 @@ SQUAD MOV_get_quad(const dsc* desc, SSHORT scale)
*
**************************************/
return CVT_get_quad(desc, scale, ERR_post);
return CVT_get_quad(desc, scale, tdbb->getAttachment()->att_dec_status, ERR_post);
}
int MOV_get_string_ptr(const dsc* desc,
int MOV_get_string_ptr(Jrd::thread_db* tdbb,
const dsc* desc,
USHORT* ttype,
UCHAR** address, vary* temp, USHORT length)
{
@ -221,11 +222,11 @@ int MOV_get_string_ptr(const dsc* desc,
*
**************************************/
return CVT_get_string_ptr(desc, ttype, address, temp, length);
return CVT_get_string_ptr(desc, ttype, address, temp, length, tdbb->getAttachment()->att_dec_status);
}
int MOV_get_string(const dsc* desc, UCHAR** address, vary* temp, USHORT length)
int MOV_get_string(Jrd::thread_db* tdbb, const dsc* desc, UCHAR** address, vary* temp, USHORT length)
{
/**************************************
*
@ -238,7 +239,7 @@ int MOV_get_string(const dsc* desc, UCHAR** address, vary* temp, USHORT length)
**************************************/
USHORT ttype;
return MOV_get_string_ptr(desc, &ttype, address, temp, length);
return MOV_get_string_ptr(tdbb, desc, &ttype, address, temp, length);
}
@ -293,7 +294,8 @@ GDS_TIMESTAMP MOV_get_timestamp(const dsc* desc)
}
int MOV_make_string(const dsc* desc,
int MOV_make_string(Jrd::thread_db* tdbb,
const dsc* desc,
USHORT ttype,
const char** address,
vary* temp,
@ -318,7 +320,7 @@ int MOV_make_string(const dsc* desc,
*
**************************************/
return CVT_make_string(desc, ttype, address, temp, length, ERR_post);
return CVT_make_string(desc, ttype, address, temp, length, tdbb->getAttachment()->att_dec_status, ERR_post);
}
@ -380,7 +382,7 @@ int MOV_make_string2(Jrd::thread_db* tdbb,
return size;
}
return CVT2_make_string2(desc, ttype, address, buffer);
return CVT2_make_string2(desc, ttype, address, buffer, tdbb->getAttachment()->att_dec_status);
}
@ -410,5 +412,41 @@ void MOV_move(Jrd::thread_db* tdbb, /*const*/ dsc* from, dsc* to)
if (DTYPE_IS_BLOB_OR_QUAD(from->dsc_dtype) || DTYPE_IS_BLOB_OR_QUAD(to->dsc_dtype))
Jrd::blb::move(tdbb, from, to, NULL);
else
CVT_move(from, to);
CVT_move(from, to, tdbb->getAttachment()->att_dec_status);
}
Decimal64 MOV_get_dec64(Jrd::thread_db* tdbb, const dsc* desc)
{
/**************************************
*
* M O V _ g e t _ d o u b l e
*
**************************************
*
* Functional description
* Convert something arbitrary to a double precision number
*
**************************************/
return CVT_get_dec64(desc, tdbb->getAttachment()->att_dec_status, ERR_post);
}
Decimal128 MOV_get_dec128(Jrd::thread_db* tdbb, const dsc* desc)
{
/**************************************
*
* M O V _ g e t _ d o u b l e
*
**************************************
*
* Functional description
* Convert something arbitrary to a double precision number
*
**************************************/
return CVT_get_dec128(desc, tdbb->getAttachment()->att_dec_status, ERR_post);
}

View File

@ -31,25 +31,26 @@
struct dsc;
struct vary;
int MOV_compare(const dsc*, const dsc*);
int MOV_compare(Jrd::thread_db*, const dsc*, const dsc*);
double MOV_date_to_double(const dsc*);
void MOV_double_to_date(double, SLONG[2]);
bool MOV_get_boolean(const dsc*);
double MOV_get_double(const dsc*);
SLONG MOV_get_long(const dsc*, SSHORT);
void MOV_get_metaname(const dsc*, Firebird::MetaName&);
SQUAD MOV_get_quad(const dsc*, SSHORT);
SINT64 MOV_get_int64(const dsc*, SSHORT);
int MOV_get_string_ptr(const dsc*, USHORT*, UCHAR**, vary*,
USHORT);
int MOV_get_string(const dsc*, UCHAR**, vary*, USHORT);
double MOV_get_double(Jrd::thread_db*, const dsc*);
SLONG MOV_get_long(Jrd::thread_db*, const dsc*, SSHORT);
void MOV_get_metaname(Jrd::thread_db*, const dsc*, Firebird::MetaName&);
SQUAD MOV_get_quad(Jrd::thread_db*, const dsc*, SSHORT);
SINT64 MOV_get_int64(Jrd::thread_db*, const dsc*, SSHORT);
int MOV_get_string_ptr(Jrd::thread_db*, const dsc*, USHORT*, UCHAR**, vary*, USHORT);
int MOV_get_string(Jrd::thread_db*, const dsc*, UCHAR**, vary*, USHORT);
GDS_DATE MOV_get_sql_date(const dsc*);
GDS_TIME MOV_get_sql_time(const dsc*);
GDS_TIMESTAMP MOV_get_timestamp(const dsc*);
int MOV_make_string(const dsc*, USHORT, const char**, vary*, USHORT);
int MOV_make_string(Jrd::thread_db*, const dsc*, USHORT, const char**, vary*, USHORT);
int MOV_make_string2(Jrd::thread_db*, const dsc*, USHORT, UCHAR**, Jrd::MoveBuffer&, bool = true);
Firebird::string MOV_make_string2(Jrd::thread_db* tdbb, const dsc* desc, USHORT ttype,
bool limit = true);
void MOV_move(Jrd::thread_db*, /*const*/ dsc*, dsc*);
Firebird::Decimal64 MOV_get_dec64(Jrd::thread_db*, const dsc*);
Firebird::Decimal128 MOV_get_dec128(Jrd::thread_db*, const dsc*);
#endif // JRD_MOV_PROTO_H

View File

@ -396,7 +396,9 @@ static const UCHAR sort_dtypes[] =
0, // dtype_array
SKD_int64, // dtype_int64
SKD_text, // dtype_dbkey - use text sort for backward compatibility
SKD_bytes // dtype_boolean
SKD_bytes, // dtype_boolean
0, // dtype_dec64
0 // dtype_dec128
};

View File

@ -385,6 +385,16 @@ USHORT PAR_datatype(BlrReader& blrReader, 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_blob2:
desc->dsc_dtype = dtype_blob;
desc->dsc_length = sizeof(ISC_QUAD);

View File

@ -334,7 +334,7 @@ int BaseAggWinStream<ThisType, NextType>::lookForChange(thread_db* tdbb, jrd_req
}
else if (!vtemp->vlu_desc.dsc_address)
return 1 * nullDirection;
else if ((n = MOV_compare(desc, &vtemp->vlu_desc)) != 0)
else if ((n = MOV_compare(tdbb, desc, &vtemp->vlu_desc)) != 0)
return n * direction;
}

View File

@ -52,7 +52,7 @@ void FirstRowsStream::open(thread_db* tdbb) const
impure->irsb_flags = 0;
const dsc* desc = EVL_expr(tdbb, request, m_value);
const SINT64 value = (desc && !(request->req_flags & req_null)) ? MOV_get_int64(desc, 0) : 0;
const SINT64 value = (desc && !(request->req_flags & req_null)) ? MOV_get_int64(tdbb, desc, 0) : 0;
if (value < 0)
status_exception::raise(Arg::Gds(isc_bad_limit_param));

View File

@ -409,7 +409,7 @@ int MergeJoin::compare(thread_db* tdbb, const NestValueArray* node1,
if (!null1 && !null2)
{
const int result = MOV_compare(desc1, desc2);
const int result = MOV_compare(tdbb, desc1, desc2);
if (result != 0)
return result;

View File

@ -52,7 +52,7 @@ void SkipRowsStream::open(thread_db* tdbb) const
impure->irsb_flags = irsb_open;
const dsc* desc = EVL_expr(tdbb, request, m_value);
const SINT64 value = (desc && !(request->req_flags & req_null)) ? MOV_get_int64(desc, 0) : 0;
const SINT64 value = (desc && !(request->req_flags & req_null)) ? MOV_get_int64(tdbb, desc, 0) : 0;
if (value < 0)
{

View File

@ -276,6 +276,7 @@ bool SortedStream::compareKeys(const UCHAR* p, const UCHAR* q) const
fb_assert(m_map->keyItems.getCount() % 2 == 0);
const USHORT count = m_map->keyItems.getCount() / 2;
thread_db* tdbb = JRD_get_thread_data();
for (USHORT i = 0; i < count; i++)
{
@ -295,7 +296,7 @@ bool SortedStream::compareKeys(const UCHAR* p, const UCHAR* q) const
dsc desc2 = item->desc;
desc2.dsc_address = const_cast<UCHAR*>(q) + (IPTR) desc2.dsc_address;
if (MOV_compare(&desc1, &desc2))
if (MOV_compare(tdbb, &desc1, &desc2))
return false;
}
}

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