mirror of
https://github.com/c3d/DB48X-on-DM42.git
synced 2024-09-28 03:20:53 +02:00
Decimal128 objects and related
This uses the Intel library for 3 classes of precision Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
This commit is contained in:
parent
5ebfe20527
commit
644e7954b7
18 changed files with 867 additions and 25 deletions
27
Makefile
27
Makefile
|
@ -44,16 +44,28 @@ C_INCLUDES += -Isrc -Iinc
|
|||
# C sources
|
||||
C_SOURCES +=
|
||||
|
||||
# Floating point sizes
|
||||
DECIMAL_SIZES=32 64
|
||||
DECIMAL_SOURCES=$(DECIMAL_SIZES:%=src/decimal-%.cc)
|
||||
|
||||
# C++ sources
|
||||
CXX_SOURCES += \
|
||||
src/main.cc \
|
||||
src/menu.cc \
|
||||
src/util.cc \
|
||||
src/runtime.cc \
|
||||
src/object.cc \
|
||||
src/integer.cc \
|
||||
CXX_SOURCES += \
|
||||
src/main.cc \
|
||||
src/menu.cc \
|
||||
src/util.cc \
|
||||
src/settings.cc \
|
||||
src/runtime.cc \
|
||||
src/object.cc \
|
||||
src/integer.cc \
|
||||
src/decimal128.cc \
|
||||
$(DECIMAL_SOURCES) \
|
||||
src/rplstring.cc
|
||||
|
||||
# Generate the sized variants of decimal128
|
||||
src/decimal-%.cc: src/decimal128.cc src/decimal-%.h
|
||||
sed -e s/decimal128.h/decimal-$*.h/g -e s/128/$*/g $< > $@
|
||||
src/decimal-%.h: src/decimal128.h
|
||||
sed -e s/128/$*/g -e s/leb$*/leb128/g $< > $@
|
||||
|
||||
# ASM sources
|
||||
#ASM_SOURCES += src/xxx.s
|
||||
|
@ -181,6 +193,7 @@ $(TARGET).pgm: $(BUILD)/$(TARGET).elf Makefile
|
|||
$(SIZE) $<
|
||||
wc -c $@
|
||||
|
||||
$(OBJECTS): $(DECIMAL_SOURCES)
|
||||
|
||||
$(BUILD)/%.hex: $(BUILD)/%.elf | $(BUILD)
|
||||
$(HEX) $< $@
|
||||
|
|
|
@ -2623,13 +2623,13 @@ BID_EXTERN_C _IDEC_round _IDEC_glbround; // initialized to BID_ROUNDING_TO_NEARE
|
|||
px _RND_MODE_PARAM _EXC_FLAGS_PARAM
|
||||
_EXC_MASKS_PARAM _EXC_INFO_PARAM);
|
||||
|
||||
BID_EXTERN_C void bid32_from_string (BID_UINT32 * pres, char *ps
|
||||
BID_EXTERN_C void bid32_from_string (BID_UINT32 * pres, const char *ps
|
||||
_RND_MODE_PARAM _EXC_FLAGS_PARAM
|
||||
_EXC_MASKS_PARAM _EXC_INFO_PARAM);
|
||||
BID_EXTERN_C void bid32_to_string (char *ps, BID_UINT32 * px
|
||||
_EXC_FLAGS_PARAM
|
||||
_EXC_MASKS_PARAM _EXC_INFO_PARAM);
|
||||
BID_EXTERN_C void bid64_from_string (BID_UINT64 * pres, char *ps
|
||||
BID_EXTERN_C void bid64_from_string (BID_UINT64 * pres, const char *ps
|
||||
_RND_MODE_PARAM _EXC_FLAGS_PARAM
|
||||
_EXC_MASKS_PARAM _EXC_INFO_PARAM);
|
||||
BID_EXTERN_C void bid64_to_string (char *ps, BID_UINT64 * px
|
||||
|
|
|
@ -34,8 +34,12 @@ SOURCES += \
|
|||
../src/menu.cc \
|
||||
../src/main.cc \
|
||||
../src/util.cc \
|
||||
../src/settings.cc \
|
||||
../src/object.cc \
|
||||
../src/integer.cc \
|
||||
../src/decimal128.cc \
|
||||
../src/decimal-64.cc \
|
||||
../src/decimal-32.cc \
|
||||
../src/runtime.cc \
|
||||
../src/rplstring.cc
|
||||
|
||||
|
|
174
src/decimal-32.cc
Normal file
174
src/decimal-32.cc
Normal file
|
@ -0,0 +1,174 @@
|
|||
// ****************************************************************************
|
||||
// decimal32.cc DB48X project
|
||||
// ****************************************************************************
|
||||
//
|
||||
// File Description:
|
||||
//
|
||||
// Implementation of decimal floating point using Intel's library
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// ****************************************************************************
|
||||
// (C) 2022 Christophe de Dinechin <christophe@dinechin.org>
|
||||
// This software is licensed under the terms outlined in LICENSE.txt
|
||||
// ****************************************************************************
|
||||
// This file is part of DB48X.
|
||||
//
|
||||
// DB48X is free software: you can redistribute it and/or modify
|
||||
// it under the terms outlined in the LICENSE.txt file
|
||||
//
|
||||
// DB48X is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// ****************************************************************************
|
||||
|
||||
#include "decimal-32.h"
|
||||
|
||||
#include "runtime.h"
|
||||
#include "settings.h"
|
||||
|
||||
#include <bid_conf.h>
|
||||
#include <bid_functions.h>
|
||||
#include <cstdio>
|
||||
|
||||
|
||||
OBJECT_HANDLER_BODY(decimal32)
|
||||
// ----------------------------------------------------------------------------
|
||||
// Handle commands for decimal32s
|
||||
// ----------------------------------------------------------------------------
|
||||
{
|
||||
switch(cmd)
|
||||
{
|
||||
case EVAL:
|
||||
// Decimal32 values evaluate as self
|
||||
rt.push(obj);
|
||||
return 0;
|
||||
case SIZE:
|
||||
return ptrdiff(payload, obj) + sizeof(bid32);
|
||||
case PARSE:
|
||||
{
|
||||
parser *p = (parser *) arg;
|
||||
return parse(p->begin, &p->end, &p->output, rt);
|
||||
}
|
||||
case RENDER:
|
||||
{
|
||||
renderer *r = (renderer *) arg;
|
||||
return obj->render(r->begin, r->end, rt);
|
||||
}
|
||||
|
||||
default:
|
||||
// Check if anyone else knows how to deal with it
|
||||
return DELEGATE(object);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
OBJECT_PARSER_BODY(decimal32)
|
||||
// ----------------------------------------------------------------------------
|
||||
// Try to parse this as an decimal32
|
||||
// ----------------------------------------------------------------------------
|
||||
{
|
||||
cstring p = begin;
|
||||
|
||||
// Skip leading sign
|
||||
if (*p == '+' || *p == '-')
|
||||
p++;
|
||||
|
||||
// Skip digits
|
||||
cstring digits = p;
|
||||
while (*p >= '0' && *p <= '9')
|
||||
p++;
|
||||
|
||||
// If we had no digits, check for special names or exit
|
||||
if (p == digits)
|
||||
{
|
||||
if (strncasecmp(p, "infinity", sizeof("infinity") - 1) != 0 &&
|
||||
strncasecmp(p, "NaN", sizeof("NaN") - 1) != 0)
|
||||
return SKIP;
|
||||
}
|
||||
|
||||
// Check decimal dot
|
||||
char *decimal = nullptr;
|
||||
if (*p == '.' || *p == ',')
|
||||
{
|
||||
decimal = (char *) p++;
|
||||
while (*p >= '0' && *p <= '9')
|
||||
p++;
|
||||
}
|
||||
|
||||
// Check exponent
|
||||
char *exponent = nullptr;
|
||||
if (*p == 'e' || *p == 'E' || *p == Settings.exponentChar)
|
||||
{
|
||||
exponent = (char *) p++;
|
||||
if (*p == '+' || *p == '-')
|
||||
p++;
|
||||
cstring expval = p;
|
||||
while (*p >= '0' && *p <= '9')
|
||||
p++;
|
||||
if (p == expval)
|
||||
{
|
||||
rt.error("Malformed exponent");
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
// Patch the input to the BID library
|
||||
char dot = '.';
|
||||
if (decimal)
|
||||
{
|
||||
dot = *decimal;
|
||||
*decimal = '.';
|
||||
}
|
||||
|
||||
char exp = 'e';
|
||||
if (exponent)
|
||||
{
|
||||
exp = *exponent;
|
||||
*exponent = 'e';
|
||||
}
|
||||
|
||||
// Parse the number
|
||||
if (end)
|
||||
*end = p;
|
||||
if (out)
|
||||
*out = rt.make<decimal32>(ID_decimal32, begin);
|
||||
|
||||
// Restore the patched input
|
||||
if (decimal)
|
||||
*decimal = dot;
|
||||
if (exponent)
|
||||
*exponent = exp;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
OBJECT_RENDERER_BODY(decimal32)
|
||||
// ----------------------------------------------------------------------------
|
||||
// Render the decimal32 into the given string buffer
|
||||
// ----------------------------------------------------------------------------
|
||||
{
|
||||
// Align the value
|
||||
bid32 num = value();
|
||||
|
||||
// Render in a separate buffer to avoid overflows
|
||||
char buffer[50];
|
||||
bid32_to_string(buffer, &num);
|
||||
|
||||
// Adjust special characters
|
||||
for (char *p = buffer; *p && p < buffer + sizeof(buffer); p++)
|
||||
if (*p == 'e' || *p == 'E')
|
||||
*p = Settings.exponentChar;
|
||||
else if (*p == '.')
|
||||
*p = Settings.decimalDot;
|
||||
|
||||
// And return it to the caller
|
||||
return snprintf(begin, end - begin, "%s", buffer);
|
||||
}
|
71
src/decimal-32.h
Normal file
71
src/decimal-32.h
Normal file
|
@ -0,0 +1,71 @@
|
|||
#ifndef DECIMAL32_H
|
||||
#define DECIMAL32_H
|
||||
// ****************************************************************************
|
||||
// decimal32.h DB48X project
|
||||
// ****************************************************************************
|
||||
//
|
||||
// File Description:
|
||||
//
|
||||
// Real numbers in decimal32 representation
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// ****************************************************************************
|
||||
// (C) 2022 Christophe de Dinechin <christophe@dinechin.org>
|
||||
// This software is licensed under the terms outlined in LICENSE.txt
|
||||
// ****************************************************************************
|
||||
// This file is part of DB48X.
|
||||
//
|
||||
// DB48X is free software: you can redistribute it and/or modify
|
||||
// it under the terms outlined in the LICENSE.txt file
|
||||
//
|
||||
// DB48X is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// ****************************************************************************
|
||||
|
||||
#include "object.h"
|
||||
|
||||
#include <bid_conf.h>
|
||||
#include <bid_functions.h>
|
||||
#include <cstring>
|
||||
|
||||
struct decimal32 : object
|
||||
// ----------------------------------------------------------------------------
|
||||
// Floating-point numbers in 32-bit decimal32 representation
|
||||
// ----------------------------------------------------------------------------
|
||||
{
|
||||
typedef BID_UINT32 bid32;
|
||||
|
||||
decimal32(cstring value, id type = ID_decimal32): object(type)
|
||||
{
|
||||
bid32 num;
|
||||
bid32_from_string(&num, value);
|
||||
byte *p = payload();
|
||||
memcpy(p, &num, sizeof(num));
|
||||
}
|
||||
|
||||
static size_t required_memory(id i, cstring value)
|
||||
{
|
||||
return leb128size(i) + sizeof(bid32);
|
||||
}
|
||||
|
||||
bid32 value()
|
||||
{
|
||||
bid32 result;
|
||||
byte *p = payload();
|
||||
memcpy(&result, p, sizeof(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
OBJECT_HANDLER(decimal32);
|
||||
OBJECT_PARSER(decimal32);
|
||||
OBJECT_RENDERER(decimal32);
|
||||
};
|
||||
|
||||
#endif // DECIMAL32_H
|
174
src/decimal-64.cc
Normal file
174
src/decimal-64.cc
Normal file
|
@ -0,0 +1,174 @@
|
|||
// ****************************************************************************
|
||||
// decimal64.cc DB48X project
|
||||
// ****************************************************************************
|
||||
//
|
||||
// File Description:
|
||||
//
|
||||
// Implementation of decimal floating point using Intel's library
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// ****************************************************************************
|
||||
// (C) 2022 Christophe de Dinechin <christophe@dinechin.org>
|
||||
// This software is licensed under the terms outlined in LICENSE.txt
|
||||
// ****************************************************************************
|
||||
// This file is part of DB48X.
|
||||
//
|
||||
// DB48X is free software: you can redistribute it and/or modify
|
||||
// it under the terms outlined in the LICENSE.txt file
|
||||
//
|
||||
// DB48X is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// ****************************************************************************
|
||||
|
||||
#include "decimal-64.h"
|
||||
|
||||
#include "runtime.h"
|
||||
#include "settings.h"
|
||||
|
||||
#include <bid_conf.h>
|
||||
#include <bid_functions.h>
|
||||
#include <cstdio>
|
||||
|
||||
|
||||
OBJECT_HANDLER_BODY(decimal64)
|
||||
// ----------------------------------------------------------------------------
|
||||
// Handle commands for decimal64s
|
||||
// ----------------------------------------------------------------------------
|
||||
{
|
||||
switch(cmd)
|
||||
{
|
||||
case EVAL:
|
||||
// Decimal64 values evaluate as self
|
||||
rt.push(obj);
|
||||
return 0;
|
||||
case SIZE:
|
||||
return ptrdiff(payload, obj) + sizeof(bid64);
|
||||
case PARSE:
|
||||
{
|
||||
parser *p = (parser *) arg;
|
||||
return parse(p->begin, &p->end, &p->output, rt);
|
||||
}
|
||||
case RENDER:
|
||||
{
|
||||
renderer *r = (renderer *) arg;
|
||||
return obj->render(r->begin, r->end, rt);
|
||||
}
|
||||
|
||||
default:
|
||||
// Check if anyone else knows how to deal with it
|
||||
return DELEGATE(object);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
OBJECT_PARSER_BODY(decimal64)
|
||||
// ----------------------------------------------------------------------------
|
||||
// Try to parse this as an decimal64
|
||||
// ----------------------------------------------------------------------------
|
||||
{
|
||||
cstring p = begin;
|
||||
|
||||
// Skip leading sign
|
||||
if (*p == '+' || *p == '-')
|
||||
p++;
|
||||
|
||||
// Skip digits
|
||||
cstring digits = p;
|
||||
while (*p >= '0' && *p <= '9')
|
||||
p++;
|
||||
|
||||
// If we had no digits, check for special names or exit
|
||||
if (p == digits)
|
||||
{
|
||||
if (strncasecmp(p, "infinity", sizeof("infinity") - 1) != 0 &&
|
||||
strncasecmp(p, "NaN", sizeof("NaN") - 1) != 0)
|
||||
return SKIP;
|
||||
}
|
||||
|
||||
// Check decimal dot
|
||||
char *decimal = nullptr;
|
||||
if (*p == '.' || *p == ',')
|
||||
{
|
||||
decimal = (char *) p++;
|
||||
while (*p >= '0' && *p <= '9')
|
||||
p++;
|
||||
}
|
||||
|
||||
// Check exponent
|
||||
char *exponent = nullptr;
|
||||
if (*p == 'e' || *p == 'E' || *p == Settings.exponentChar)
|
||||
{
|
||||
exponent = (char *) p++;
|
||||
if (*p == '+' || *p == '-')
|
||||
p++;
|
||||
cstring expval = p;
|
||||
while (*p >= '0' && *p <= '9')
|
||||
p++;
|
||||
if (p == expval)
|
||||
{
|
||||
rt.error("Malformed exponent");
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
// Patch the input to the BID library
|
||||
char dot = '.';
|
||||
if (decimal)
|
||||
{
|
||||
dot = *decimal;
|
||||
*decimal = '.';
|
||||
}
|
||||
|
||||
char exp = 'e';
|
||||
if (exponent)
|
||||
{
|
||||
exp = *exponent;
|
||||
*exponent = 'e';
|
||||
}
|
||||
|
||||
// Parse the number
|
||||
if (end)
|
||||
*end = p;
|
||||
if (out)
|
||||
*out = rt.make<decimal64>(ID_decimal64, begin);
|
||||
|
||||
// Restore the patched input
|
||||
if (decimal)
|
||||
*decimal = dot;
|
||||
if (exponent)
|
||||
*exponent = exp;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
OBJECT_RENDERER_BODY(decimal64)
|
||||
// ----------------------------------------------------------------------------
|
||||
// Render the decimal64 into the given string buffer
|
||||
// ----------------------------------------------------------------------------
|
||||
{
|
||||
// Align the value
|
||||
bid64 num = value();
|
||||
|
||||
// Render in a separate buffer to avoid overflows
|
||||
char buffer[50];
|
||||
bid64_to_string(buffer, &num);
|
||||
|
||||
// Adjust special characters
|
||||
for (char *p = buffer; *p && p < buffer + sizeof(buffer); p++)
|
||||
if (*p == 'e' || *p == 'E')
|
||||
*p = Settings.exponentChar;
|
||||
else if (*p == '.')
|
||||
*p = Settings.decimalDot;
|
||||
|
||||
// And return it to the caller
|
||||
return snprintf(begin, end - begin, "%s", buffer);
|
||||
}
|
71
src/decimal-64.h
Normal file
71
src/decimal-64.h
Normal file
|
@ -0,0 +1,71 @@
|
|||
#ifndef DECIMAL64_H
|
||||
#define DECIMAL64_H
|
||||
// ****************************************************************************
|
||||
// decimal64.h DB48X project
|
||||
// ****************************************************************************
|
||||
//
|
||||
// File Description:
|
||||
//
|
||||
// Real numbers in decimal64 representation
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// ****************************************************************************
|
||||
// (C) 2022 Christophe de Dinechin <christophe@dinechin.org>
|
||||
// This software is licensed under the terms outlined in LICENSE.txt
|
||||
// ****************************************************************************
|
||||
// This file is part of DB48X.
|
||||
//
|
||||
// DB48X is free software: you can redistribute it and/or modify
|
||||
// it under the terms outlined in the LICENSE.txt file
|
||||
//
|
||||
// DB48X is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// ****************************************************************************
|
||||
|
||||
#include "object.h"
|
||||
|
||||
#include <bid_conf.h>
|
||||
#include <bid_functions.h>
|
||||
#include <cstring>
|
||||
|
||||
struct decimal64 : object
|
||||
// ----------------------------------------------------------------------------
|
||||
// Floating-point numbers in 64-bit decimal64 representation
|
||||
// ----------------------------------------------------------------------------
|
||||
{
|
||||
typedef BID_UINT64 bid64;
|
||||
|
||||
decimal64(cstring value, id type = ID_decimal64): object(type)
|
||||
{
|
||||
bid64 num;
|
||||
bid64_from_string(&num, value);
|
||||
byte *p = payload();
|
||||
memcpy(p, &num, sizeof(num));
|
||||
}
|
||||
|
||||
static size_t required_memory(id i, cstring value)
|
||||
{
|
||||
return leb128size(i) + sizeof(bid64);
|
||||
}
|
||||
|
||||
bid64 value()
|
||||
{
|
||||
bid64 result;
|
||||
byte *p = payload();
|
||||
memcpy(&result, p, sizeof(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
OBJECT_HANDLER(decimal64);
|
||||
OBJECT_PARSER(decimal64);
|
||||
OBJECT_RENDERER(decimal64);
|
||||
};
|
||||
|
||||
#endif // DECIMAL64_H
|
174
src/decimal128.cc
Normal file
174
src/decimal128.cc
Normal file
|
@ -0,0 +1,174 @@
|
|||
// ****************************************************************************
|
||||
// decimal128.cc DB48X project
|
||||
// ****************************************************************************
|
||||
//
|
||||
// File Description:
|
||||
//
|
||||
// Implementation of decimal floating point using Intel's library
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// ****************************************************************************
|
||||
// (C) 2022 Christophe de Dinechin <christophe@dinechin.org>
|
||||
// This software is licensed under the terms outlined in LICENSE.txt
|
||||
// ****************************************************************************
|
||||
// This file is part of DB48X.
|
||||
//
|
||||
// DB48X is free software: you can redistribute it and/or modify
|
||||
// it under the terms outlined in the LICENSE.txt file
|
||||
//
|
||||
// DB48X is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// ****************************************************************************
|
||||
|
||||
#include "decimal128.h"
|
||||
|
||||
#include "runtime.h"
|
||||
#include "settings.h"
|
||||
|
||||
#include <bid_conf.h>
|
||||
#include <bid_functions.h>
|
||||
#include <cstdio>
|
||||
|
||||
|
||||
OBJECT_HANDLER_BODY(decimal128)
|
||||
// ----------------------------------------------------------------------------
|
||||
// Handle commands for decimal128s
|
||||
// ----------------------------------------------------------------------------
|
||||
{
|
||||
switch(cmd)
|
||||
{
|
||||
case EVAL:
|
||||
// Decimal128 values evaluate as self
|
||||
rt.push(obj);
|
||||
return 0;
|
||||
case SIZE:
|
||||
return ptrdiff(payload, obj) + sizeof(bid128);
|
||||
case PARSE:
|
||||
{
|
||||
parser *p = (parser *) arg;
|
||||
return parse(p->begin, &p->end, &p->output, rt);
|
||||
}
|
||||
case RENDER:
|
||||
{
|
||||
renderer *r = (renderer *) arg;
|
||||
return obj->render(r->begin, r->end, rt);
|
||||
}
|
||||
|
||||
default:
|
||||
// Check if anyone else knows how to deal with it
|
||||
return DELEGATE(object);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
OBJECT_PARSER_BODY(decimal128)
|
||||
// ----------------------------------------------------------------------------
|
||||
// Try to parse this as an decimal128
|
||||
// ----------------------------------------------------------------------------
|
||||
{
|
||||
cstring p = begin;
|
||||
|
||||
// Skip leading sign
|
||||
if (*p == '+' || *p == '-')
|
||||
p++;
|
||||
|
||||
// Skip digits
|
||||
cstring digits = p;
|
||||
while (*p >= '0' && *p <= '9')
|
||||
p++;
|
||||
|
||||
// If we had no digits, check for special names or exit
|
||||
if (p == digits)
|
||||
{
|
||||
if (strncasecmp(p, "infinity", sizeof("infinity") - 1) != 0 &&
|
||||
strncasecmp(p, "NaN", sizeof("NaN") - 1) != 0)
|
||||
return SKIP;
|
||||
}
|
||||
|
||||
// Check decimal dot
|
||||
char *decimal = nullptr;
|
||||
if (*p == '.' || *p == ',')
|
||||
{
|
||||
decimal = (char *) p++;
|
||||
while (*p >= '0' && *p <= '9')
|
||||
p++;
|
||||
}
|
||||
|
||||
// Check exponent
|
||||
char *exponent = nullptr;
|
||||
if (*p == 'e' || *p == 'E' || *p == Settings.exponentChar)
|
||||
{
|
||||
exponent = (char *) p++;
|
||||
if (*p == '+' || *p == '-')
|
||||
p++;
|
||||
cstring expval = p;
|
||||
while (*p >= '0' && *p <= '9')
|
||||
p++;
|
||||
if (p == expval)
|
||||
{
|
||||
rt.error("Malformed exponent");
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
// Patch the input to the BID library
|
||||
char dot = '.';
|
||||
if (decimal)
|
||||
{
|
||||
dot = *decimal;
|
||||
*decimal = '.';
|
||||
}
|
||||
|
||||
char exp = 'e';
|
||||
if (exponent)
|
||||
{
|
||||
exp = *exponent;
|
||||
*exponent = 'e';
|
||||
}
|
||||
|
||||
// Parse the number
|
||||
if (end)
|
||||
*end = p;
|
||||
if (out)
|
||||
*out = rt.make<decimal128>(ID_decimal128, begin);
|
||||
|
||||
// Restore the patched input
|
||||
if (decimal)
|
||||
*decimal = dot;
|
||||
if (exponent)
|
||||
*exponent = exp;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
OBJECT_RENDERER_BODY(decimal128)
|
||||
// ----------------------------------------------------------------------------
|
||||
// Render the decimal128 into the given string buffer
|
||||
// ----------------------------------------------------------------------------
|
||||
{
|
||||
// Align the value
|
||||
bid128 num = value();
|
||||
|
||||
// Render in a separate buffer to avoid overflows
|
||||
char buffer[50];
|
||||
bid128_to_string(buffer, &num);
|
||||
|
||||
// Adjust special characters
|
||||
for (char *p = buffer; *p && p < buffer + sizeof(buffer); p++)
|
||||
if (*p == 'e' || *p == 'E')
|
||||
*p = Settings.exponentChar;
|
||||
else if (*p == '.')
|
||||
*p = Settings.decimalDot;
|
||||
|
||||
// And return it to the caller
|
||||
return snprintf(begin, end - begin, "%s", buffer);
|
||||
}
|
71
src/decimal128.h
Normal file
71
src/decimal128.h
Normal file
|
@ -0,0 +1,71 @@
|
|||
#ifndef DECIMAL128_H
|
||||
#define DECIMAL128_H
|
||||
// ****************************************************************************
|
||||
// decimal128.h DB48X project
|
||||
// ****************************************************************************
|
||||
//
|
||||
// File Description:
|
||||
//
|
||||
// Real numbers in decimal128 representation
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// ****************************************************************************
|
||||
// (C) 2022 Christophe de Dinechin <christophe@dinechin.org>
|
||||
// This software is licensed under the terms outlined in LICENSE.txt
|
||||
// ****************************************************************************
|
||||
// This file is part of DB48X.
|
||||
//
|
||||
// DB48X is free software: you can redistribute it and/or modify
|
||||
// it under the terms outlined in the LICENSE.txt file
|
||||
//
|
||||
// DB48X is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// ****************************************************************************
|
||||
|
||||
#include "object.h"
|
||||
|
||||
#include <bid_conf.h>
|
||||
#include <bid_functions.h>
|
||||
#include <cstring>
|
||||
|
||||
struct decimal128 : object
|
||||
// ----------------------------------------------------------------------------
|
||||
// Floating-point numbers in 128-bit decimal128 representation
|
||||
// ----------------------------------------------------------------------------
|
||||
{
|
||||
typedef BID_UINT128 bid128;
|
||||
|
||||
decimal128(cstring value, id type = ID_decimal128): object(type)
|
||||
{
|
||||
bid128 num;
|
||||
bid128_from_string(&num, value);
|
||||
byte *p = payload();
|
||||
memcpy(p, &num, sizeof(num));
|
||||
}
|
||||
|
||||
static size_t required_memory(id i, cstring value)
|
||||
{
|
||||
return leb128size(i) + sizeof(bid128);
|
||||
}
|
||||
|
||||
bid128 value()
|
||||
{
|
||||
bid128 result;
|
||||
byte *p = payload();
|
||||
memcpy(&result, p, sizeof(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
OBJECT_HANDLER(decimal128);
|
||||
OBJECT_PARSER(decimal128);
|
||||
OBJECT_RENDERER(decimal128);
|
||||
};
|
||||
|
||||
#endif // DECIMAL128_H
|
8
src/id.h
8
src/id.h
|
@ -37,11 +37,9 @@ ID(bin_integer)
|
|||
ID(dec_integer)
|
||||
|
||||
|
||||
// ID(real)
|
||||
// ID(real32)
|
||||
// ID(decimal32)
|
||||
// ID(decimal64)
|
||||
// ID(decimal128)
|
||||
ID(decimal32)
|
||||
ID(decimal64)
|
||||
ID(decimal128)
|
||||
|
||||
//ID(add)
|
||||
//ID(sub)
|
||||
|
|
|
@ -58,7 +58,7 @@ OBJECT_HANDLER_BODY(integer)
|
|||
|
||||
default:
|
||||
// Check if anyone else knows how to deal with it
|
||||
return SKIP;
|
||||
return DELEGATE(object);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
//
|
||||
// File Description:
|
||||
//
|
||||
//
|
||||
// The DB48X main RPL loop
|
||||
//
|
||||
//
|
||||
//
|
||||
|
@ -33,14 +33,15 @@
|
|||
#include "menu.h"
|
||||
#include "num.h"
|
||||
#include "rpl.h"
|
||||
#include "settings.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cctype>
|
||||
#include <dmcp.h>
|
||||
|
||||
using std::min;
|
||||
|
@ -306,7 +307,7 @@ void disp_stack_line(char *s, int a, int cpl)
|
|||
}
|
||||
char *t = strchr(s, expchar);
|
||||
if (t)
|
||||
*t = exponent_char; // Special 'E'
|
||||
*t = Settings.exponentChar; // Special 'E'
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -30,6 +30,9 @@
|
|||
#include "object.h"
|
||||
|
||||
#include "integer.h"
|
||||
#include "decimal128.h"
|
||||
#include "decimal-64.h"
|
||||
#include "decimal-32.h"
|
||||
#include "rplstring.h"
|
||||
#include "runtime.h"
|
||||
|
||||
|
@ -88,8 +91,7 @@ OBJECT_HANDLER_BODY(object)
|
|||
"<Unknown object %p>", obj);
|
||||
}
|
||||
default:
|
||||
rt.error("Invalid command for default object");
|
||||
return ERROR;
|
||||
return SKIP;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -208,7 +208,7 @@ struct object
|
|||
#define OBJECT_RENDERER(type) \
|
||||
intptr_t render(char *begin, cstring end, runtime &rt = RT)
|
||||
|
||||
#define OBJECT_RENDERER_BODY(type) \
|
||||
#define OBJECT_RENDERER_BODY(type) \
|
||||
intptr_t type::render(char *begin, cstring end, runtime &rt)
|
||||
|
||||
OBJECT_RENDERER(object);
|
||||
|
@ -233,6 +233,9 @@ struct object
|
|||
object *payload)
|
||||
OBJECT_HANDLER_NO_ID(object);
|
||||
|
||||
#define DELEGATE(base) \
|
||||
base::handle(rt, cmd, arg, obj, payload)
|
||||
|
||||
static cstring name(id i)
|
||||
// ------------------------------------------------------------------------
|
||||
// Return the name for a given ID
|
||||
|
|
|
@ -63,7 +63,7 @@ OBJECT_HANDLER_BODY(string)
|
|||
|
||||
default:
|
||||
// Check if anyone else knows how to deal with it
|
||||
return SKIP;
|
||||
return DELEGATE(object);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
32
src/settings.cc
Normal file
32
src/settings.cc
Normal file
|
@ -0,0 +1,32 @@
|
|||
// ****************************************************************************
|
||||
// settings.cc DB48X project
|
||||
// ****************************************************************************
|
||||
//
|
||||
// File Description:
|
||||
//
|
||||
// Representation of settings
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// ****************************************************************************
|
||||
// (C) 2022 Christophe de Dinechin <christophe@dinechin.org>
|
||||
// This software is licensed under the terms outlined in LICENSE.txt
|
||||
// ****************************************************************************
|
||||
// This file is part of DB48X.
|
||||
//
|
||||
// DB48X is free software: you can redistribute it and/or modify
|
||||
// it under the terms outlined in the LICENSE.txt file
|
||||
//
|
||||
// DB48X is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// ****************************************************************************
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
settings Settings;
|
55
src/settings.h
Normal file
55
src/settings.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
#ifndef SETTINGS_H
|
||||
#define SETTINGS_H
|
||||
// ****************************************************************************
|
||||
// settings.h DB48X project
|
||||
// ****************************************************************************
|
||||
//
|
||||
// File Description:
|
||||
//
|
||||
// List of system-wide settings
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// ****************************************************************************
|
||||
// (C) 2022 Christophe de Dinechin <christophe@dinechin.org>
|
||||
// This software is licensed under the terms outlined in LICENSE.txt
|
||||
// ****************************************************************************
|
||||
// This file is part of DB48X.
|
||||
//
|
||||
// DB48X is free software: you can redistribute it and/or modify
|
||||
// it under the terms outlined in the LICENSE.txt file
|
||||
//
|
||||
// DB48X is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// ****************************************************************************
|
||||
|
||||
#include <types.h>
|
||||
|
||||
struct settings
|
||||
// ----------------------------------------------------------------------------
|
||||
// Internal representation of settings
|
||||
// ----------------------------------------------------------------------------
|
||||
{
|
||||
settings()
|
||||
: precision(32),
|
||||
displayed(0),
|
||||
decimalDot('.'),
|
||||
exponentChar(0x98) // The special mini-'E'
|
||||
{}
|
||||
|
||||
uint precision; // Internal precision for numbers
|
||||
uint displayed; // Number of displayed digits
|
||||
char decimalDot; // Character used for decimal separator
|
||||
char exponentChar; // The character used to represent exponents
|
||||
};
|
||||
|
||||
|
||||
extern settings Settings;
|
||||
|
||||
#endif // SETTINGS_H
|
|
@ -48,8 +48,7 @@ typedef const char *cstring;
|
|||
typedef const char *utf8;
|
||||
typedef unsigned utf8code;
|
||||
|
||||
enum { exponent_char = 0x98 };
|
||||
|
||||
#define UNUSED(var) ((void *) &(var))
|
||||
// Indicate that an argument may be unused
|
||||
#define UNUSED(x) ((void) &x)
|
||||
|
||||
#endif // TYPES_H
|
||||
|
|
Loading…
Reference in a new issue