From b09d7956b612ccf3a755283042f14be899d310fd Mon Sep 17 00:00:00 2001 From: Joerg Siebenmorgen Date: Mon, 5 Dec 2022 21:28:37 +0100 Subject: [PATCH 1/4] bug fix for BIN and changes to return values of POLYCENT and POLYAREA --- samples/distro-examples/tests/all.bas | 2 +- samples/distro-examples/tests/output/all.out | 2 +- src/common/blib_func.c | 38 +++++++++++++++----- 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/samples/distro-examples/tests/all.bas b/samples/distro-examples/tests/all.bas index cc656336..427cd171 100644 --- a/samples/distro-examples/tests/all.bas +++ b/samples/distro-examples/tests/all.bas @@ -99,7 +99,7 @@ print "TSAVE:" ':TSAVE file, var print "VIEW:" ':VIEW [x1,y1,x2,y2 [,color [,border-color]]] print "WINDOW:" ':WINDOW [x1,y1,x2,y2] print "WRITE:" ':WRITE #fileN; var1 [, ...] -print "ABS:" + ABS (12.2222) +print "ABS:" + ABS (-12.2222) print "ABSMAX:" + ABSMAX (1,2,3,4,5,6,7,8,9) print "ABSMIN:" + ABSMIN (1,2,3,4,5,6,7,8,9) print "ACOS:" + ACOS (x) diff --git a/samples/distro-examples/tests/output/all.out b/samples/distro-examples/tests/output/all.out index d4b49a47..004e0913 100644 --- a/samples/distro-examples/tests/output/all.out +++ b/samples/distro-examples/tests/output/all.out @@ -103,7 +103,7 @@ ATANH:nan ATN:1.489673934694 BCS:catsanddogs BGETC: -BIN:00000000000000000000000000001100 +BIN:1100 CAT: CBS:catsanddogs CEIL:13 diff --git a/src/common/blib_func.c b/src/common/blib_func.c index 3ff7b691..05df35b4 100644 --- a/src/common/blib_func.c +++ b/src/common/blib_func.c @@ -957,9 +957,18 @@ void cmd_str1(long funcCode, var_t *arg, var_t *r) { // case kwBIN: l = v_getint(arg); - IF_ERR_RETURN; + IF_ERR_RETURN; + + if (l == 0) { + r->v.p.ptr = (char *)malloc(2); + strcpy(r->v.p.ptr, "0"); + r->v.p.length = strlen(r->v.p.ptr) + 1; + break; + } + tb = malloc(33); - memset(tb, 0, 33); + memset(tb, 0, 33); + for (int i = 0; i < 32; i++) { if (l & (1 << i)) { tb[31 - i] = '1'; @@ -967,8 +976,15 @@ void cmd_str1(long funcCode, var_t *arg, var_t *r) { tb[31 - i] = '0'; } } + + // remove preceding zeros + p = tb; + while (*p == '0') { + p++; + } - r->v.p.ptr = tb; + r->v.p.ptr = (char *)malloc(strlen(p) + 1); + strcpy(r->v.p.ptr, p); r->v.p.length = strlen(r->v.p.ptr) + 1; break; case kwHEX: @@ -2307,7 +2323,7 @@ void cmd_genfunc(long funcCode, var_t *r) { for (int i = 0; i < count - 1; i++) { r->v.n = r->v.n + (poly[i].x - poly[i + 1].x) * (poly[i].y + poly[i + 1].y); } - r->v.n = fabs(r->v.n / 2); + r->v.n = r->v.n / 2; free(poly); } @@ -2327,17 +2343,21 @@ void cmd_genfunc(long funcCode, var_t *r) { IF_ERR_RETURN; err = geo_polycentroid(poly, count, &x, &y, &area); - v_toarray1(r, 2); - v_setreal(v_elem(r, 0), x); - v_setreal(v_elem(r, 1), y); if (err == 1) { rt_raise(ERR_WRONG_POLY); } if (err == 2) { - rt_raise(ERR_CENTROID); - } + // return empty array insead of "rt_raise(ERR_CENTROID);" + v_toarray1(r, 0); + free(poly); + break; + } + v_toarray1(r, 2); + v_setreal(v_elem(r, 0), x); + v_setreal(v_elem(r, 1), y); + free(poly); } break; From 5f4cbda294d9daf2c607ef5820f01605b077bebc Mon Sep 17 00:00:00 2001 From: Joerg Siebenmorgen Date: Fri, 9 Dec 2022 19:54:32 +0100 Subject: [PATCH 2/4] Implementation of MEDIAN() to calculate the median of a data sample in statistics. --- samples/distro-examples/tests/all.bas | 1 + samples/distro-examples/tests/output/all.out | 1 + src/common/blib_func.c | 4 +++ src/common/blib_math.c | 29 ++++++++++++++++++++ src/common/blib_math.h | 11 ++++++++ src/common/eval.c | 1 + src/common/kw.h | 1 + src/languages/keywords.en.c | 1 + 8 files changed, 49 insertions(+) diff --git a/samples/distro-examples/tests/all.bas b/samples/distro-examples/tests/all.bas index 427cd171..203931c0 100644 --- a/samples/distro-examples/tests/all.bas +++ b/samples/distro-examples/tests/all.bas @@ -217,6 +217,7 @@ print "SQR:" + SQR (x) print "SQUEEZE:" + SQUEEZE (s) print "STATMEAN:" + STATMEAN (1,2,3,4,5,6,7,8,9) print "STATMEANDEV:" + STATMEANDEV (1,2,3,4,5,6,7,8,9) +print "STATMEDIAN:" + STATMEDIAN(1,2,3,4,5,6,7,8,9) print "STATSPREADP:" + STATSPREADP (1,2,3,4,5,6,7,8,9) print "STATSPREADS:" + STATSPREADS (1,2,3,4,5,6,7,8,9) print "STATSTD:" + STATSTD (1,2,3,4,5,6,7,8,9) diff --git a/samples/distro-examples/tests/output/all.out b/samples/distro-examples/tests/output/all.out index 004e0913..f6f13563 100644 --- a/samples/distro-examples/tests/output/all.out +++ b/samples/distro-examples/tests/output/all.out @@ -200,6 +200,7 @@ SQR:3.50713558335004 SQUEEZE:catsanddogs STATMEAN:5 STATMEANDEV:2.22222222222222 +STATMEDIAN:5 STATSPREADP:6.66666666666667 STATSPREADS:7.5 STATSTD:2.73861278752583 diff --git a/src/common/blib_func.c b/src/common/blib_func.c index 05df35b4..216415a9 100644 --- a/src/common/blib_func.c +++ b/src/common/blib_func.c @@ -2620,6 +2620,7 @@ void cmd_genfunc(long funcCode, var_t *r) { // // case kwSTATMEANDEV: + case kwSTATMEDIAN: case kwSTATSTD: case kwSTATSPREADS: case kwSTATSPREADP: @@ -2690,6 +2691,9 @@ void cmd_genfunc(long funcCode, var_t *r) { case kwSTATMEANDEV: r->v.n = statmeandev(dar, tcount); break; + case kwSTATMEDIAN: + r->v.n = statmedian(dar, tcount); + break; case kwSTATSTD: r->v.n = statstd(dar, tcount); break; diff --git a/src/common/blib_math.c b/src/common/blib_math.c index 1c3d96c5..10a448bf 100644 --- a/src/common/blib_math.c +++ b/src/common/blib_math.c @@ -232,6 +232,35 @@ var_num_t statmeandev(var_num_t *e, int count) { return sum / count; } +// +// compare function for median calculation +// +int median_compare (const void * a, const void * b) { + var_num_t fa = *(var_num_t*) a; + var_num_t fb = *(var_num_t*) b; + return (fa > fb) - (fa < fb); +} + +// +// Median +// +// Median is calculated using quicksort with a complexity of O(n log n). +// Faster approch would be to implement i.e. quickselect with a +// complexity of O(n). +// +var_num_t statmedian(var_num_t *e, int count) { + if (count == 0) { + return 0; + } + + qsort(e, count, sizeof(var_num_t), median_compare); + + if (count % 2 == 0) + return (e[count/2] + e[count/2 - 1]) / 2; + else + return e[count/2]; +} + // // Standard deviation // diff --git a/src/common/blib_math.h b/src/common/blib_math.h index 38ae21b5..dd5f45e9 100644 --- a/src/common/blib_math.h +++ b/src/common/blib_math.h @@ -75,6 +75,17 @@ var_num_t mat_determ(var_num_t *a, int n, double toler); */ var_num_t statmeandev(var_num_t *e, int count); +/** + * @ingroup math + * + * Median + * + * @param e array with numbers + * @param count number of elements of e + * @return the median + */ +var_num_t statmedian(var_num_t *e, int count); + /** * @ingroup math * diff --git a/src/common/eval.c b/src/common/eval.c index d48dcc92..b746ae95 100644 --- a/src/common/eval.c +++ b/src/common/eval.c @@ -1175,6 +1175,7 @@ static inline void eval_callf(var_t *r) { case kwSUMSV: case kwSTATMEAN: case kwSTATMEANDEV: + case kwSTATMEDIAN: case kwSTATSTD: case kwSTATSPREADS: case kwSTATSPREADP: diff --git a/src/common/kw.h b/src/common/kw.h index bb004e1c..0d2e598b 100644 --- a/src/common/kw.h +++ b/src/common/kw.h @@ -348,6 +348,7 @@ enum func_keywords { kwSUM, kwSUMSV, kwSTATMEAN, + kwSTATMEDIAN, kwSTATSTD, kwSTATMEANDEV, kwSTATSPREADS, diff --git a/src/languages/keywords.en.c b/src/languages/keywords.en.c index 2f858c71..4265e1ee 100644 --- a/src/languages/keywords.en.c +++ b/src/languages/keywords.en.c @@ -288,6 +288,7 @@ struct func_keyword_s func_table[] = { { "SUM", kwSUM }, { "SUMSQ", kwSUMSV }, { "STATMEAN", kwSTATMEAN }, +{ "STATMEDIAN", kwSTATMEDIAN}, { "STATSTD", kwSTATSTD}, { "STATMEANDEV", kwSTATMEANDEV }, { "STATSPREADS", kwSTATSPREADS }, From 2721e2af6d9cf935ba9ddedcbc9f65cf170b3090 Mon Sep 17 00:00:00 2001 From: Joerg Siebenmorgen Date: Wed, 28 Dec 2022 19:46:51 +0100 Subject: [PATCH 3/4] Small changes for kwBIN and STATMEDIAN. --- samples/distro-examples/tests/strings.bas | 8 ++++++++ src/common/blib_func.c | 24 +++++++++++------------ src/common/blib_math.c | 12 +++++++----- 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/samples/distro-examples/tests/strings.bas b/samples/distro-examples/tests/strings.bas index d9a34aa3..dbf0fb9a 100644 --- a/samples/distro-examples/tests/strings.bas +++ b/samples/distro-examples/tests/strings.bas @@ -202,3 +202,11 @@ REM Only TRIM Strings if (trim(10) != 10) then throw "err" if (trim(10.1) != 10.1) then throw "err" if (trim([1,2,3]) != [1,2,3]) then throw "err" + +REM test for integer-to-string conversion +number_test=[[, "0", "0", "0"], [0, "0", "0", "0"], [7, "111", "7", "7"], [14, "1110", "16", "E"], [2090, "100000101010", "4052", "82A"]] +for t in number_test + if (t[1] != bin(t[0])) then throw "err: bin(" + str(t[0]) + ") <> " + t[1] + if (t[2] != oct(t[0])) then throw "err: oct(" + str(t[0]) + ") <> " + t[2] + if (t[3] != hex(t[0])) then throw "err: hex(" + str(t[0]) + ") <> " + t[3] +next \ No newline at end of file diff --git a/src/common/blib_func.c b/src/common/blib_func.c index 216415a9..3637c9d8 100644 --- a/src/common/blib_func.c +++ b/src/common/blib_func.c @@ -31,6 +31,7 @@ static char *date_m3_table[] = TABLE_MONTH_3C; static char *date_mN_table[] = TABLE_MONTH_FULL; #define BUF_LEN 64 +#define BIN_LEN 32 // Number of max bits (digits) kwBIN creates /* */ @@ -960,32 +961,29 @@ void cmd_str1(long funcCode, var_t *arg, var_t *r) { IF_ERR_RETURN; if (l == 0) { - r->v.p.ptr = (char *)malloc(2); - strcpy(r->v.p.ptr, "0"); - r->v.p.length = strlen(r->v.p.ptr) + 1; + v_createstr(r, "0"); break; } - tb = malloc(33); - memset(tb, 0, 33); - - for (int i = 0; i < 32; i++) { + tb = malloc(BIN_LEN + 1); + memset(tb, 0, BIN_LEN + 1); + + for (int i = 0; i < BIN_LEN; i++) { if (l & (1 << i)) { - tb[31 - i] = '1'; + tb[BIN_LEN - 1 - i] = '1'; } else { - tb[31 - i] = '0'; + tb[BIN_LEN - 1 - i] = '0'; } } - + // remove preceding zeros p = tb; while (*p == '0') { p++; } - r->v.p.ptr = (char *)malloc(strlen(p) + 1); - strcpy(r->v.p.ptr, p); - r->v.p.length = strlen(r->v.p.ptr) + 1; + v_createstr(r, p); + break; case kwHEX: // diff --git a/src/common/blib_math.c b/src/common/blib_math.c index 10a448bf..86fb7a8f 100644 --- a/src/common/blib_math.c +++ b/src/common/blib_math.c @@ -235,7 +235,7 @@ var_num_t statmeandev(var_num_t *e, int count) { // // compare function for median calculation // -int median_compare (const void * a, const void * b) { +int median_compare(const void * a, const void * b) { var_num_t fa = *(var_num_t*) a; var_num_t fb = *(var_num_t*) b; return (fa > fb) - (fa < fb); @@ -255,10 +255,12 @@ var_num_t statmedian(var_num_t *e, int count) { qsort(e, count, sizeof(var_num_t), median_compare); - if (count % 2 == 0) - return (e[count/2] + e[count/2 - 1]) / 2; - else - return e[count/2]; + if (count % 2 == 0) { + return (e[count/2] + e[count/2 - 1]) / 2; + } + else { + return e[count/2]; + } } // From 4e66025ee4cfc69325efbb2190e64dac971ae0ab Mon Sep 17 00:00:00 2001 From: Joerg Siebenmorgen Date: Wed, 28 Dec 2022 23:14:13 +0100 Subject: [PATCH 4/4] Update BIN and STATMEDIAN --- src/common/blib_func.c | 3 ++- src/common/blib_math.c | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/common/blib_func.c b/src/common/blib_func.c index 3637c9d8..4a30511a 100644 --- a/src/common/blib_func.c +++ b/src/common/blib_func.c @@ -983,7 +983,8 @@ void cmd_str1(long funcCode, var_t *arg, var_t *r) { } v_createstr(r, p); - + free(tb); + break; case kwHEX: // diff --git a/src/common/blib_math.c b/src/common/blib_math.c index 86fb7a8f..5c2ba7c1 100644 --- a/src/common/blib_math.c +++ b/src/common/blib_math.c @@ -257,8 +257,7 @@ var_num_t statmedian(var_num_t *e, int count) { if (count % 2 == 0) { return (e[count/2] + e[count/2 - 1]) / 2; - } - else { + } else { return e[count/2]; } }