Merge pull request #1 from srtlg/development-compile-sdcc350

- fixes build with sdcc 3.5.0
- adds a few more checks for special cases, and prevents some operations on `Error`
This commit is contained in:
jjj11x 2020-09-07 23:10:24 -04:00 committed by GitHub
commit 7a733cea0b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 126 additions and 64 deletions

View File

@ -1,14 +1,15 @@
cmake_minimum_required(VERSION 3.1)
project(stc_rpncalc C CXX)
# 3rd party tools
find_package(Qt5 COMPONENTS Widgets Qml Quick REQUIRED)
set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Build type (for tests debug make sense)")
# Compiler warnings
if(MSVC)
add_compile_options(/W4 /WX)
else()
add_compile_options(-Wall -Wextra -pedantic)
set(cpp_flags -std=c++11 -fsanitize=address,undefined)
add_compile_options("$<$<COMPILE_LANGUAGE:CXX>:${cxx_flags}>")
endif()
# Directory with source code

View File

@ -33,7 +33,7 @@ __xdata dec80 LastX;
#define STACK_T 3
uint8_t NoLift = 0;
uint8_t IsShifted = 0;
__bit IsShifted = 0;
//stack "grows" towards 0
__xdata dec80 Stack[STACK_SIZE]; //0->x, 1->y, 2->z, 3->t initially
@ -46,7 +46,7 @@ static void pop(){
StackPtr++; //adjust pointer
}
void push_decn(__xdata const char* signif_str, exp_t exponent){
void push_decn(__xdata const char* signif_str, __xdata exp_t exponent){
if (!NoLift){
StackPtr--;
}

View File

@ -30,9 +30,9 @@ extern "C" {
void process_cmd(char cmd);
//push_decn is equivalent to "set_x()" if no_lift is true
void push_decn(__xdata const char* signif_str, exp_t exponent);
void push_decn(__xdata const char* signif_str, __xdata exp_t exponent);
extern uint8_t NoLift;
extern uint8_t IsShifted;
extern __bit IsShifted;
void clear_x(void);
__xdata dec80* get_x(void);

View File

@ -1,3 +1,10 @@
add_library(Catch INTERFACE)
if(EXISTS /usr/include/catch/catch.hpp)
target_include_directories(Catch INTERFACE /usr/include/catch)
elseif(EXISTS /usr/include/catch2/catch.hpp)
target_include_directories(Catch INTERFACE /usr/include/catch2)
else()
endif()
#code coverage
add_library(coverage_config INTERFACE)
@ -12,10 +19,10 @@ add_library(decn_cover decn.c)
target_link_libraries(decn_cover PUBLIC coverage_config)
add_executable(decn_test decn_test.c ../utils.c)
target_link_libraries(decn_test decn_cover coverage_config)
target_link_libraries(decn_test decn_cover coverage_config Catch)
add_executable(decn_tests catch_main.cpp decn_tests.cpp ../utils.c)
target_link_libraries(decn_tests decn_cover coverage_config mpfr)
target_link_libraries(decn_tests decn_cover coverage_config mpfr Catch)
# decn prototyping
add_subdirectory(proto)

View File

@ -73,8 +73,18 @@ __xdata dec80 Tmp4Decn; //used by div_decn() and pow_decn()
__xdata char Buf[DECN_BUF_SIZE];
//1 constant
const dec80 DECN_1 = {
0, {10, 0}
};
void copy_decn(dec80* dest, const dec80* src){
//ln(10) constant
const dec80 DECN_LN_10 = {
0, {23, 2, 58, 50, 92, 99, 40, 45, 68}
};
void copy_decn(dec80* const dest, const dec80* const src){
uint8_t i;
dest->exponent = src->exponent;
@ -84,7 +94,7 @@ void copy_decn(dec80* dest, const dec80* src){
}
}
exp_t get_exponent(const dec80* x){
exp_t get_exponent(const dec80* const x){
exp_t exponent = x->exponent;
#ifdef EXP16
if (exponent & 0x4000){ //negative
@ -181,7 +191,7 @@ static void remove_leading_zeros(dec80* x){
set_exponent(x, exponent, is_negative);
}
void build_dec80(__xdata const char* signif_str, exp_t exponent){
void build_dec80(__xdata const char* signif_str, __xdata exp_t exponent){
enum {
SIGN_ZERO,
SIGN_ZERO_SEEN_POINT,
@ -306,7 +316,6 @@ void build_dec80(__xdata const char* signif_str, exp_t exponent){
// adjust exponent for left-aligned significand input
// or for number of digits past decimal point
if (num_lr_points > 0){ //left count exists
assert(DEC80_NUM_LSU*2 > num_lr_points);
new_exponent = exponent + (num_lr_points - 1); //1 digit left of implicit point
//overflow is checked later, should be impossible to overflow int16_t:
assert(new_exponent >= exponent);
@ -664,8 +673,8 @@ void add_decn(void){
}
//may need to rescale number
if (carry > 0){
assert(carry == 1);
exp_t curr_exp = get_exponent(&AccDecn);
assert(carry == 1);
rel = (AccDecn.exponent < 0); //is_neg?
//shift right
shift_right(&AccDecn);
@ -686,6 +695,12 @@ void mult_decn(void){
uint8_t carry = 0;
uint8_t is_neg;
exp_t new_exponent;
#ifdef EXTRA_CHECKS
if (decn_is_nan(&AccDecn) || decn_is_nan(&BDecn)) {
set_dec80_NaN(&AccDecn);
return;
}
#endif
//initialize values
set_dec80_zero(&TmpDecn);
//normalize
@ -1218,14 +1233,22 @@ inline void exp10_decn(void){
exp_decn();
}
//inline void pow_decn(void)
//{
// copy_decn(&Tmp4Decn, &BDecn); //save b
// ln_decn();
// copy_decn(&BDecn, &Tmp4Decn); //restore b
// mult_decn(); //accum = b*ln(accum)
// exp_decn();
//}
inline void pow_decn(void) {
if (decn_is_zero(&BDecn)) {
copy_decn(&AccDecn, &DECN_1);
return;
}
if (decn_is_zero(&AccDecn)) {
set_dec80_zero(&AccDecn);
return;
}
//calculate AccDecn = AccDecn ^ BDecn
copy_decn(&Tmp4Decn, &BDecn); //save b
ln_decn();
copy_decn(&BDecn, &Tmp4Decn); //restore b
mult_decn(); //accum = b*ln(accum)
exp_decn();
}
static void set_str_error(void){

View File

@ -57,26 +57,16 @@ typedef struct {
//implicit decimal point between (lsu[0]/10) and (lsu[0]%10)
} dec80;
//1 constant
static const dec80 DECN_1 = {
0, {10, 0}
};
//ln(10) constant
static const dec80 DECN_LN_10 = {
0, {23, 2, 58, 50, 92, 99, 40, 45, 68}
};
//remove sign bit, and return 15 bit exponent sign-extended to 16 bits
exp_t get_exponent(const dec80* x);
exp_t get_exponent(const dec80* const x);
void copy_decn(dec80* dest, const dec80* src);
void copy_decn(dec80* const dest, const dec80* const src);
extern dec80 AccDecn;
extern __idata dec80 BDecn;
extern __xdata dec80 Tmp4Decn;
void build_dec80(__xdata const char* signif_str, exp_t exponent);
void build_dec80(__xdata const char* signif_str, __xdata exp_t exponent);
void set_dec80_zero(dec80* dest);
void set_dec80_NaN(dec80* dest);
@ -94,15 +84,7 @@ void log10_decn(void);
void exp_decn(void);
void exp10_decn(void);
//calculate AccDecn = AccDecn ^ BDecn
#define pow_decn() do {\
copy_decn(&Tmp4Decn, &BDecn); \
ln_decn(); \
copy_decn(&BDecn, &Tmp4Decn); \
mult_decn(); \
exp_decn(); \
} while (0);
void pow_decn(void);
//Buf should hold at least 18 + 4 + 5 + 1 = 28
#define DECN_BUF_SIZE 28

View File

@ -20,7 +20,7 @@
#include <stdio.h>
#include "decn.h"
char Buf[DECN_BUF_SIZE];
extern char Buf[DECN_BUF_SIZE];
static dec80 diff;

View File

@ -32,7 +32,7 @@ using Catch::Matchers::Equals;
char Buf[DECN_BUF_SIZE];
extern char Buf[DECN_BUF_SIZE];
TEST_CASE("build decn"){
@ -110,6 +110,10 @@ TEST_CASE("build decn"){
decn_to_str_complete(&AccDecn);
CHECK_THAT(Buf, Equals("123456789012345678."));
build_dec80("12345678901234567890", +2);
decn_to_str_complete(&AccDecn);
CHECK_THAT(Buf, Equals("1.23456789012345678E21"));
//overflow
build_dec80("100", DEC80_MAX_EXP-1);
decn_to_str_complete(&AccDecn);
@ -243,6 +247,19 @@ TEST_CASE("multiply"){
decn_to_str_complete(&AccDecn);
CHECK_THAT(Buf, Equals("Error")); //acc*b
//NaN
build_dec80("9.99", DEC80_MAX_EXP/2);
set_dec80_NaN(&BDecn);
mult_decn();
decn_to_str_complete(&AccDecn);
CHECK_THAT(Buf, Equals("Error")); //acc*b
//NaN
set_dec80_NaN(&AccDecn);
build_decn_at(&BDecn, "9.99", DEC80_MAX_EXP/2);
mult_decn();
decn_to_str_complete(&AccDecn);
CHECK_THAT(Buf, Equals("Error")); //acc*b
}
static void div_test(
@ -466,12 +483,10 @@ static void pow_test(
CAPTURE(b_str); CAPTURE(b_exp);
//compute power
log_test(a_str, a_exp);
build_decn_at(&BDecn, b_str, b_exp);
mult_decn();
int8_t exp_test_exp = decn_to_str(&AccDecn);
std::string copied(Buf);
exp_test(copied.c_str(), exp_test_exp, 6e-15);
build_dec80(a_str, a_exp);
pow_decn();
decn_to_str_complete(&AccDecn);
CAPTURE(Buf); // a^b
@ -487,9 +502,14 @@ static void pow_test(
// CAPTURE(b_full_str);
bmp::mpfr_float a_actual(a_full_str);
bmp::mpfr_float b_actual(b_full_str);
a_actual = exp(log(a_actual) * b_actual);
bmp::mpfr_float rel_diff = abs((a_actual - calculated) / a_actual);
CHECK(rel_diff < 3e-14);
a_actual = pow(a_actual, b_actual);
if (decn_is_zero(&AccDecn)) {
bmp::mpfr_float diff = abs(a_actual - calculated);
CHECK(diff < 3e-14);
} else {
bmp::mpfr_float rel_diff = abs((a_actual - calculated)/a_actual);
CHECK(rel_diff < 3e-14);
}
}
TEST_CASE("power"){
@ -502,6 +522,26 @@ TEST_CASE("power"){
"3", 0,
"201", 0
);
pow_test(
"5", 0,
"0", 0
);
pow_test(
"5", 0,
"0", 2
);
pow_test(
"0", 0,
"5", 0
);
pow_test(
"0", 0,
"0", 0
);
}
TEST_CASE("u32str corner"){

View File

@ -43,7 +43,7 @@
static int row, col;
static uint8_t row, col;
#define CLEAR_BIT(port, bit) (port &= ~(_BV(bit)))
#define CLEAR_BITS(port, bits) (port &= ~(bits))
@ -227,6 +227,13 @@ void LCD_OutString(__xdata const char *string, uint8_t max_chars) {
}
}
void LCD_OutString_Initial(__code const char *s) {
while (*s) {
TERMIO_PutChar(*s);
s++;
}
}
short TERMIO_PutChar(unsigned char letter) {
if (letter == CR || letter == '\n') {
LCD_Clear();

View File

@ -29,11 +29,7 @@ void LCD_Clear(void);
void LCD_GoTo(uint8_t row, uint8_t col);
void LCD_OutString(__xdata const char* string, uint8_t max_chars);
#ifdef DESKTOP
void LCD_OutString_Initial(__xdata const char* string, uint8_t max_chars);
#else
#define LCD_OutString_Initial(a, b) LCD_OutString(a, b)
#endif
void LCD_OutString_Initial(__code const char* string);
short TERMIO_PutChar(unsigned char letter);
void LCD_OutNibble(uint8_t x);
void LCD_ClearToEnd(uint8_t curr_row);

View File

@ -20,6 +20,8 @@
#include <stdio.h>
#include <stdint.h>
#include <ctype.h>
#include <string.h>
#include <assert.h>
#include "lcd.h"
#define CR 13 // \r
@ -86,9 +88,10 @@ void LCD_OutString(const char *string, uint8_t max_chars) {
}
}
void LCD_OutString_Initial(const char *string, uint8_t max_chars) {
void LCD_OutString_Initial(const char *string) {
enable_checks = 0;
LCD_OutString(string, max_chars);
assert(strlen(string) <= 32);
LCD_OutString(string, 32);
enable_checks = 1;
}

View File

@ -49,7 +49,7 @@ QSemaphore LcdAvailable(1);
int8_t NewKeyBuf[4];
volatile uint8_t new_key_write_i;
volatile uint8_t new_key_read_i;
volatile uint8_t NewKeyEmpty;
volatile __bit NewKeyEmpty;
#define INCR_NEW_KEY_I(i) i = (i + 1) & 3
@ -139,7 +139,7 @@ static void latch_on(void)
__xdata char EntryBuf[MAX_CHARS_PER_LINE + 1];
__xdata uint8_t ExpBuf[2];
__xdata const char VER_STR[32+1] = "STC RPN Calculator v1.09";
__code const char VER_STR[32+1] = "STC RPN Calculator v1.10";
enum {
@ -230,7 +230,7 @@ int main()
ExpBuf[0] = 0;
ExpBuf[1] = 0;
LCD_OutString_Initial(VER_STR, 32);
LCD_OutString_Initial(VER_STR);
#ifdef DESKTOP
LcdAvailable.release();
#endif

View File

@ -48,7 +48,10 @@ void backlight_off(void);
#endif
#if defined(DESKTOP) || defined(IS_ECLIPSE)
#include <stdbool.h>
char* u32str(uint32_t x, char* buf, uint8_t base);
#define __bit bool
#define __code
#define __xdata
#define __idata
#define __sfr