blob: dd966ade127c287fde04fdc36d6e5d55351571c3 [file] [log] [blame]
/*
* Copyright (c) 2008-2010 Stefan Krah. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "mpdecimal.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <locale.h>
#include <time.h>
#include "io.h"
#include "memory.h"
#include "mptest.h"
#include "mptypes.h"
#include "malloc_fail.h"
#define MAXLINE 400000
#define MAXTOKEN 32
#ifndef _MSC_VER
#include <inttypes.h>
#define ASSERT(p) if (!(p)) {abort();}
#else
#define ASSERT(p) if (!(p)) {mpd_err_fatal("assertion failed");}
#endif
int have_fail = 0;
int have_printed = 0;
static void
mpd_init_rand(mpd_t *x)
{
long r = random() % 100;
uint8_t sign = random()%2;
if (r >= 80) {
mpd_minalloc(x);
}
else if (r >= 60) {
mpd_minalloc(x);
mpd_set_flags(x, sign);
}
else if (r >= 40) {
mpd_setspecial(x, sign, MPD_NAN);
}
else if (r >= 20) {
mpd_setspecial(x, sign, MPD_SNAN);
}
else {
mpd_setspecial(x, sign, MPD_INF);
}
}
static void
mpd_readcontext(mpd_context_t *ctx)
{
#if defined(CONFIG_64)
ctx->prec=1070000000000000000;
ctx->emax=1070000000000000000;
ctx->emin=-1070000000000000000;
#elif defined(CONFIG_32)
/* These ranges are needed for the official testsuite
* and are generally not problematic at all. */
ctx->prec=1070000000;
ctx->emax=1070000000;
ctx->emin=-1070000000;
#else
#error "config not defined"
#endif
ctx->round=MPD_ROUND_HALF_UP;
ctx->traps=MPD_Traps;
ctx->status=0;
ctx->newtrap=0;
ctx->clamp=0;
ctx->allcr=0;
}
static void
mpd_testcontext(mpd_context_t *ctx)
{
#if defined(CONFIG_64)
ctx->prec=999999999;
ctx->emax=MPD_MAX_EMAX;
ctx->emin=MPD_MIN_EMIN;
#elif defined(CONFIG_32)
/* These ranges are needed for the official testsuite
* and are generally not problematic at all. */
ctx->prec=999999999;
ctx->emax=999999999;
ctx->emin=-999999999;
#else
#error "config not defined"
#endif
ctx->round=MPD_ROUND_HALF_UP;
ctx->traps=MPD_Traps;
ctx->status=0;
ctx->newtrap=0;
ctx->clamp=0;
ctx->allcr=0;
}
/* Known differences that are within the spec */
struct result_diff {
const char *id;
const char *calc;
const char *expected;
};
struct status_diff {
const char *id;
uint32_t calc;
uint32_t expected;
};
struct result_diff ulp_cases[] = {
/* Cases where the result is allowed to differ by less than one ULP.
* Only needed if ctx->allcr is 0. */
{ "expx013", "1.001000", "1.001001" },
{ "expx020", "1.000000", "1.000001" },
{ "expx109", "0.999999910000004049999878", "0.999999910000004049999879" },
{ "expx1036", "1.005088", "1.005087" },
{ "expx350", "1.0000000", "1.0000001" },
{ "expx351", "1.0000000", "1.0000001" },
{ "expx352", "1.0000000", "1.0000001" },
{NULL, NULL, NULL}
};
struct status_diff status_cases[] = {
/* With a reduced working precision in mpd_qpow() the status matches. */
{ "pwsx803", MPD_Inexact|MPD_Rounded|MPD_Subnormal|MPD_Underflow, MPD_Inexact|MPD_Rounded },
{NULL, 0, 0}
};
char *skipit[] = {
/* NULL reference, decimal16, decimal32, or decimal128 */
"absx900",
"addx9990",
"addx9991",
"clam090",
"clam091",
"clam092",
"clam093",
"clam094",
"clam095",
"clam096",
"clam097",
"clam098",
"clam099",
"clam189",
"clam190",
"clam191",
"clam192",
"clam193",
"clam194",
"clam195",
"clam196",
"clam197",
"clam198",
"clam199",
"comx990",
"comx991",
"cotx9990",
"cotx9991",
"ctmx9990",
"ctmx9991",
"ddabs900",
"ddadd9990",
"ddadd9991",
"ddcom9990",
"ddcom9991",
"ddcot9990",
"ddcot9991",
"ddctm9990",
"ddctm9991",
"dddiv9998",
"dddiv9999",
"dddvi900",
"dddvi901",
"ddfma2990",
"ddfma2991",
"ddfma39990",
"ddfma39991",
"ddlogb900",
"ddmax900",
"ddmax901",
"ddmxg900",
"ddmxg901",
"ddmin900",
"ddmin901",
"ddmng900",
"ddmng901",
"ddmul9990",
"ddmul9991",
"ddnextm900",
"ddnextm900",
"ddnextp900",
"ddnextp900",
"ddnextt900",
"ddnextt901",
"ddqua998",
"ddqua999",
"ddred900",
"ddrem1000",
"ddrem1001",
"ddrmn1000",
"ddrmn1001",
"ddsub9990",
"ddsub9991",
"ddintx074",
"ddintx094",
"divx9998",
"divx9999",
"dvix900",
"dvix901",
"dqabs900",
"dqadd9990",
"dqadd9991",
"dqcom990",
"dqcom991",
"dqcot9990",
"dqcot9991",
"dqctm9990",
"dqctm9991",
"dqdiv9998",
"dqdiv9999",
"dqdvi900",
"dqdvi901",
"dqfma2990",
"dqfma2991",
"dqadd39990",
"dqadd39991",
"dqlogb900",
"dqmax900",
"dqmax901",
"dqmxg900",
"dqmxg901",
"dqmin900",
"dqmin901",
"dqmng900",
"dqmng901",
"dqmul9990",
"dqmul9991",
"dqnextm900",
"dqnextp900",
"dqnextt900",
"dqnextt901",
"dqqua998",
"dqqua999",
"dqred900",
"dqrem1000",
"dqrem1001",
"dqrmn1000",
"dqrmn1001",
"dqsub9990",
"dqsub9991",
"dqintx074",
"dqintx094",
"expx900",
"fmax2990",
"fmax2991",
"fmax39990",
"fmax39991",
"lnx900",
"logx900",
"logbx900",
"maxx900",
"maxx901",
"mxgx900",
"mxgx901",
"mnm900",
"mnm901",
"mng900",
"mng901",
"minx900",
"mulx990",
"mulx991",
"nextm900",
"nextp900",
"nextt900",
"nextt901",
"plu900",
"powx900",
"powx901",
"pwsx900",
"quax1022",
"quax1023",
"quax1024",
"quax1025",
"quax1026",
"quax1027",
"quax1028",
"quax1029",
"quax0a2",
"quax0a3",
"quax998",
"quax999",
"redx900",
"remx1000",
"remx1001",
"rmnx900",
"rmnx901",
"sqtx9900",
"subx9990",
"subx9991",
/* operand range violations, invalid context */
"expx901",
"expx902",
"expx903",
"expx905",
"lnx901",
"lnx902",
"lnx903",
"lnx905",
"logx901",
"logx902",
"logx903",
"logx905",
"powx1183",
"powx1184",
"powx4001",
"powx4002",
"powx4003",
"powx4005",
"powx4008",
"powx4010",
"powx4012",
"powx4014",
"scbx164",
"scbx165",
"scbx166",
/* skipped for decNumber, too */
"powx4302",
"powx4303",
"powx4303",
"powx4342",
"powx4343",
"pwsx805",
/* disagreement for three arg power */
"pwmx325",
"pwmx326",
NULL
};
static inline int
startswith(const char *token, const char *s)
{
return strncasecmp(token, s, strlen(s)) == 0;
}
static inline int
eqtoken(const char *token, const char *s)
{
return strcasecmp(token, s) == 0;
}
static int
check_skip(char *id)
{
int i;
for (i = 0; skipit[i] != NULL; i++) {
if (eqtoken(id, skipit[i])) {
#if RT_VERBOSITY == 2
if (!have_printed) {
fputs("\n\n", stderr);
have_printed = 1;
}
fprintf(stderr, "SKIP: %s\n", id);
#endif
return 1;
}
}
return 0;
}
static char *
nexttoken(char *cp)
{
static char *start;
static char *end;
if (cp == NULL)
cp = end;
for (; *cp != '\0'; cp++) {
if (isspace((unsigned char)*cp)) {
;
}
else if (*cp == '"') {
start = end = cp+1;
for (; *end != '\0'; end++) {
if (*end == '"' && *(end+1) == '"')
end += 1;
else if (*end == '"')
break;
}
if (*end == '\0')
return NULL;
*end++ = '\0';
return start;
}
else if (*cp == '\'') {
start = end = cp+1;
for (; *end != '\0'; end++) {
if (*end == '\'' && *(end+1) == '\'')
end += 1;
else if (*end == '\'')
break;
}
if (*end == '\0')
return NULL;
*end++ = '\0';
return start;
}
else {
start = end = cp;
for (; *end != '\0'; end++)
if (isspace((unsigned char)*end))
break;
if (*end == '\0')
return NULL;
*end++ = '\0';
return start;
}
}
return NULL;
}
/* split a line into tokens */
static int
split(char *token[], char line[])
{
char *cp;
size_t len;
int n = 0;
cp = nexttoken(line);
while (n < MAXTOKEN && cp != NULL) {
len = strlen(cp);
if ((token[n] = malloc(len+1)) == NULL) {
mpd_err_fatal("out of memory");
}
strcpy(token[n], cp);
cp = nexttoken(NULL);
n++;
}
token[n] = NULL;
return n;
}
static void
freetoken(char **token)
{
while (*token != NULL) {
free(*token++);
}
}
/* returns all expected conditions in a status flag */
static uint32_t
scan_conditions(char **token)
{
char *condition = *token;
uint32_t status = 0;
while (condition != NULL) {
if (startswith(condition, "--"))
break;
else if (eqtoken(condition, "Clamped"))
status |= MPD_Clamped;
else if (eqtoken(condition, "Conversion_syntax"))
status |= MPD_Conversion_syntax;
else if (eqtoken(condition, "Division_by_zero"))
status |= MPD_Division_by_zero;
else if (eqtoken(condition, "Division_impossible"))
status |= MPD_Division_impossible;
else if (eqtoken(condition, "Division_undefined"))
status |= MPD_Division_undefined;
else if (eqtoken(condition, "Fpu_error"))
status |= MPD_Fpu_error;
else if (eqtoken(condition, "Inexact"))
status |= MPD_Inexact;
else if (eqtoken(condition, "Invalid_context"))
status |= MPD_Invalid_context;
else if (eqtoken(condition, "Invalid_operation"))
status |= MPD_Invalid_operation;
else if (eqtoken(condition, "Malloc_error"))
status |= MPD_Malloc_error;
else if (eqtoken(condition, "Not_implemented"))
status |= MPD_Not_implemented;
else if (eqtoken(condition, "Overflow"))
status |= MPD_Overflow;
else if (eqtoken(condition, "Rounded"))
status |= MPD_Rounded;
else if (eqtoken(condition, "Subnormal"))
status |= MPD_Subnormal;
else if (eqtoken(condition, "Underflow"))
status |= MPD_Underflow;
else
mpd_err_fatal("unknown status: %s", condition);
condition = *(++token);
}
return status;
}
static void
compare_expected(const char *calc, const char *expected, uint32_t expected_status,
char *id, mpd_context_t *ctx)
{
char ctxstatus[MPD_MAX_FLAG_STRING];
char expstatus[MPD_MAX_FLAG_STRING];
#ifndef RT_VERBOSITY
/* Do not print known pseudo-failures. */
int i;
/* known ULP diffs */
if (ctx->allcr == 0) {
for (i = 0; ulp_cases[i].id != NULL; i++) {
if (eqtoken(id, ulp_cases[i].id) &&
strcmp(expected, ulp_cases[i].expected) == 0 &&
strcmp(calc, ulp_cases[i].calc) == 0) {
return;
}
}
}
/* known status diffs */
for (i = 0; status_cases[i].id != NULL; i++) {
if (eqtoken(id, status_cases[i].id) &&
expected_status == status_cases[i].expected &&
ctx->status == status_cases[i].calc) {
return;
}
}
#endif
if (strcmp(calc, expected) != 0) {
if (!have_printed) {
fputs("\n\n", stderr);
have_printed = 1;
}
fprintf(stderr, "FAIL: %s calc: %s expected: %s\n",
id, calc, expected);
have_fail = 1;
}
if (ctx->status != expected_status) {
if (!have_printed) {
fputs("\n\n", stderr);
have_printed = 1;
}
mpd_snprint_flags(ctxstatus, MPD_MAX_FLAG_STRING, ctx->status),
mpd_snprint_flags(expstatus, MPD_MAX_FLAG_STRING, expected_status);
fprintf(stderr, "FAIL: %s: status: calc: %s expected: %s\n",
id, ctxstatus, expstatus);
have_fail = 1;
}
}
static int
equalmem(const mpd_t *a, const mpd_t *b)
{
mpd_ssize_t i;
if (a->flags != b->flags) return 0;
if (a->exp != b->exp) return 0;
if (a->len != b->len) return 0;
if (a->digits != b->digits) return 0;
for (i = 0; i < a->len; i++)
if (a->data[i] != b->data[i])
return 0;
return 1;
}
static void
check_equalmem(const mpd_t *a, const mpd_t *b, char *id)
{
if (!equalmem(a, b)) {
fprintf(stderr, "FAIL: const arg changed: %s\n", id);
}
}
static unsigned long
get_testno(char *token)
{
char *number;
number = strpbrk(token, "0123456789");
return strtoul(number, NULL, 10);
}
/* scan a single operand and the expected result */
static int
scan_1op_result(mpd_t *op1, char **result, char *token[], mpd_context_t *ctx)
{
/* operand 1 */
if (token[2] == NULL) {
mpd_err_fatal("parse error at id %s", token[0]);
}
mpd_set_string(op1, token[2], ctx);
/* discard "->" */
if (token[3] == NULL) {
mpd_err_fatal("parse error at id %s", token[0]);
}
/* expected result */
if (token[4] == NULL) {
mpd_err_fatal("parse error at id %s", token[0]);
}
*result = token[4];
return 5;
}
/* scan a single operand and two results */
static int
scan_1op_2results(mpd_t *op1, char **result1, char **result2, char *token[], mpd_context_t *ctx)
{
/* operand 1 */
if (token[2] == NULL) {
mpd_err_fatal("parse error at id %s", token[0]);
}
mpd_set_string(op1, token[2], ctx);
/* discard "->" */
if (token[3] == NULL) {
mpd_err_fatal("parse error at id %s", token[0]);
}
/* expected result1 */
if (token[4] == NULL) {
mpd_err_fatal("parse error at id %s", token[0]);
}
*result1 = token[4];
/* expected result2 */
if (token[5] == NULL) {
mpd_err_fatal("parse error at id %s", token[0]);
}
*result2 = token[5];
return 6;
}
/* scan decimal operand, string operand and the expected result */
static int
scan_1op_str_result(mpd_t *op1, char **op2, char **result, char *token[], mpd_context_t *ctx)
{
/* operand 1 */
if (token[2] == NULL) {
mpd_err_fatal("%s", token[0]);
}
mpd_set_string(op1, token[2], ctx);
/* operand 2 */
if (token[3] == NULL) {
mpd_err_fatal("%s", token[0]);
}
*op2 = token[3];
/* discard "->" */
if (token[4] == NULL) {
mpd_err_fatal("%s", token[0]);
}
/* expected result */
if (token[5] == NULL) {
mpd_err_fatal("%s", token[0]);
}
*result = token[5];
return 6;
}
/* scan two operands and the expected result */
static int
scan_2ops_result(mpd_t *op1, mpd_t *op2, char **result, char *token[], mpd_context_t *ctx)
{
/* operand 1 */
if (token[2] == NULL) {
mpd_err_fatal("%s", token[0]);
}
mpd_set_string(op1, token[2], ctx);
/* operand 2 */
if (token[3] == NULL) {
mpd_err_fatal("%s", token[0]);
}
mpd_set_string(op2, token[3], ctx);
/* discard "->" */
if (token[4] == NULL) {
mpd_err_fatal("%s", token[0]);
}
/* expected result */
if (token[5] == NULL) {
mpd_err_fatal("%s", token[0]);
}
*result = token[5];
return 6;
}
/* scan two operands and two results */
static int
scan_2ops_2results(mpd_t *op1, mpd_t *op2, char **result1, char **result2, char *token[], mpd_context_t *ctx)
{
/* operand 1 */
if (token[2] == NULL) {
mpd_err_fatal("%s", token[0]);
}
mpd_set_string(op1, token[2], ctx);
/* operand 2 */
if (token[3] == NULL) {
mpd_err_fatal("%s", token[0]);
}
mpd_set_string(op2, token[3], ctx);
/* discard "->" */
if (token[4] == NULL) {
mpd_err_fatal("%s", token[0]);
}
/* expected result1 */
if (token[5] == NULL) {
mpd_err_fatal("%s", token[0]);
}
*result1 = token[5];
/* expected result2 */
if (token[6] == NULL) {
mpd_err_fatal("%s", token[0]);
}
*result2 = token[6];
return 7;
}
/* scan three operands and the expected result */
static int
scan_3ops_result(mpd_t *op1, mpd_t *op2, mpd_t *op3, char **result, char *token[], mpd_context_t *ctx)
{
/* operand 1 */
if (token[2] == NULL) {
mpd_err_fatal("%s", token[0]);
}
mpd_set_string(op1, token[2], ctx);
/* operand 2 */
if (token[3] == NULL) {
mpd_err_fatal("%s", token[0]);
}
mpd_set_string(op2, token[3], ctx);
/* operand 2 */
if (token[4] == NULL) {
mpd_err_fatal("%s", token[0]);
}
mpd_set_string(op3, token[4], ctx);
/* discard "->" */
if (token[5] == NULL) {
mpd_err_fatal("%s", token[0]);
}
/* expected result */
if (token[6] == NULL) {
mpd_err_fatal("%s", token[0]);
}
*result = token[6];
return 7;
}
mpd_t *op, *op1, *op2, *op3;
mpd_t *tmp, *tmp1, *tmp2, *tmp3;
mpd_t *result, *result1, *result2;
/*
* Test a function returning pointer to char, accepting:
* op1, context
*
* This function is used for "toSci", "toEng" and "apply"
* and does not use a maxctx for the conversion of the operand.
*/
static void
_cp_MpdCtx(char **token, char *(*func)(const mpd_t *, int), mpd_context_t *ctx)
{
char *calc;
char *expected, *expected_fail;
uint32_t expstatus;
int n;
ctx->status = 0;
/* status should be set in conversion */
n = scan_1op_result(op, &expected, token, ctx);
/* scan expected conditions */
expstatus = scan_conditions(token+n);
/* Allocation failures for mpd_set_string */
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
mpd_init_rand(tmp);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
(void)scan_1op_result(tmp, &expected_fail, token, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(tmp))
}
ASSERT(strcmp(expected, expected_fail) == 0)
ASSERT(mpd_cmp_total(tmp, op) == 0)
/* make a copy of the operand */
mpd_init_rand(tmp);
mpd_copy(tmp, op, ctx);
calc = func(tmp, 1);
/* compare the calculated result to the expected result */
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp, op, token[0]);
/* Allocation failures */
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
mpd_init_rand(tmp);
mpd_copy(tmp, op, ctx);
mpd_set_alloc_fail(ctx);
calc = func(tmp, 1);
mpd_set_alloc(ctx);
if (calc != NULL) {
break;
}
}
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp, op, token[0]);
}
/* Quick and dirty: parse hex escape sequences as printed in bytestring
* output of Python3x. */
static char *
parse_escapes(const char *s)
{
char hex[5];
char *result, *cp;
unsigned int u;
int n;
cp = result = malloc(strlen(s)+1);
if (result == NULL) {
return NULL;
}
hex[0] = '0';
hex[1] = '\0';
while (*s) {
if (*s == '\\' && *(s+1) == 'x') {
for (n = 1; n < 4; n++) {
if (!s[n]) {
free(result);
return NULL;
}
hex[n] = s[n];
}
hex[n] = '\0';
sscanf(hex, "%x%n", &u, &n);
*cp++ = u;
s += n;
}
else {
*cp++ = *s++;
}
}
*cp = '\0';
return result;
}
/*
* Test a function returning pointer to char, accepting:
* op1, fmt, context
*
* This function is used for "mpd_format".
*/
static void
_cp_MpdFmtCtx(char **token, char *(*func)(const mpd_t *, const char *, mpd_context_t *), mpd_context_t *ctx)
{
mpd_context_t maxctx;
char *fmt;
char *calc;
char *expected;
uint32_t expstatus;
int n;
mpd_readcontext(&maxctx);
maxctx.traps = MPD_Malloc_error;
/* conversion should be done as if there were no limits */
n = scan_1op_str_result(op1, &fmt, &expected, token, &maxctx);
fmt = parse_escapes(fmt);
expected = parse_escapes(expected);
expstatus = scan_conditions(token+n);
mpd_init_rand(tmp);
mpd_copy(tmp, op1, ctx);
ctx->status = 0;
calc = func(tmp, fmt, ctx);
if (calc == NULL) {
calc = __mingw_dfp_get_globals()->mpd_callocfunc(1,5);
memcpy(calc,"NULL",4);
}
/* compare the calculated result to the expected result */
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp, op1, token[0]);
/* Allocation failures */
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
mpd_init_rand(tmp);
mpd_copy(tmp, op1, ctx);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
calc = func(tmp, fmt, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(calc == NULL)
}
if (calc == NULL) {
calc = __mingw_dfp_get_globals()->mpd_callocfunc(1,5);
memcpy(calc,"NULL",4);
}
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp, op1, token[0]);
free(fmt);
free(expected);
}
/*
* Test a function returning pointer to const char, accepting:
* op1, context
*/
static void
_ccp_MpdCtx(char **token, const char *(*func)(const mpd_t *, const mpd_context_t *), mpd_context_t *ctx)
{
mpd_context_t maxctx;
const char *calc;
char *expected;
uint32_t expstatus;
int n;
mpd_readcontext(&maxctx);
maxctx.traps = MPD_Malloc_error;
/* conversion should be done as if there were no limits */
n = scan_1op_result(op, &expected, token, &maxctx);
/* scan expected conditions */
expstatus = scan_conditions(token+n);
mpd_init_rand(tmp);
mpd_copy(tmp, op, ctx);
ctx->status = 0;
calc = func(tmp, ctx);
compare_expected(calc, expected, expstatus, token[0], ctx);
check_equalmem(tmp, op, token[0]);
/* Allocation failures */
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
mpd_init_rand(tmp);
mpd_copy(tmp, op, ctx);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
calc = func(tmp, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(calc == NULL)
}
compare_expected(calc, expected, expstatus, token[0], ctx);
check_equalmem(tmp, op, token[0]);
}
/* Test a unary function */
static void
_Res_Op_Ctx(char *token[], void (*func)(mpd_t *, const mpd_t *, mpd_context_t *), mpd_context_t *ctx)
{
mpd_context_t maxctx;
char *calc;
char *expected;
uint32_t expstatus;
int n, incr;
mpd_readcontext(&maxctx);
maxctx.traps = MPD_Malloc_error;
n = scan_1op_result(op, &expected, token, &maxctx);
/* scan expected conditions */
expstatus = scan_conditions(token+n);
/* result and tmp are distinct decimals */
mpd_init_rand(tmp);
mpd_copy(tmp, op, ctx);
mpd_init_rand(result);
ctx->status = 0;
mpd_set_alloc_count(ctx);
func(result, tmp, ctx);
mpd_set_alloc(ctx);
calc = mpd_to_sci(result, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp, op, token[0]);
/* Allocation failures */
incr = 1;
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail += incr) {
mpd_init_rand(tmp);
mpd_copy(tmp, op, ctx);
mpd_minalloc(result);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
func(result, tmp, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(result))
if (alloc_fail > 50) {
incr = (int)(alloc_count*0.02) + 1;
}
}
calc = mpd_to_sci(result, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp, op, token[0]);
/* result equals operand */
mpd_init_rand(tmp);
mpd_copy(tmp, op, ctx);
ctx->status = 0;
mpd_set_alloc_count(ctx);
func(tmp, tmp, ctx);
mpd_set_alloc(ctx);
calc = mpd_to_sci(tmp, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
/* Allocation failures */
incr = 1;
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail += incr) {
mpd_init_rand(tmp);
mpd_copy(tmp, op, ctx);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
func(tmp, tmp, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(tmp))
if (alloc_fail > 50) {
incr = (int)(alloc_count*0.02) + 1;
}
}
calc = mpd_to_sci(tmp, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
}
/* Test a binary function */
static void
_Res_Binop_Ctx(char *token[], void (*func)(mpd_t *, const mpd_t *, const mpd_t *, mpd_context_t *), mpd_context_t *ctx)
{
mpd_context_t maxctx;
char *calc;
char *expected;
uint32_t expstatus;
int n, incr;
mpd_readcontext(&maxctx);
maxctx.traps = MPD_Malloc_error;
n = scan_2ops_result(op1, op2, &expected, token, &maxctx);
/* scan expected conditions */
expstatus = scan_conditions(token+n);
/* three distinct decimals */
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
mpd_init_rand(result);
ctx->status = 0;
mpd_set_alloc_count(ctx);
func(result, tmp1, tmp2, ctx);
mpd_set_alloc(ctx);
calc = mpd_to_sci(result, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp1, op1, token[0]);
check_equalmem(tmp2, op2, token[0]);
/* Allocation failures */
incr = 1;
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail += incr) {
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
mpd_minalloc(result);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
func(result, tmp1, tmp2, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(result))
if (alloc_fail > 50) {
incr = (int)(alloc_count*0.02) + 1;
}
}
calc = mpd_to_sci(result, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp1, op1, token[0]);
check_equalmem(tmp2, op2, token[0]);
/* result == tmp1 */
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
ctx->status = 0;
mpd_set_alloc_count(ctx);
func(tmp1, tmp1, tmp2, ctx);
mpd_set_alloc(ctx);
calc = mpd_to_sci(tmp1, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp2, op2, token[0]);
/* Allocation failures */
incr = 1;
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail += incr) {
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
func(tmp1, tmp1, tmp2, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(tmp1))
if (alloc_fail > 50) {
incr = (int)(alloc_count*0.02) + 1;
}
}
calc = mpd_to_sci(tmp1, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp2, op2, token[0]);
/* result == tmp2 */
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
ctx->status = 0;
mpd_set_alloc_count(ctx);
func(tmp2, tmp1, tmp2, ctx);
mpd_set_alloc(ctx);
calc = mpd_to_sci(tmp2, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp1, op1, token[0]);
/* Allocation failures */
incr = 1;
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail += incr) {
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
func(tmp2, tmp1, tmp2, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(tmp2))
if (alloc_fail > 50) {
incr = (int)(alloc_count*0.02) + 1;
}
}
calc = mpd_to_sci(tmp2, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp1, op1, token[0]);
}
/* Test a binary function where op1 == op2. */
static void
_Res_EqualBinop_Ctx(char *token[], void (*func)(mpd_t *, const mpd_t *, const mpd_t *, mpd_context_t *), mpd_context_t *ctx)
{
mpd_context_t maxctx;
char *calc;
char *expected;
uint32_t expstatus;
int n;
mpd_readcontext(&maxctx);
maxctx.traps = MPD_Malloc_error;
n = scan_1op_result(op, &expected, token, &maxctx);
/* scan expected conditions */
expstatus = scan_conditions(token+n);
/* equal operands, distinct result */
mpd_init_rand(tmp);
mpd_copy(tmp, op, ctx);
mpd_init_rand(result);
ctx->status = 0;
func(result, tmp, tmp, ctx);
/* hack #1 to resolve disagreement with results generated by decimal.py */
if (expstatus&MPD_Invalid_operation && ctx->status&MPD_Division_impossible) {
expstatus = MPD_Division_impossible;
}
/* hack #2 to resolve disagreement with results generated by decimal.py */
if (expstatus&MPD_Invalid_operation && ctx->status&MPD_Division_undefined) {
expstatus = MPD_Division_undefined;
}
/* hack #3 to resolve disagreement with results generated by decimal.py (power) */
if ((startswith(expected, "-0E") || startswith(expected, "0E")) && mpd_isnan(result)) {
expected = "NaN";
expstatus = MPD_Invalid_operation;
}
calc = mpd_to_sci(result, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp, op, token[0]);
/* Allocation failures */
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
mpd_init_rand(tmp);
mpd_copy(tmp, op, ctx);
mpd_minalloc(result);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
func(result, tmp, tmp, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(result))
}
calc = mpd_to_sci(result, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp, op, token[0]);
/* all parameters equal */
mpd_init_rand(tmp);
mpd_copy(tmp, op, ctx);
ctx->status = 0;
func(tmp, tmp, tmp, ctx);
calc = mpd_to_sci(tmp, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
/* Allocation failures */
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
mpd_init_rand(tmp);
mpd_copy(tmp, op, ctx);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
func(tmp, tmp, tmp, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(tmp))
}
calc = mpd_to_sci(tmp, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
}
/* Test a binary function with a binary result */
static void
_Binres_Binop_Ctx(char *token[], void (*func)(mpd_t *, mpd_t*, const mpd_t *, const mpd_t *, mpd_context_t *), mpd_context_t *ctx)
{
mpd_context_t maxctx;
char *calc;
char *expected1, *expected2;
uint32_t expstatus;
int n, incr;
mpd_readcontext(&maxctx);
maxctx.traps = MPD_Malloc_error;
n = scan_2ops_2results(op1, op2, &expected1, &expected2, token, &maxctx);
/* scan expected conditions */
expstatus = scan_conditions(token+n);
/* four distinct decimals */
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
mpd_init_rand(result1);
mpd_init_rand(result2);
ctx->status = 0;
mpd_set_alloc_count(ctx);
func(result1, result2, tmp1, tmp2, ctx);
mpd_set_alloc(ctx);
/* hack #1 to resolve disagreement with results generated by decimal.py */
if (expstatus&MPD_Invalid_operation && ctx->status&MPD_Division_impossible) {
expstatus = MPD_Division_impossible;
}
/* hack #2 to resolve disagreement with results generated by decimal.py */
if (expstatus&MPD_Invalid_operation && ctx->status&MPD_Division_undefined) {
expstatus = MPD_Division_undefined;
}
/* hack #3 to resolve disagreement with results generated by decimal.py */
if ((startswith(expected1, "-Inf") || startswith(expected1, "Inf")) && mpd_isnan(result1)) {
expected1 = "NaN";
}
calc = mpd_to_sci(result1, 1);
compare_expected(calc, expected1, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
calc = mpd_to_sci(result2, 1);
compare_expected(calc, expected2, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp1, op1, token[0]);
check_equalmem(tmp2, op2, token[0]);
/* Allocation failures */
incr = 1;
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail += incr) {
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
mpd_minalloc(result1);
mpd_minalloc(result2);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
func(result1, result2, tmp1, tmp2, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(result1))
ASSERT(mpd_isnan(result2))
if (alloc_fail > 50) {
incr = (int)(alloc_count*0.02) + 1;
}
}
calc = mpd_to_sci(result1, 1);
compare_expected(calc, expected1, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
calc = mpd_to_sci(result2, 1);
compare_expected(calc, expected2, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp1, op1, token[0]);
check_equalmem(tmp2, op2, token[0]);
/* result1 == tmp1 */
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
mpd_init_rand(result2);
ctx->status = 0;
mpd_set_alloc_count(ctx);
func(tmp1, result2, tmp1, tmp2, ctx);
mpd_set_alloc(ctx);
calc = mpd_to_sci(tmp1, 1);
compare_expected(calc, expected1, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
calc = mpd_to_sci(result2, 1);
compare_expected(calc, expected2, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp2, op2, token[0]);
/* Allocation failures */
incr = 1;
for (alloc_fail = 1; alloc_fail <= INT_MAX; alloc_fail += incr) {
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
mpd_minalloc(result2);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
func(tmp1, result2, tmp1, tmp2, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(tmp1))
ASSERT(mpd_isnan(result2))
if (alloc_fail > 50) {
incr = (int)(alloc_count*0.02) + 1;
}
}
calc = mpd_to_sci(tmp1, 1);
compare_expected(calc, expected1, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
calc = mpd_to_sci(result2, 1);
compare_expected(calc, expected2, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp2, op2, token[0]);
/* result2 == tmp1 */
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
mpd_init_rand(result1);
ctx->status = 0;
mpd_set_alloc_count(ctx);
func(result1, tmp1, tmp1, tmp2, ctx);
mpd_set_alloc(ctx);
calc = mpd_to_sci(result1, 1);
compare_expected(calc, expected1, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
calc = mpd_to_sci(tmp1, 1);
compare_expected(calc, expected2, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp2, op2, token[0]);
/* Allocation failures */
incr = 1;
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail += incr) {
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
mpd_minalloc(result1);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
func(result1, tmp1, tmp1, tmp2, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(result1))
ASSERT(mpd_isnan(tmp1))
if (alloc_fail > 50) {
incr = (int)(alloc_count*0.02) + 1;
}
}
calc = mpd_to_sci(result1, 1);
compare_expected(calc, expected1, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
calc = mpd_to_sci(tmp1, 1);
compare_expected(calc, expected2, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp2, op2, token[0]);
/* result1 == tmp2 */
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
mpd_init_rand(result2);
ctx->status = 0;
mpd_set_alloc_count(ctx);
func(tmp2, result2, tmp1, tmp2, ctx);
mpd_set_alloc(ctx);
calc = mpd_to_sci(tmp2, 1);
compare_expected(calc, expected1, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
calc = mpd_to_sci(result2, 1);
compare_expected(calc, expected2, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp1, op1, token[0]);
/* Allocation failures */
incr = 1;
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail += incr) {
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
mpd_minalloc(result2);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
func(tmp2, result2, tmp1, tmp2, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(tmp2))
ASSERT(mpd_isnan(result2))
if (alloc_fail > 50) {
incr = (int)(alloc_count*0.02) + 1;
}
}
calc = mpd_to_sci(tmp2, 1);
compare_expected(calc, expected1, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
calc = mpd_to_sci(result2, 1);
compare_expected(calc, expected2, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp1, op1, token[0]);
/* result2 == tmp2 */
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
mpd_init_rand(result1);
ctx->status = 0;
mpd_set_alloc_count(ctx);
func(result1, tmp2, tmp1, tmp2, ctx);
mpd_set_alloc(ctx);
calc = mpd_to_sci(result1, 1);
compare_expected(calc, expected1, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
calc = mpd_to_sci(tmp2, 1);
compare_expected(calc, expected2, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp1, op1, token[0]);
/* Allocation failures */
incr = 1;
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail += incr) {
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
mpd_minalloc(result1);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
func(result1, tmp2, tmp1, tmp2, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(result1))
ASSERT(mpd_isnan(tmp2))
if (alloc_fail > 50) {
incr = (int)(alloc_count*0.02) + 1;
}
}
calc = mpd_to_sci(result1, 1);
compare_expected(calc, expected1, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
calc = mpd_to_sci(tmp2, 1);
compare_expected(calc, expected2, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp1, op1, token[0]);
/* result1 == tmp1, result2 == tmp2 */
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
ctx->status = 0;
mpd_set_alloc_count(ctx);
func(tmp1, tmp2, tmp1, tmp2, ctx);
mpd_set_alloc(ctx);
calc = mpd_to_sci(tmp1, 1);
compare_expected(calc, expected1, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
calc = mpd_to_sci(tmp2, 1);
compare_expected(calc, expected2, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
/* Allocation failures */
incr = 1;
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail += incr) {
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
func(tmp1, tmp2, tmp1, tmp2, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(tmp1))
ASSERT(mpd_isnan(tmp2))
if (alloc_fail > 50) {
incr = (int)(alloc_count*0.02) + 1;
}
}
calc = mpd_to_sci(tmp1, 1);
compare_expected(calc, expected1, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
calc = mpd_to_sci(tmp2, 1);
compare_expected(calc, expected2, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
/* result1 == tmp2, result2 == tmp1 */
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
ctx->status = 0;
mpd_set_alloc_count(ctx);
func(tmp2, tmp1, tmp1, tmp2, ctx);
mpd_set_alloc(ctx);
calc = mpd_to_sci(tmp2, 1);
compare_expected(calc, expected1, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
calc = mpd_to_sci(tmp1, 1);
compare_expected(calc, expected2, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
/* Allocation failures */
incr = 1;
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail += incr) {
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
func(tmp2, tmp1, tmp1, tmp2, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(tmp2))
ASSERT(mpd_isnan(tmp1))
if (alloc_fail > 50) {
incr = (int)(alloc_count*0.02) + 1;
}
}
calc = mpd_to_sci(tmp2, 1);
compare_expected(calc, expected1, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
calc = mpd_to_sci(tmp1, 1);
compare_expected(calc, expected2, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
}
/* Test a binary function with a binary result; equal operands */
static void
_Binres_EqualBinop_Ctx(char *token[], void (*func)(mpd_t *, mpd_t*, const mpd_t *, const mpd_t *, mpd_context_t *), mpd_context_t *ctx)
{
mpd_context_t maxctx;
char *calc;
char *expected1, *expected2;
uint32_t expstatus;
int n;
mpd_readcontext(&maxctx);
maxctx.traps = MPD_Malloc_error;
n = scan_1op_2results(op, &expected1, &expected2, token, &maxctx);
/* scan expected conditions */
expstatus = scan_conditions(token+n);
/* distinct results */
mpd_init_rand(tmp);
mpd_copy(tmp, op, ctx);
mpd_init_rand(result1);
mpd_init_rand(result2);
ctx->status = 0;
func(result1, result2, tmp, tmp, ctx);
/* hack #1 to resolve disagreement with results generated by decimal.py */
if (expstatus&MPD_Invalid_operation && ctx->status&MPD_Division_impossible) {
expstatus = MPD_Division_impossible;
}
/* hack #2 to resolve disagreement with results generated by decimal.py */
if (expstatus&MPD_Invalid_operation && ctx->status&MPD_Division_undefined) {
expstatus = MPD_Division_undefined;
}
/* hack #3 to resolve disagreement with results generated by decimal.py */
if ((startswith(expected1, "-Inf") || startswith(expected1, "Inf")) && mpd_isnan(result1)) {
expected1 = "NaN";
}
calc = mpd_to_sci(result1, 1);
compare_expected(calc, expected1, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
calc = mpd_to_sci(result2, 1);
compare_expected(calc, expected2, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp, op, token[0]);
/* Allocation failures */
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
mpd_init_rand(tmp);
mpd_copy(tmp, op, ctx);
mpd_minalloc(result1);
mpd_minalloc(result2);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
func(result1, result2, tmp, tmp, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(result1))
ASSERT(mpd_isnan(result2))
}
calc = mpd_to_sci(result1, 1);
compare_expected(calc, expected1, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
calc = mpd_to_sci(result2, 1);
compare_expected(calc, expected2, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp, op, token[0]);
/* result1 == tmp */
mpd_init_rand(tmp);
mpd_copy(tmp, op, ctx);
mpd_init_rand(result2);
ctx->status = 0;
func(tmp, result2, tmp, tmp, ctx);
calc = mpd_to_sci(tmp, 1);
compare_expected(calc, expected1, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
calc = mpd_to_sci(result2, 1);
compare_expected(calc, expected2, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
/* Allocation failures */
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
mpd_init_rand(tmp);
mpd_copy(tmp, op, ctx);
mpd_minalloc(result2);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
func(tmp, result2, tmp, tmp, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(tmp))
ASSERT(mpd_isnan(result2))
}
calc = mpd_to_sci(tmp, 1);
compare_expected(calc, expected1, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
calc = mpd_to_sci(result2, 1);
compare_expected(calc, expected2, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
/* result2 == tmp */
mpd_init_rand(tmp);
mpd_copy(tmp, op, ctx);
mpd_init_rand(result1);
ctx->status = 0;
func(result1, tmp, tmp, tmp, ctx);
calc = mpd_to_sci(result1, 1);
compare_expected(calc, expected1, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
calc = mpd_to_sci(tmp, 1);
compare_expected(calc, expected2, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
/* Allocation failures */
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
mpd_init_rand(tmp);
mpd_copy(tmp, op, ctx);
mpd_minalloc(result1);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
func(result1, tmp, tmp, tmp, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(result1))
ASSERT(mpd_isnan(tmp))
}
calc = mpd_to_sci(result1, 1);
compare_expected(calc, expected1, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
calc = mpd_to_sci(tmp, 1);
compare_expected(calc, expected2, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
}
/* Test a ternary function */
static void
_Res_Ternop_Ctx(char *token[], void (*func)(mpd_t *, const mpd_t *, const mpd_t *, const mpd_t *, mpd_context_t *), mpd_context_t *ctx)
{
mpd_context_t maxctx;
char *calc;
char *expected;
uint32_t expstatus;
int n, incr;
mpd_readcontext(&maxctx);
maxctx.traps = MPD_Malloc_error;
n = scan_3ops_result(op1, op2, op3, &expected, token, &maxctx);
/* scan expected conditions */
expstatus = scan_conditions(token+n);
/* four distinct decimals */
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_init_rand(tmp3);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
mpd_copy(tmp3, op3, ctx);
mpd_init_rand(result);
ctx->status = 0;
mpd_set_alloc_count(ctx);
func(result, tmp1, tmp2, tmp3, ctx);
mpd_set_alloc(ctx);
calc = mpd_to_sci(result, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp1, op1, token[0]);
check_equalmem(tmp2, op2, token[0]);
check_equalmem(tmp3, op3, token[0]);
/* Allocation failures */
incr = 1;
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail += incr) {
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_init_rand(tmp3);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
mpd_copy(tmp3, op3, ctx);
mpd_minalloc(result);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
func(result, tmp1, tmp2, tmp3, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(result))
if (alloc_fail > 100) {
incr = (int)(alloc_count*0.02) + 1;
}
}
calc = mpd_to_sci(result, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp1, op1, token[0]);
check_equalmem(tmp2, op2, token[0]);
check_equalmem(tmp3, op3, token[0]);
/* result == tmp1 */
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_init_rand(tmp3);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
mpd_copy(tmp3, op3, ctx);
ctx->status = 0;
mpd_set_alloc_count(ctx);
func(tmp1, tmp1, tmp2, tmp3, ctx);
mpd_set_alloc(ctx);
calc = mpd_to_sci(tmp1, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp2, op2, token[0]);
check_equalmem(tmp3, op3, token[0]);
/* Allocation failures */
incr = 1;
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail += incr) {
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_init_rand(tmp3);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
mpd_copy(tmp3, op3, ctx);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
func(tmp1, tmp1, tmp2, tmp3, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(tmp1))
if (alloc_fail > 100) {
incr = (int)(alloc_count*0.02) + 1;
}
}
calc = mpd_to_sci(tmp1, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp2, op2, token[0]);
check_equalmem(tmp3, op3, token[0]);
/* result == tmp2 */
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_init_rand(tmp3);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
mpd_copy(tmp3, op3, ctx);
ctx->status = 0;
mpd_set_alloc_count(ctx);
func(tmp2, tmp1, tmp2, tmp3, ctx);
mpd_set_alloc(ctx);
calc = mpd_to_sci(tmp2, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp1, op1, token[0]);
check_equalmem(tmp3, op3, token[0]);
/* Allocation failures */
incr = 1;
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail += incr) {
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_init_rand(tmp3);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
mpd_copy(tmp3, op3, ctx);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
func(tmp2, tmp1, tmp2, tmp3, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(tmp2))
if (alloc_fail > 100) {
incr = (int)(alloc_count*0.02) + 1;
}
}
calc = mpd_to_sci(tmp2, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp1, op1, token[0]);
check_equalmem(tmp3, op3, token[0]);
/* result == tmp3 */
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_init_rand(tmp3);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
mpd_copy(tmp3, op3, ctx);
ctx->status = 0;
mpd_set_alloc_count(ctx);
func(tmp3, tmp1, tmp2, tmp3, ctx);
mpd_set_alloc(ctx);
calc = mpd_to_sci(tmp3, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp1, op1, token[0]);
check_equalmem(tmp2, op2, token[0]);
/* Allocation failures */
incr = 1;
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail += incr) {
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_init_rand(tmp3);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
mpd_copy(tmp3, op3, ctx);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
func(tmp3, tmp1, tmp2, tmp3, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(tmp3))
if (alloc_fail > 100) {
incr = (int)(alloc_count*0.02) + 1;
}
}
calc = mpd_to_sci(tmp3, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp1, op1, token[0]);
check_equalmem(tmp2, op2, token[0]);
}
/* Test a ternary function, first and second operand equal */
static void
_Res_EqEqOp_Ctx(char *token[], void (*func)(mpd_t *, const mpd_t *, const mpd_t *, const mpd_t *, mpd_context_t *), mpd_context_t *ctx)
{
mpd_context_t maxctx;
char *calc;
char *expected;
uint32_t expstatus;
int n;
mpd_readcontext(&maxctx);
maxctx.traps = MPD_Malloc_error;
n = scan_2ops_result(op1, op2, &expected, token, &maxctx);
/* scan expected conditions */
expstatus = scan_conditions(token+n);
/* distinct result */
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
mpd_init_rand(result);
ctx->status = 0;
func(result, tmp1, tmp1, tmp2, ctx);
calc = mpd_to_sci(result, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp1, op1, token[0]);
check_equalmem(tmp2, op2, token[0]);
/* Allocation failures */
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
mpd_minalloc(result);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
func(result, tmp1, tmp1, tmp2, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(result))
}
calc = mpd_to_sci(result, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp1, op1, token[0]);
check_equalmem(tmp2, op2, token[0]);
/* result == tmp1 */
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
ctx->status = 0;
func(tmp1, tmp1, tmp1, tmp2, ctx);
calc = mpd_to_sci(tmp1, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp2, op2, token[0]);
/* Allocation failures */
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
func(tmp1, tmp1, tmp1, tmp2, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(tmp1))
}
calc = mpd_to_sci(tmp1, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp2, op2, token[0]);
/* result == tmp2 */
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
ctx->status = 0;
func(tmp2, tmp1, tmp1, tmp2, ctx);
calc = mpd_to_sci(tmp2, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp1, op1, token[0]);
/* Allocation failures */
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
func(tmp2, tmp1, tmp1, tmp2, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(tmp2))
}
calc = mpd_to_sci(tmp2, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp1, op1, token[0]);
}
/* Test a ternary function, first and third operand equal */
static void
_Res_EqOpEq_Ctx(char *token[], void (*func)(mpd_t *, const mpd_t *, const mpd_t *, const mpd_t *, mpd_context_t *), mpd_context_t *ctx)
{
mpd_context_t maxctx;
char *calc;
char *expected;
uint32_t expstatus;
int n;
mpd_readcontext(&maxctx);
maxctx.traps = MPD_Malloc_error;
n = scan_2ops_result(op1, op2, &expected, token, &maxctx);
/* scan expected conditions */
expstatus = scan_conditions(token+n);
/* distinct result */
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
mpd_init_rand(result);
ctx->status = 0;
func(result, tmp1, tmp2, tmp1, ctx);
calc = mpd_to_sci(result, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp1, op1, token[0]);
check_equalmem(tmp2, op2, token[0]);
/* Allocation failures */
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
mpd_minalloc(result);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
func(result, tmp1, tmp2, tmp1, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(result))
}
calc = mpd_to_sci(result, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp1, op1, token[0]);
check_equalmem(tmp2, op2, token[0]);
/* result == tmp1 */
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
ctx->status = 0;
func(tmp1, tmp1, tmp2, tmp1, ctx);
calc = mpd_to_sci(tmp1, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp2, op2, token[0]);
/* Allocation failures */
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
func(tmp1, tmp1, tmp2, tmp1, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(tmp1))
}
calc = mpd_to_sci(tmp1, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp2, op2, token[0]);
/* result == tmp2 */
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
ctx->status = 0;
func(tmp2, tmp1, tmp2, tmp1, ctx);
calc = mpd_to_sci(tmp2, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp1, op1, token[0]);
/* Allocation failures */
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
func(tmp2, tmp1, tmp2, tmp1, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(tmp2))
}
calc = mpd_to_sci(tmp2, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp1, op1, token[0]);
}
/* Test a ternary function, second and third operand equal */
static void
_Res_OpEqEq_Ctx(char *token[], void (*func)(mpd_t *, const mpd_t *, const mpd_t *, const mpd_t *, mpd_context_t *), mpd_context_t *ctx)
{
mpd_context_t maxctx;
char *calc;
char *expected;
uint32_t expstatus;
int n;
mpd_readcontext(&maxctx);
maxctx.traps = MPD_Malloc_error;
n = scan_2ops_result(op1, op2, &expected, token, &maxctx);
/* scan expected conditions */
expstatus = scan_conditions(token+n);
/* distinct result */
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
mpd_init_rand(result);
ctx->status = 0;
func(result, tmp2, tmp1, tmp1, ctx);
calc = mpd_to_sci(result, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp1, op1, token[0]);
check_equalmem(tmp2, op2, token[0]);
/* Allocation failures */
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
mpd_minalloc(result);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
func(result, tmp2, tmp1, tmp1, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(result))
}
calc = mpd_to_sci(result, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp1, op1, token[0]);
check_equalmem(tmp2, op2, token[0]);
/* result == tmp1 */
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
ctx->status = 0;
func(tmp1, tmp2, tmp1, tmp1, ctx);
calc = mpd_to_sci(tmp1, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp2, op2, token[0]);
/* Allocation failures */
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
func(tmp1, tmp2, tmp1, tmp1, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(tmp1))
}
calc = mpd_to_sci(tmp1, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp2, op2, token[0]);
/* result == tmp2 */
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
ctx->status = 0;
func(tmp2, tmp2, tmp1, tmp1, ctx);
calc = mpd_to_sci(tmp2, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp1, op1, token[0]);
/* Allocation failures */
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
func(tmp2, tmp2, tmp1, tmp1, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(tmp2))
}
calc = mpd_to_sci(tmp2, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp1, op1, token[0]);
}
/* Test a ternary function, first, second and third operand equal */
static void
_Res_EqEqEq_Ctx(char *token[], void (*func)(mpd_t *, const mpd_t *, const mpd_t *, const mpd_t *, mpd_context_t *), mpd_context_t *ctx)
{
mpd_context_t maxctx;
char *calc;
char *expected;
uint32_t expstatus;
int n;
mpd_readcontext(&maxctx);
maxctx.traps = MPD_Malloc_error;
n = scan_1op_result(op, &expected, token, &maxctx);
/* scan expected conditions */
expstatus = scan_conditions(token+n);
/* distinct result */
mpd_init_rand(tmp);
mpd_copy(tmp, op, ctx);
mpd_init_rand(result);
ctx->status = 0;
func(result, tmp, tmp, tmp, ctx);
calc = mpd_to_sci(result, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp, op, token[0]);
/* Allocation failures */
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
mpd_init_rand(tmp);
mpd_copy(tmp, op, ctx);
mpd_minalloc(result);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
func(result, tmp, tmp, tmp, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(result))
}
calc = mpd_to_sci(result, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp, op, token[0]);
/* result == tmp */
mpd_init_rand(tmp);
mpd_copy(tmp, op, ctx);
ctx->status = 0;
func(tmp, tmp, tmp, tmp, ctx);
calc = mpd_to_sci(tmp, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
/* Allocation failures */
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
mpd_init_rand(tmp);
mpd_copy(tmp, op, ctx);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
func(tmp, tmp, tmp, tmp, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(tmp))
}
calc = mpd_to_sci(tmp, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
}
/*
* Test a binary function that returns an additional integer result.
* Used for the comparison functions.
*/
static void
_Int_Res_Binop_Ctx(char *token[], int (*func)(mpd_t *, const mpd_t *, const mpd_t *, mpd_context_t *), mpd_context_t *ctx)
{
mpd_context_t maxctx;
char *calc;
char *expected;
int int_result;
char buf[11];
uint32_t expstatus;
int n;
mpd_readcontext(&maxctx);
maxctx.traps = MPD_Malloc_error;
n = scan_2ops_result(op1, op2, &expected, token, &maxctx);
/* scan expected conditions */
expstatus = scan_conditions(token+n);
/* three distinct decimals */
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
mpd_init_rand(result);
ctx->status = 0;
int_result = func(result, tmp1, tmp2, ctx);
calc = mpd_to_sci(result, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
snprintf(buf, 11, "%d", int_result);
if (int_result != INT_MAX) { /* NaN cases are skipped for the int_retval */
compare_expected(buf, expected, expstatus, token[0], ctx);
}
check_equalmem(tmp1, op1, token[0]);
check_equalmem(tmp2, op2, token[0]);
/* Allocation failures */
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
mpd_minalloc(result);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
int_result = func(result, tmp1, tmp2, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(result))
}
calc = mpd_to_sci(result, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
snprintf(buf, 11, "%d", int_result);
if (int_result != INT_MAX) { /* NaN cases are skipped for the int_retval */
compare_expected(buf, expected, expstatus, token[0], ctx);
}
check_equalmem(tmp1, op1, token[0]);
check_equalmem(tmp2, op2, token[0]);
/* result == tmp1 */
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
ctx->status = 0;
int_result = func(tmp1, tmp1, tmp2, ctx);
calc = mpd_to_sci(tmp1, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
snprintf(buf, 11, "%d", int_result);
if (int_result != INT_MAX) { /* NaN cases are skipped for the int_retval */
compare_expected(buf, expected, expstatus, token[0], ctx);
}
check_equalmem(tmp2, op2, token[0]);
/* Allocation failures */
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
int_result = func(tmp1, tmp1, tmp2, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(tmp1))
}
calc = mpd_to_sci(tmp1, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
snprintf(buf, 11, "%d", int_result);
if (int_result != INT_MAX) { /* NaN cases are skipped for the int_retval */
compare_expected(buf, expected, expstatus, token[0], ctx);
}
check_equalmem(tmp2, op2, token[0]);
/* result == tmp2 */
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
ctx->status = 0;
int_result = func(tmp2, tmp1, tmp2, ctx);
calc = mpd_to_sci(tmp2, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
snprintf(buf, 11, "%d", int_result);
if (int_result != INT_MAX) { /* NaN cases are skipped for the int_retval */
compare_expected(buf, expected, expstatus, token[0], ctx);
}
check_equalmem(tmp1, op1, token[0]);
/* Allocation failures */
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
int_result = func(tmp2, tmp1, tmp2, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(tmp2))
}
calc = mpd_to_sci(tmp2, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
snprintf(buf, 11, "%d", int_result);
if (int_result != INT_MAX) { /* NaN cases are skipped for the int_retval */
compare_expected(buf, expected, expstatus, token[0], ctx);
}
check_equalmem(tmp1, op1, token[0]);
}
/*
* Test a binary function that returns an additional integer result.
* Equal operands.
* Used for the comparison functions.
*/
static void
_Int_Res_EqualBinop_Ctx(char *token[], int (*func)(mpd_t *, const mpd_t *, const mpd_t *, mpd_context_t *), mpd_context_t *ctx)
{
mpd_context_t maxctx;
char *calc;
char *expected;
int int_result;
char buf[11];
uint32_t expstatus;
int n;
mpd_readcontext(&maxctx);
maxctx.traps = MPD_Malloc_error;
n = scan_1op_result(op, &expected, token, &maxctx);
/* scan expected conditions */
expstatus = scan_conditions(token+n);
/* equal operands */
mpd_init_rand(tmp);
mpd_copy(tmp, op, ctx);
mpd_init_rand(result);
ctx->status = 0;
int_result = func(result, tmp, tmp, ctx);
calc = mpd_to_sci(result, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
snprintf(buf, 11, "%d", int_result);
if (int_result != INT_MAX) { /* NaN cases are skipped for the int_retval */
compare_expected(buf, expected, expstatus, token[0], ctx);
}
check_equalmem(tmp, op, token[0]);
/* Allocation failures */
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
mpd_init_rand(tmp);
mpd_copy(tmp, op, ctx);
mpd_minalloc(result);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
int_result = func(result, tmp, tmp, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(result))
}
calc = mpd_to_sci(result, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
snprintf(buf, 11, "%d", int_result);
if (int_result != INT_MAX) { /* NaN cases are skipped for the int_retval */
compare_expected(buf, expected, expstatus, token[0], ctx);
}
check_equalmem(tmp, op, token[0]);
/* all parameters equal */
mpd_init_rand(tmp);
mpd_copy(tmp, op, ctx);
ctx->status = 0;
int_result = func(tmp, tmp, tmp, ctx);
calc = mpd_to_sci(tmp, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
snprintf(buf, 11, "%d", int_result);
if (int_result != INT_MAX) { /* NaN cases are skipped for the int_retval */
compare_expected(buf, expected, expstatus, token[0], ctx);
}
/* Allocation failures */
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
mpd_init_rand(tmp);
mpd_copy(tmp, op, ctx);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
int_result = func(tmp, tmp, tmp, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(tmp))
}
calc = mpd_to_sci(tmp, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
snprintf(buf, 11, "%d", int_result);
if (int_result != INT_MAX) { /* NaN cases are skipped for the int_retval */
compare_expected(buf, expected, expstatus, token[0], ctx);
}
}
/*
* Test a binary function that returns an additional integer result.
* Function does not take a context argument.
* Used for the comparison functions.
*/
static void
_Int_Res_Binop(char *token[], int (*func)(mpd_t *, const mpd_t *, const mpd_t *), mpd_context_t *ctx)
{
mpd_context_t maxctx;
char *calc;
char *expected;
int int_result;
char buf[11];
uint32_t expstatus;
int n;
mpd_readcontext(&maxctx);
maxctx.traps = MPD_Malloc_error;
n = scan_2ops_result(op1, op2, &expected, token, &maxctx);
/* scan expected conditions */
expstatus = scan_conditions(token+n);
/* three distinct decimals */
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
mpd_init_rand(result);
ctx->status = 0;
int_result = func(result, tmp1, tmp2);
calc = mpd_to_sci(result, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
snprintf(buf, 11, "%d", int_result);
if (int_result != INT_MAX) { /* NaN cases are skipped for the int_retval */
compare_expected(buf, expected, expstatus, token[0], ctx);
}
check_equalmem(tmp1, op1, token[0]);
check_equalmem(tmp2, op2, token[0]);
/* Allocation failures */
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
mpd_minalloc(result);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
int_result = func(result, tmp1, tmp2);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(result))
}
calc = mpd_to_sci(result, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
snprintf(buf, 11, "%d", int_result);
if (int_result != INT_MAX) { /* NaN cases are skipped for the int_retval */
compare_expected(buf, expected, expstatus, token[0], ctx);
}
check_equalmem(tmp1, op1, token[0]);
check_equalmem(tmp2, op2, token[0]);
/* result == tmp1 */
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
ctx->status = 0;
int_result = func(tmp1, tmp1, tmp2);
calc = mpd_to_sci(tmp1, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
snprintf(buf, 11, "%d", int_result);
if (int_result != INT_MAX) { /* NaN cases are skipped for the int_retval */
compare_expected(buf, expected, expstatus, token[0], ctx);
}
check_equalmem(tmp2, op2, token[0]);
/* Allocation failures */
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
int_result = func(tmp1, tmp1, tmp2);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(tmp1))
}
calc = mpd_to_sci(tmp1, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
snprintf(buf, 11, "%d", int_result);
if (int_result != INT_MAX) { /* NaN cases are skipped for the int_retval */
compare_expected(buf, expected, expstatus, token[0], ctx);
}
check_equalmem(tmp2, op2, token[0]);
/* result == tmp2 */
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
ctx->status = 0;
int_result = func(tmp2, tmp1, tmp2);
calc = mpd_to_sci(tmp2, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
snprintf(buf, 11, "%d", int_result);
if (int_result != INT_MAX) { /* NaN cases are skipped for the int_retval */
compare_expected(buf, expected, expstatus, token[0], ctx);
}
check_equalmem(tmp1, op1, token[0]);
/* Allocation failures */
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
int_result = func(tmp2, tmp1, tmp2);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(tmp2))
}
calc = mpd_to_sci(tmp2, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
snprintf(buf, 11, "%d", int_result);
if (int_result != INT_MAX) { /* NaN cases are skipped for the int_retval */
compare_expected(buf, expected, expstatus, token[0], ctx);
}
check_equalmem(tmp1, op1, token[0]);
}
/*
* Test a binary function that returns an additional integer result.
* Function does not take a context argument.
* Equal operands.
* Used for the comparison functions.
*/
static void
_Int_Res_EqualBinop(char *token[], int (*func)(mpd_t *, const mpd_t *, const mpd_t *), mpd_context_t *ctx)
{
mpd_context_t maxctx;
char *calc;
char *expected;
int int_result;
char buf[11];
uint32_t expstatus;
int n;
mpd_readcontext(&maxctx);
maxctx.traps = MPD_Malloc_error;
n = scan_1op_result(op, &expected, token, &maxctx);
/* scan expected conditions */
expstatus = scan_conditions(token+n);
/* equal operands */
mpd_init_rand(tmp);
mpd_copy(tmp, op, ctx);
mpd_init_rand(result);
ctx->status = 0;
int_result = func(result, tmp, tmp);
calc = mpd_to_sci(result, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
snprintf(buf, 11, "%d", int_result);
if (int_result != INT_MAX) { /* NaN cases are skipped for the int_retval */
compare_expected(buf, expected, expstatus, token[0], ctx);
}
check_equalmem(tmp, op, token[0]);
/* Allocation failures */
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
mpd_init_rand(tmp);
mpd_copy(tmp, op, ctx);
mpd_minalloc(result);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
int_result = func(result, tmp, tmp);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(result))
}
calc = mpd_to_sci(result, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
snprintf(buf, 11, "%d", int_result);
if (int_result != INT_MAX) { /* NaN cases are skipped for the int_retval */
compare_expected(buf, expected, expstatus, token[0], ctx);
}
check_equalmem(tmp, op, token[0]);
/* all parameters equal */
mpd_init_rand(tmp);
mpd_copy(tmp, op, ctx);
ctx->status = 0;
int_result = func(tmp, tmp, tmp);
calc = mpd_to_sci(tmp, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
snprintf(buf, 11, "%d", int_result);
if (int_result != INT_MAX) { /* NaN cases are skipped for the int_retval */
compare_expected(buf, expected, expstatus, token[0], ctx);
}
/* Allocation failures */
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
mpd_init_rand(tmp);
mpd_copy(tmp, op, ctx);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
int_result = func(tmp, tmp, tmp);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(tmp))
}
calc = mpd_to_sci(tmp, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
snprintf(buf, 11, "%d", int_result);
if (int_result != INT_MAX) { /* NaN cases are skipped for the int_retval */
compare_expected(buf, expected, expstatus, token[0], ctx);
}
}
/*
* Test a binary function that returns only an integer result.
* Used for the cmp functions.
*/
enum {SKIP_NONE, SKIP_NAN, SKIP_NONINT};
static void
_Int_Binop_Ctx(int skip, char *token[], int (*func)(const mpd_t *, const mpd_t *, mpd_context_t *), mpd_context_t *ctx)
{
mpd_context_t maxctx;
int int_result;
char buf[11];
char *expected;
uint32_t expstatus;
int n;
mpd_readcontext(&maxctx);
maxctx.traps = MPD_Malloc_error;
n = scan_2ops_result(op1, op2, &expected, token, &maxctx);
/* scan expected conditions */
expstatus = scan_conditions(token+n);
/* two distinct decimals */
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
ctx->status = 0;
int_result = func(tmp1, tmp2, ctx);
snprintf(buf, 11, "%d", int_result);
if (!(skip && int_result == INT_MAX)) { /* NaN cases are skipped for the int_retval */
compare_expected(buf, expected, expstatus, token[0], ctx);
}
check_equalmem(tmp1, op1, token[0]);
check_equalmem(tmp2, op2, token[0]);
/* Allocation failures */
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
int_result = func(tmp1, tmp2, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(int_result== INT_MAX)
}
snprintf(buf, 11, "%d", int_result);
if (!(skip && int_result == INT_MAX)) { /* NaN cases are skipped for the int_retval */
compare_expected(buf, expected, expstatus, token[0], ctx);
}
check_equalmem(tmp1, op1, token[0]);
check_equalmem(tmp2, op2, token[0]);
}
/*
* Test a binary function that returns only an integer result.
* Equal operands.
* Used for the cmp functions.
*/
static void
_Int_EqualBinop_Ctx(int skip, char *token[], int (*func)(const mpd_t *, const mpd_t *, mpd_context_t *), mpd_context_t *ctx)
{
mpd_context_t maxctx;
int int_result;
char buf[11];
char *expected;
uint32_t expstatus;
int n;
mpd_readcontext(&maxctx);
maxctx.traps = MPD_Malloc_error;
n = scan_1op_result(op, &expected, token, &maxctx);
/* scan expected conditions */
expstatus = scan_conditions(token+n);
/* equal operands */
mpd_init_rand(tmp);
mpd_copy(tmp, op, ctx);
ctx->status = 0;
int_result = func(tmp, tmp, ctx);
snprintf(buf, 11, "%d", int_result);
if (!(skip && int_result == INT_MAX)) { /* NaN cases are skipped for the int_retval */
compare_expected(buf, expected, expstatus, token[0], ctx);
}
check_equalmem(tmp, op, token[0]);
/* Allocation failures */
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
mpd_init_rand(tmp);
mpd_copy(tmp, op, ctx);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
int_result = func(tmp, tmp, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(int_result== INT_MAX)
}
snprintf(buf, 11, "%d", int_result);
if (!(skip && int_result == INT_MAX)) { /* NaN cases are skipped for the int_retval */
compare_expected(buf, expected, expstatus, token[0], ctx);
}
check_equalmem(tmp, op, token[0]);
}
/*
* Test a binary function that returns an int.
* The function does not take a context argument.
*/
static void
_Int_Binop(char *token[], int (*func)(const mpd_t *, const mpd_t *), mpd_context_t *ctx)
{
mpd_context_t maxctx;
int int_result;
char buf[11];
char *expected;
uint32_t expstatus;
int n;
mpd_readcontext(&maxctx);
maxctx.traps = MPD_Malloc_error;
n = scan_2ops_result(op1, op2, &expected, token, &maxctx);
/* scan expected conditions */
expstatus = scan_conditions(token+n);
/* two distinct decimals */
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
ctx->status = 0;
int_result = func(tmp1, tmp2);
snprintf(buf, 11, "%d", int_result);
compare_expected(buf, expected, expstatus, token[0], ctx);
check_equalmem(tmp1, op1, token[0]);
check_equalmem(tmp2, op2, token[0]);
/* Allocation failures */
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
mpd_init_rand(tmp1);
mpd_init_rand(tmp2);
mpd_copy(tmp1, op1, ctx);
mpd_copy(tmp2, op2, ctx);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
int_result = func(tmp1, tmp2);
mpd_set_alloc(ctx);
if (int_result != INT_MAX) {
break;
}
}
snprintf(buf, 11, "%d", int_result);
compare_expected(buf, expected, expstatus, token[0], ctx);
check_equalmem(tmp1, op1, token[0]);
check_equalmem(tmp2, op2, token[0]);
}
/*
* Test a binary function that returns an int.
* Equal operands.
* The function does not take a context argument.
*/
static void
_Int_EqualBinop(char *token[], int (*func)(const mpd_t *, const mpd_t *), mpd_context_t *ctx)
{
mpd_context_t maxctx;
int int_result;
char buf[11];
char *expected;
uint32_t expstatus;
int n;
mpd_readcontext(&maxctx);
maxctx.traps = MPD_Malloc_error;
n = scan_1op_result(op, &expected, token, &maxctx);
/* scan expected conditions */
expstatus = scan_conditions(token+n);
/* equal operands */
mpd_init_rand(tmp);
mpd_copy(tmp, op, ctx);
ctx->status = 0;
int_result = func(tmp, tmp);
snprintf(buf, 11, "%d", int_result);
compare_expected(buf, expected, expstatus, token[0], ctx);
check_equalmem(tmp, op, token[0]);
/* Allocation failures */
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
mpd_init_rand(tmp);
mpd_copy(tmp, op, ctx);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
int_result = func(tmp, tmp);
mpd_set_alloc(ctx);
if (int_result != INT_MAX) {
break;
}
}
snprintf(buf, 11, "%d", int_result);
compare_expected(buf, expected, expstatus, token[0], ctx);
check_equalmem(tmp, op, token[0]);
}
static mpd_ssize_t
scan_ssize(char *token[])
{
errno = 0;
if (token[1] == NULL) {
errno = 1;
return MPD_SSIZE_MAX;
}
return mpd_strtossize(token[1], NULL, 10);
}
/*
* Test a function with an mpd_t and an mpd_ssize_t operand.
* Used for the shift functions.
*/
static void
_Res_Op_Lsize_Ctx(int skip, char *token[], void (*func)(mpd_t *, const mpd_t *, mpd_ssize_t, mpd_context_t *), mpd_context_t *ctx)
{
mpd_context_t maxctx;
char *calc;
char *expected;
uint32_t expstatus;
mpd_ssize_t ssize;
int n;
mpd_readcontext(&maxctx);
maxctx.traps = MPD_Malloc_error;
n = scan_2ops_result(op1, op2, &expected, token, &maxctx);
/* scan expected conditions */
expstatus = scan_conditions(token+n);
/* only integers are allowed for ssize */
if (skip && (mpd_isspecial(op2) || op2->exp != 0)) {
/* fprintf(stderr, "SKIP: %s\n", token[0]); */
return;
}
ssize = mpd_get_ssize(op2, &maxctx);
if (maxctx.status&MPD_Invalid_operation) {
return;
}
/* two distinct decimals */
mpd_init_rand(tmp1);
mpd_copy(tmp1, op1, ctx);
mpd_init_rand(result);
ctx->status = 0;
func(result, tmp1, ssize, ctx);
calc = mpd_to_sci(result, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp1, op1, token[0]);
/* Allocation failures */
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
mpd_init_rand(tmp1);
mpd_copy(tmp1, op1, ctx);
mpd_minalloc(result);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
func(result, tmp1, ssize, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(result))
}
calc = mpd_to_sci(result, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
check_equalmem(tmp1, op1, token[0]);
/* result == tmp1 */
mpd_init_rand(tmp1);
mpd_copy(tmp1, op1, ctx);
ctx->status = 0;
func(tmp1, tmp1, ssize, ctx);
calc = mpd_to_sci(tmp1, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
/* Allocation failures */
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
mpd_init_rand(tmp1);
mpd_copy(tmp1, op1, ctx);
ctx->status = 0;
mpd_set_alloc_fail(ctx);
func(tmp1, tmp1, ssize, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(tmp1))
}
calc = mpd_to_sci(tmp1, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
}
static void
_Baseconv(char *token[], mpd_context_t *ctx)
{
mpd_context_t maxctx;
uint32_t base;
uint16_t *data16;
uint32_t *data32;
size_t len16, len32;
size_t exp_len16, exp_len32;
char *expected;
uint32_t expstatus;
char *calc;
int n = 0;
int i, iter = 0;
mpd_readcontext(&maxctx);
maxctx.traps = MPD_Malloc_error;
n = scan_1op_result(op1, &expected, token, &maxctx);
ASSERT(mpd_isinteger(op1))
/* scan expected conditions */
expstatus = scan_conditions(token+n);
base = (1<<15);
len16 = mpd_sizeinbase(op1, base);
data16 = mpd_alloc((mpd_size_t)len16, sizeof *data16);
exp_len16 = mpd_export_u16(data16, len16, base, op1, ctx);
if (exp_len16 == SIZE_MAX) {
mpd_err_fatal("export_to_base failed");
}
mpd_import_u16(result, data16, exp_len16, MPD_POS, base, ctx);
calc = mpd_to_sci(result, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
__mingw_dfp_get_globals()->mpd_free(data16);
/* Allocation failures */
base = (1<<15);
len16 = mpd_sizeinbase(op1, base);
data16 = mpd_alloc((mpd_size_t)len16, sizeof *data16);
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
ctx->status = 0;
mpd_set_alloc_fail(ctx);
exp_len16 = mpd_export_u16(data16, len16, base, op1, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(exp_len16 == SIZE_MAX)
}
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
ctx->status = 0;
mpd_set_alloc_fail(ctx);
mpd_import_u16(result, data16, exp_len16, MPD_POS, base, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(result))
}
calc = mpd_to_sci(result, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
__mingw_dfp_get_globals()->mpd_free(data16);
base = (1U<<16);
len16 = mpd_sizeinbase(op1, base);
data16 = mpd_alloc((mpd_size_t)len16, sizeof *data16);
len16 = mpd_export_u16(data16, len16, base, op1, ctx);
if (len16 == SIZE_MAX) {
mpd_err_fatal("export_to_base failed");
}
mpd_import_u16(result, data16, len16, MPD_POS, base, ctx);
calc = mpd_to_sci(result, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
__mingw_dfp_get_globals()->mpd_free(data16);
base = 9999;
len16 = mpd_sizeinbase(op1, base);
data16 = mpd_alloc((mpd_size_t)len16, sizeof *data16);
exp_len16 = mpd_export_u16(data16, len16, base, op1, ctx);
if (exp_len16 == SIZE_MAX) {
mpd_err_fatal("export_to_base failed");
}
mpd_import_u16(result, data16, exp_len16, MPD_POS, base, ctx);
calc = mpd_to_sci(result, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
__mingw_dfp_get_globals()->mpd_free(data16);
#ifdef RT_EXT_BASECONV
iter = 16;
#endif
for (i = 2; i <= iter; i++) {
base = i;
len16 = mpd_sizeinbase(op1, base);
data16 = mpd_alloc((mpd_size_t)len16, sizeof *data16);
len16 = mpd_export_u16(data16, len16, base, op1, ctx);
if (len16 == SIZE_MAX) {
mpd_err_fatal("export_to_base failed");
}
mpd_import_u16(result, data16, len16, MPD_POS, base, ctx);
calc = mpd_to_sci(result, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
__mingw_dfp_get_globals()->mpd_free(data16);
}
#ifdef RT_EXT_BASECONV
iter = 100;
#endif
for (i = 0; i < iter; i++) {
base = random() % UINT16_MAX;
if (base < 2) base = 2;
len16 = mpd_sizeinbase(op1, base);
data16 = mpd_alloc((mpd_size_t)len16, sizeof *data16);
len16 = mpd_export_u16(data16, len16, base, op1, ctx);
if (len16 == SIZE_MAX) {
mpd_err_fatal("export_to_base failed");
}
mpd_import_u16(result, data16, len16, MPD_POS, base, ctx);
calc = mpd_to_sci(result, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
__mingw_dfp_get_globals()->mpd_free(data16);
}
base = 1000000000;
len32 = mpd_sizeinbase(op1, base);
data32 = mpd_alloc((mpd_size_t)len32, sizeof *data32);
exp_len32 = mpd_export_u32(data32, len32, base, op1, ctx);
if (exp_len32 == SIZE_MAX) {
mpd_err_fatal("export_to_base failed");
}
mpd_import_u32(result, data32, len32, MPD_POS, base, ctx);
calc = mpd_to_sci(result, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
__mingw_dfp_get_globals()->mpd_free(data32);
/* Allocation failures */
base = 1000000000;
len32 = mpd_sizeinbase(op1, base);
data32 = mpd_alloc((mpd_size_t)len32, sizeof *data32);
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
ctx->status = 0;
mpd_set_alloc_fail(ctx);
exp_len32 = mpd_export_u32(data32, len32, base, op1, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(exp_len32 == SIZE_MAX)
}
for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
ctx->status = 0;
mpd_set_alloc_fail(ctx);
mpd_import_u32(result, data32, exp_len32, MPD_POS, base, ctx);
mpd_set_alloc(ctx);
if (!(ctx->status&MPD_Malloc_error)) {
break;
}
ASSERT(mpd_isnan(result))
}
calc = mpd_to_sci(result, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
__mingw_dfp_get_globals()->mpd_free(data32);
base = (1<<30);
len32 = mpd_sizeinbase(op1, base);
data32 = mpd_alloc((mpd_size_t)len32, sizeof *data32);
len32 = mpd_export_u32(data32, len32, base, op1, ctx);
if (len32 == SIZE_MAX) {
mpd_err_fatal("export_to_base failed");
}
mpd_import_u32(result, data32, len32, MPD_POS, base, ctx);
calc = mpd_to_sci(result, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
__mingw_dfp_get_globals()->mpd_free(data32);
for (i = 2; i <= 16; i++) {
base = i;
len32 = mpd_sizeinbase(op1, base);
data32 = mpd_alloc((mpd_size_t)len32, sizeof *data32);
len32 = mpd_export_u32(data32, len32, base, op1, ctx);
if (len32 == SIZE_MAX) {
mpd_err_fatal("export_to_base failed");
}
mpd_import_u32(result, data32, len32, MPD_POS, base, ctx);
calc = mpd_to_sci(result, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
__mingw_dfp_get_globals()->mpd_free(data32);
}
for (i = 0; i < 100; i++) {
base = random() % UINT32_MAX;
if (base < 2) base = 2;
len32 = mpd_sizeinbase(op1, base);
data32 = mpd_alloc((mpd_size_t)len32, sizeof *data32);
len32 = mpd_export_u32(data32, len32, base, op1, ctx);
if (len32 == SIZE_MAX) {
mpd_err_fatal("export_to_base failed");
}
mpd_import_u32(result, data32, len32, MPD_POS, base, ctx);
calc = mpd_to_sci(result, 1);
compare_expected(calc, expected, expstatus, token[0], ctx);
__mingw_dfp_get_globals()->mpd_free(calc);
__mingw_dfp_get_globals()->mpd_free(data32);
}
}
/*
* Test a function returning an mpd_uint_t, accepting:
* op, context
*
* This function is used for:
* - mpd_get_uint
* - mpd_abs_uint
* - mpd_get_u64
* - mpd_get_u32
*/
static void
_uint_MpdCtx(char **token, mpd_uint_t (*func)(const mpd_t *, mpd_context_t *), mpd_context_t *ctx)
{
mpd_context_t maxctx;
mpd_uint_t calc_uint;
char calc[23];
char *expected;
uint32_t expstatus;
int n;
mpd_readcontext(&maxctx);
maxctx.traps = MPD_Malloc_error;
/* conversion should be done as if there were no limits */
n = scan_1op_result(op, &expected, token, &maxctx);
expstatus = scan_conditions(token+n);
mpd_init_rand(tmp);
mpd_copy(tmp, op, ctx);
ctx->status = 0;
calc_uint = func(tmp, ctx);
snprintf(calc, 23, "%" PRI_mpd_uint_t, calc_uint);
/* compare the calculated result to the expected result */
compare_expected(calc, expected, expstatus, token[0], ctx);
check_equalmem(tmp, op, token[0]);
}
/*
* Test a function returning an mpd_ssize_t, accepting:
* op, fmt, context
*
* This function is used for:
* - mpd_get_ssize
* - mpd_get_i64
* - mpd_get_i32
*/
static void
_ssize_MpdCtx(char **token, mpd_ssize_t (*func)(const mpd_t *, mpd_context_t *), mpd_context_t *ctx)
{
mpd_context_t maxctx;
mpd_ssize_t calc_ssize;
char calc[23];
char *expected;
uint32_t expstatus;
int n;
mpd_readcontext(&maxctx);
maxctx.traps = MPD_Malloc_error;
/* conversion should be done as if there were no limits */
n = scan_1op_result(op, &expected, token, &maxctx);
expstatus = scan_conditions(token+n);
mpd_init_rand(tmp);
mpd_copy(tmp, op, ctx);
ctx->status = 0;
calc_ssize = func(tmp, ctx);
snprintf(calc, 23, "%" PRI_mpd_ssize_t, calc_ssize);
/* compare the calculated result to the expected result */
compare_expected(calc, expected, expstatus, token[0], ctx);
check_equalmem(tmp, op, token[0]);
}
/* process a file */
static void
doit(char *filename)
{
FILE *file;
mpd_context_t ctx;
char *line;
char *tmpline;
char *token[MAXTOKEN+1];
uint32_t testno;
mpd_ssize_t l;
mpd_testcontext(&ctx);
ctx.traps = MPD_Malloc_error;
if (strcmp(filename, "-") == 0) {
file = stdin;
}
else {
if ((file = fopen(filename, "r")) == NULL) {
mpd_err_fatal("could not open %s", filename);
}
}
if ((line = mpd_alloc(MAXLINE+1, sizeof *line)) == NULL) {
mpd_err_fatal("out of memory");
}
if ((tmpline = mpd_alloc(MAXLINE+1, sizeof *line)) == NULL) {
mpd_err_fatal("out of memory");
}
while (fgets(line, MAXLINE+1, file) != NULL) {
/* split a line into tokens */
strcpy(tmpline, line);
if (split(token, tmpline) == 0) {
goto cleanup;
}
/* comments */
if (startswith(token[0], "--")) {
goto cleanup;
}
/* end comments */
/* skip bool* tests in extra.decTest */
if (startswith(token[0], "bool")) {
goto cleanup;
}
/* end skips */
/* directives */
if (startswith(token[0], "Precision")) {
l = scan_ssize(token);
if (errno != 0) {
mpd_err_fatal("%s: %s", filename, line);
}
/*if (!mpd_qsetprec(&ctx, l)) {
mpd_err_fatal("%s: %s", filename, line);
}*/
/* use a wider range than officially allowed */
ctx.prec = l;
goto cleanup;
}
if (startswith(token[0], "Rounding")) {
if (eqtoken(token[1], "Ceiling"))
ctx.round = MPD_ROUND_CEILING;
else if (eqtoken(token[1], "Up"))
ctx.round = MPD_ROUND_UP;
else if (eqtoken(token[1], "Half_up"))
ctx.round = MPD_ROUND_HALF_UP;
else if (eqtoken(token[1], "Half_even"))
ctx.round = MPD_ROUND_HALF_EVEN;
else if (eqtoken(token[1], "Half_down"))
ctx.round = MPD_ROUND_HALF_DOWN;
else if (eqtoken(token[1], "Down"))
ctx.round = MPD_ROUND_DOWN;
else if (eqtoken(token[1], "Floor"))
ctx.round = MPD_ROUND_FLOOR;
else if (eqtoken(token[1], "05up"))
ctx.round = MPD_ROUND_05UP;
else
mpd_err_fatal("%s: %s", filename, line);
goto cleanup;
}
if (startswith(token[0], "MaxExponent")) {
l = scan_ssize(token);
if (errno != 0) {
mpd_err_fatal("%s: %s", filename, line);
}
/*if (!mpd_qsetemax(&ctx, l)) {
mpd_err_fatal("%s: %s", filename, line);
}*/
/* use a wider range than officially allowed */
ctx.emax = l;
goto cleanup;
}
if (startswith(token[0], "MinExponent")) {
l = scan_ssize(token);
if (errno != 0) {
mpd_err_fatal("%s: %s", filename, line);
}
/*if (!mpd_qsetemin(&ctx, l)) {
mpd_err_fatal("%s: %s", filename, line);
}*/
/* use a wider range than officially allowed */
ctx.emin = l;
goto cleanup;
}
if (startswith(token[0], "Dectest")) {
if (token[1] == NULL) {
mpd_err_fatal("%s: %s", filename, line);
}
doit(token[1]);
goto cleanup;
}
/* end directives */
/* optional directives */
if (startswith(token[0], "Version")) {
goto cleanup;
}
if (startswith(token[0], "Extended")) {
goto cleanup;
}
if (startswith(token[0], "Clamp")) {
l = scan_ssize(token);
if (errno != 0) {
mpd_err_fatal("%s: %s", filename, line);
}
if (!mpd_qsetclamp(&ctx, (int)l)) {
mpd_err_fatal("%s: %s", filename, line);
}
goto cleanup;
}
if (startswith(token[0], "Locale")) {
if (token[1] == NULL) {
mpd_err_fatal("%s: %s", filename, line);
}
fprintf(stderr, "locale: %s\n", token[1]);
if (setlocale(LC_NUMERIC, token[1]) == NULL) {
mpd_err_fatal("%s: %s", filename, line);
}
goto cleanup;
}
/* end optional directives */
/*
* Actual tests start here:
* - token[0] is the id
* - token[1] is the operation type
* - testno can be used for setting a watchpoint in the debugger
*/
testno = get_testno(token[0]);
(void)testno;
/* The id is in the skip list */
if (check_skip(token[0])) {
goto cleanup;
}
#ifdef CONFIG_32
/* Skip coverage tests with excessive run time. */
if (startswith(token[0], "cov64")) {
goto cleanup;
}
#endif
/* Translate operation type for powmod */
if (startswith(token[0], "pwmx")) {
free(token[1]);
token[1] = malloc(sizeof("powmod"));
strcpy(token[1], "powmod");
}
/* end skips */
/* Unary functions with char * result */
if (eqtoken(token[1], "tosci") || eqtoken(token[1], "apply")) {
_cp_MpdCtx(token, mpd_to_sci, &ctx);
}
else if (eqtoken(token[1], "toeng")) {
_cp_MpdCtx(token, mpd_to_eng, &ctx);
}
else if (eqtoken(token[1], "format")) {
_cp_MpdFmtCtx(token, mpd_format, &ctx);
}
/* Unary function with const char * result */
else if (eqtoken(token[1], "class")) {
_ccp_MpdCtx(token, mpd_class, &ctx);
}
/* Unary functions with mpd_t * result */
else if (eqtoken(token[1], "abs")) {
_Res_Op_Ctx(token, mpd_abs, &ctx);
}
else if (eqtoken(token[1], "copy")) {
_Res_Op_Ctx(token, mpd_copy, &ctx);
}
else if (eqtoken(token[1], "copyabs")) {
_Res_Op_Ctx(token, mpd_copy_abs, &ctx);
}
else if (eqtoken(token[1], "copynegate")) {
_Res_Op_Ctx(token, mpd_copy_negate, &ctx);
}
else if (eqtoken(token[1], "exp")) {
ctx.allcr = 0;
_Res_Op_Ctx(token, mpd_exp, &ctx);
ctx.allcr = 1;
_Res_Op_Ctx(token, mpd_exp, &ctx);
}
else if (eqtoken(token[1], "invert")) {
_Res_Op_Ctx(token, mpd_invert, &ctx);
}
else if (eqtoken(token[1], "invroot")) {
_Res_Op_Ctx(token, mpd_invroot, &ctx);
}
else if (eqtoken(token[1], "ln")) {
ctx.allcr = 0;
_Res_Op_Ctx(token, mpd_ln, &ctx);
ctx.allcr = 1;
_Res_Op_Ctx(token, mpd_ln, &ctx);
}
else if (eqtoken(token[1], "log10")) {
ctx.allcr = 0;
_Res_Op_Ctx(token, mpd_log10, &ctx);
ctx.allcr = 1;
_Res_Op_Ctx(token, mpd_log10, &ctx);
}
else if (eqtoken(token[1], "logb")) {
_Res_Op_Ctx(token, mpd_logb, &ctx);
}
else if (eqtoken(token[1], "minus")) {
_Res_Op_Ctx(token, mpd_minus, &ctx);
}
else if (eqtoken(token[1], "nextminus")) {
_Res_Op_Ctx(token, mpd_next_minus, &ctx);
}
else if (eqtoken(token[1], "nextplus")) {
_Res_Op_Ctx(token, mpd_next_plus, &ctx);
}
else if (eqtoken(token[1], "plus")) {
_Res_Op_Ctx(token, mpd_plus, &ctx);
}
else if (eqtoken(token[1], "reduce")) {
_Res_Op_Ctx(token, mpd_reduce, &ctx);
}
else if (eqtoken(token[1], "squareroot")) {
_Res_Op_Ctx(token, mpd_sqrt, &ctx);
}
else if (eqtoken(token[1], "tointegral")) {
_Res_Op_Ctx(token, mpd_round_to_int, &ctx);
}
else if (eqtoken(token[1], "tointegralx")) {
_Res_Op_Ctx(token, mpd_round_to_intx, &ctx);
}
else if (eqtoken(token[1], "floor")) {
_Res_Op_Ctx(token, mpd_floor, &ctx);
}
else if (eqtoken(token[1], "ceil")) {
_Res_Op_Ctx(token, mpd_ceil, &ctx);
}
else if (eqtoken(token[1], "trunc")) {
_Res_Op_Ctx(token, mpd_trunc, &ctx);
}
/* Binary function returning an int */
else if (eqtoken(token[1], "samequantum")) {
_Int_Binop(token, mpd_same_quantum, &ctx);
}
/* Binary function returning an int, equal operands */
else if (eqtoken(token[1], "samequantum_eq")) {
_Int_EqualBinop(token, mpd_same_quantum, &ctx);
}
/* Binary functions with mpd_t * result */
else if (eqtoken(token[1], "add")) {
_Res_Binop_Ctx(token, mpd_add, &ctx);
}
else if (eqtoken(token[1], "and")) {
_Res_Binop_Ctx(token, mpd_and, &ctx);
}
else if (eqtoken(token[1], "copysign")) {
_Res_Binop_Ctx(token, mpd_copy_sign, &ctx);
}
else if (eqtoken(token[1], "divide")) {
_Res_Binop_Ctx(token, mpd_div, &ctx);
_Res_Binop_Ctx(token, mpd_test_newtondiv, &ctx);
}
else if (eqtoken(token[1], "divideint")) {
_Res_Binop_Ctx(token, mpd_divint, &ctx);
_Res_Binop_Ctx(token, mpd_test_newtondivint, &ctx);
}
else if (eqtoken(token[1], "max")) {
_Res_Binop_Ctx(token, mpd_max, &ctx);
}
else if (eqtoken(token[1], "maxmag")) {
_Res_Binop_Ctx(token, mpd_max_mag, &ctx);
}
else if (eqtoken(token[1], "min")) {
_Res_Binop_Ctx(token, mpd_min, &ctx);
}
else if (eqtoken(token[1], "minmag")) {
_Res_Binop_Ctx(token, mpd_min_mag, &ctx);
}
else if (eqtoken(token[1], "multiply")) {
_Res_Binop_Ctx(token, mpd_mul, &ctx);
}
else if (eqtoken(token[1], "nexttoward")) {
_Res_Binop_Ctx(token, mpd_next_toward, &ctx);
}
else if (eqtoken(token[1], "or")) {
_Res_Binop_Ctx(token, mpd_or, &ctx);
}
else if (eqtoken(token[1], "power")) {
ctx.allcr = 0;
_Res_Binop_Ctx(token, mpd_pow, &ctx);
ctx.allcr = 1;
_Res_Binop_Ctx(token, mpd_pow, &ctx);
}
else if (eqtoken(token[1], "quantize")) {
_Res_Binop_Ctx(token, mpd_quantize, &ctx);
}
else if (eqtoken(token[1], "resc")) {
_Res_Op_Lsize_Ctx(SKIP_NONINT, token, mpd_rescale, &ctx);
}
else if (eqtoken(token[1], "remainder")) {
_Res_Binop_Ctx(token, mpd_rem, &ctx);
_Res_Binop_Ctx(token, mpd_test_newtonrem, &ctx);
}
else if (eqtoken(token[1], "remaindernear")) {
_Res_Binop_Ctx(token, mpd_rem_near, &ctx);
}
else if (eqtoken(token[1], "rotate")) {
_Res_Binop_Ctx(token, mpd_rotate, &ctx);
}
else if (eqtoken(token[1], "scaleb")) {
_Res_Binop_Ctx(token, mpd_scaleb, &ctx);
}
else if (eqtoken(token[1], "shift")) {
_Res_Binop_Ctx(token, mpd_shift, &ctx);
_Res_Op_Lsize_Ctx(SKIP_NONINT, token, mpd_shiftn, &ctx);
}
else if (eqtoken(token[1], "subtract")) {
_Res_Binop_Ctx(token, mpd_sub, &ctx);
}
else if (eqtoken(token[1], "xor")) {
_Res_Binop_Ctx(token, mpd_xor, &ctx);
}
/* Binary functions with mpd_t result, equal operands */
else if (eqtoken(token[1], "add_eq")) {
_Res_EqualBinop_Ctx(token, mpd_add, &ctx);
}
else if (eqtoken(token[1], "and_eq")) {
_Res_EqualBinop_Ctx(token, mpd_and, &ctx);
}
else if (eqtoken(token[1], "copysign_eq")) {
_Res_EqualBinop_Ctx(token, mpd_copy_sign, &ctx);
}
else if (eqtoken(token[1], "divide_eq")) {
_Res_EqualBinop_Ctx(token, mpd_div, &ctx);
_Res_EqualBinop_Ctx(token, mpd_test_newtondiv, &ctx);
}
else if (eqtoken(token[1], "divideint_eq")) {
_Res_EqualBinop_Ctx(token, mpd_divint, &ctx);
_Res_EqualBinop_Ctx(token, mpd_test_newtondivint, &ctx);
}
else if (eqtoken(token[1], "max_eq")) {
_Res_EqualBinop_Ctx(token, mpd_max, &ctx);
}
else if (eqtoken(token[1], "maxmag_eq")) {
_Res_EqualBinop_Ctx(token, mpd_max_mag, &ctx);
}
else if (eqtoken(token[1], "min_eq")) {
_Res_EqualBinop_Ctx(token, mpd_min, &ctx);
}
else if (eqtoken(token[1], "minmag_eq")) {
_Res_EqualBinop_Ctx(token, mpd_min_mag, &ctx);
}
else if (eqtoken(token[1], "multiply_eq")) {
_Res_EqualBinop_Ctx(token, mpd_mul, &ctx);
}
else if (eqtoken(token[1], "nexttoward_eq")) {
_Res_EqualBinop_Ctx(token, mpd_next_toward, &ctx);
}
else if (eqtoken(token[1], "or_eq")) {
_Res_EqualBinop_Ctx(token, mpd_or, &ctx);
}
else if (eqtoken(token[1], "power_eq")) {
ctx.allcr = 0;
_Res_EqualBinop_Ctx(token, mpd_pow, &ctx);
ctx.allcr = 1;
_Res_EqualBinop_Ctx(token, mpd_pow, &ctx);
}
else if (eqtoken(token[1], "quantize_eq")) {
_Res_EqualBinop_Ctx(token, mpd_quantize, &ctx);
}
else if (eqtoken(token[1], "remainder_eq")) {
_Res_EqualBinop_Ctx(token, mpd_rem, &ctx);
_Res_EqualBinop_Ctx(token, mpd_test_newtonrem, &ctx);
}
else if (eqtoken(token[1], "remaindernear_eq")) {
_Res_EqualBinop_Ctx(token, mpd_rem_near, &ctx);
}
else if (eqtoken(token[1], "rotate_eq")) {
_Res_EqualBinop_Ctx(token, mpd_rotate, &ctx);
}
else if (eqtoken(token[1], "scaleb_eq")) {
_Res_EqualBinop_Ctx(token, mpd_scaleb, &ctx);
}
else if (eqtoken(token[1], "shift_eq")) {
_Res_EqualBinop_Ctx(token, mpd_shift, &ctx);
}
else if (eqtoken(token[1], "subtract_eq")) {
_Res_EqualBinop_Ctx(token, mpd_sub, &ctx);
}
else if (eqtoken(token[1], "xor_eq")) {
_Res_EqualBinop_Ctx(token, mpd_xor, &ctx);
}
/* Binary function with binary result */
else if (eqtoken(token[1], "divmod")) {
_Binres_Binop_Ctx(token, mpd_divmod, &ctx);
_Binres_Binop_Ctx(token, mpd_test_newtondivmod, &ctx);
}
/* Binary function with binary result, equal operands */
else if (eqtoken(token[1], "divmod_eq")) {
_Binres_EqualBinop_Ctx(token, mpd_divmod, &ctx);
_Binres_EqualBinop_Ctx(token, mpd_test_newtondivmod, &ctx);
}
/* Ternary functions with mpd_t result */
else if (eqtoken(token[1], "fma")) {
_Res_Ternop_Ctx(token, mpd_fma, &ctx);
}
else if (eqtoken(token[1], "powmod")) {
_Res_Ternop_Ctx(token, mpd_powmod, &ctx);
}
/* Ternary functions with mpd_t result, eq_eq_op */
else if (eqtoken(token[1], "fma_eq_eq_op")) {
_Res_EqEqOp_Ctx(token, mpd_fma, &ctx);
}
else if (eqtoken(token[1], "powmod_eq_eq_op")) {
_Res_EqEqOp_Ctx(token, mpd_powmod, &ctx);
}
/* Ternary functions with mpd_t result, eq_op_eq */
else if (eqtoken(token[1], "fma_eq_op_eq")) {
_Res_EqOpEq_Ctx(token, mpd_fma, &ctx);
}
else if (eqtoken(token[1], "powmod_eq_op_eq")) {
_Res_EqOpEq_Ctx(token, mpd_powmod, &ctx);
}
/* Ternary functions with mpd_t result, op_eq_eq */
else if (eqtoken(token[1], "fma_op_eq_eq")) {
_Res_OpEqEq_Ctx(token, mpd_fma, &ctx);
}
else if (eqtoken(token[1], "powmod_op_eq_eq")) {
_Res_OpEqEq_Ctx(token, mpd_powmod, &ctx);
}
/* Ternary functions with mpd_t result, eq_eq_eq */
else if (eqtoken(token[1], "fma_eq_eq_eq")) {
_Res_EqEqEq_Ctx(token, mpd_fma, &ctx);
}
else if (eqtoken(token[1], "powmod_eq_eq_eq")) {
_Res_EqEqEq_Ctx(token, mpd_powmod, &ctx);
}
/* Special cases for the comparison functions */
else if (eqtoken(token[1], "compare")) {
_Int_Res_Binop_Ctx(token, mpd_compare, &ctx);
_Int_Binop_Ctx(SKIP_NAN, token, mpd_cmp, &ctx);
}
else if (eqtoken(token[1], "comparesig")) {
_Int_Res_Binop_Ctx(token, mpd_compare_signal, &ctx);
}
else if (eqtoken(token[1], "comparetotal")) {
_Int_Res_Binop(token, mpd_compare_total, &ctx);
_Int_Binop(token, mpd_cmp_total, &ctx);
}
else if (eqtoken(token[1], "comparetotmag")) {
_Int_Res_Binop(token, mpd_compare_total_mag, &ctx);
_Int_Binop(token, mpd_cmp_total_mag, &ctx);
}
/* Special cases for the comparison functions, equal operands */
else if (eqtoken(token[1], "compare_eq")) {
_Int_Res_EqualBinop_Ctx(token, mpd_compare, &ctx);
_Int_EqualBinop_Ctx(SKIP_NAN, token, mpd_cmp, &ctx);
}
else if (eqtoken(token[1], "comparesig_eq")) {
_Int_Res_EqualBinop_Ctx(token, mpd_compare_signal, &ctx);
}
else if (eqtoken(token[1], "comparetotal_eq")) {
_Int_Res_EqualBinop(token, mpd_compare_total, &ctx);
_Int_EqualBinop(token, mpd_cmp_total, &ctx);
}
else if (eqtoken(token[1], "comparetotmag_eq")) {
_Int_Res_EqualBinop(token, mpd_compare_total_mag, &ctx);
_Int_EqualBinop(token, mpd_cmp_total_mag, &ctx);
}
/* Special cases for the shift functions */
else if (eqtoken(token[1], "shiftleft")) {
_Res_Op_Lsize_Ctx(SKIP_NONINT, token, mpd_shiftl, &ctx);
}
else if (eqtoken(token[1], "shiftright")) {
_Res_Op_Lsize_Ctx(SKIP_NONINT, token,
(void (*)(mpd_t *, const mpd_t *, mpd_ssize_t, mpd_context_t *))mpd_shiftr, &ctx);
}
/* Special case for the base conversion functions */
else if (eqtoken(token[1], "baseconv")) {
_Baseconv(token, &ctx);
}
/* Special cases for the get_int functions */
#ifdef CONFIG_64
else if (eqtoken(token[1], "get_uint64")) {
_uint_MpdCtx(token, mpd_get_uint, &ctx);
}
else if (eqtoken(token[1], "get_uint64_abs")) {
_uint_MpdCtx(token, mpd_abs_uint, &ctx);
}
else if (eqtoken(token[1], "get_u64")) {
_uint_MpdCtx(token, mpd_get_u64, &ctx);
}
else if (eqtoken(token[1], "get_ssize64")) {
_ssize_MpdCtx(token, mpd_get_ssize, &ctx);
}
else if (eqtoken(token[1], "get_i64")) {
_ssize_MpdCtx(token, mpd_get_i64, &ctx);
}
#else
else if (eqtoken(token[1], "get_uint32")) {
_uint_MpdCtx(token, mpd_get_uint, &ctx);
}
else if (eqtoken(token[1], "get_uint32_abs")) {
_uint_MpdCtx(token, mpd_abs_uint, &ctx);
}
else if (eqtoken(token[1], "get_u32")) {
_uint_MpdCtx(token, mpd_get_u32, &ctx);
}
else if (eqtoken(token[1], "get_ssize32")) {
_ssize_MpdCtx(token, mpd_get_ssize, &ctx);
}
else if (eqtoken(token[1], "get_i32")) {
_ssize_MpdCtx(token, mpd_get_i32, &ctx);
}
#endif
else if (startswith(token[1], "get_")) {
;
}
else if (eqtoken(token[1], "rescale")) {
;
}
/* unknown operation */
else {
mpd_err_fatal("%s: unknown operation: %s", filename, line);
}
/* end tests */
cleanup:
freetoken(token);
}
__mingw_dfp_get_globals()->mpd_free(line);
__mingw_dfp_get_globals()->mpd_free(tmpline);
if (file != stdin) {
fclose(file);
}
}
int main(int argc, char **argv)
{
mpd_ssize_t ma, limit;
int n = 1;
if (argc == 2) {
limit = 2;
}
else if (argc == 3) {
if (strcmp(argv[n++], "--all") != 0) {
fputs("runtest: usage: runtest [--all] testfile\n", stderr);
exit(EXIT_FAILURE);
}
limit = MPD_MINALLOC_MAX;
}
else {
fputs("runtest: usage: runtest [--all] testfile\n", stderr);
exit(EXIT_FAILURE);
}
srand((unsigned int)time(NULL));
for (ma = MPD_MINALLOC_MIN; ma <= limit; ma++) {
/* DON'T do this in a real program. You have to be sure
* that no previously allocated decimals will ever be used. */
__mingw_dfp_get_globals()->MPD_MINALLOC = ma;
if (n == 2) {
fprintf(stderr, "minalloc: %" PRI_mpd_ssize_t "\n", __mingw_dfp_get_globals()->MPD_MINALLOC);
}
op = mpd_qnew();
op1 = mpd_qnew();
op2 = mpd_qnew();
op3 = mpd_qnew();
tmp = mpd_qnew();
tmp1 = mpd_qnew();
tmp2 = mpd_qnew();
tmp3 = mpd_qnew();
result = mpd_qnew();
result1 = mpd_qnew();
result2 = mpd_qnew();
doit(argv[n]);
mpd_del(op);
mpd_del(op1);
mpd_del(op2);
mpd_del(op3);
mpd_del(tmp);
mpd_del(tmp1);
mpd_del(tmp2);
mpd_del(tmp3);
mpd_del(result);
mpd_del(result1);
mpd_del(result2);
if (have_printed) {
fputc('\n', stderr);
}
}
/* Valgrind */
mpd_del(&__mingw_dfp_get_globals()->mpd_ln10);
return have_fail;
}