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:
commit
7a733cea0b
@ -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
|
||||
|
@ -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--;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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){
|
||||
|
@ -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
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include <stdio.h>
|
||||
#include "decn.h"
|
||||
|
||||
char Buf[DECN_BUF_SIZE];
|
||||
extern char Buf[DECN_BUF_SIZE];
|
||||
|
||||
|
||||
static dec80 diff;
|
||||
|
@ -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"){
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user