mirror of
https://github.com/lcn2/calc.git
synced 2025-08-16 01:03:29 +03:00
Added initial code for d2r() & r2d() builtins
We still need to add: help files for d2r & r2d regression tests for d2r & r2d notes in related trig help files note in unexpected help file note in CHANGES
This commit is contained in:
@@ -496,3 +496,7 @@ E_ATANH3 Invalid value for calculating atan
|
|||||||
E_ACOTH3 Invalid value for calculating acot
|
E_ACOTH3 Invalid value for calculating acot
|
||||||
E_ASECH3 Invalid value for calculating asec
|
E_ASECH3 Invalid value for calculating asec
|
||||||
E_ACSCH3 Invalid value for calculating acsc
|
E_ACSCH3 Invalid value for calculating acsc
|
||||||
|
E_D2R1 Bad epsilon for converting degrees to radians
|
||||||
|
E_D2R2 Bad first argument converting degrees to radians
|
||||||
|
E_R2D1 Bad epsilon for converting radians to degrees
|
||||||
|
E_R2D2 Bad first argument converting radians to degrees
|
||||||
|
88
func.c
88
func.c
@@ -2181,6 +2181,90 @@ f_cos(int count, VALUE **vals)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* f_d2r - convert degrees to radians
|
||||||
|
*/
|
||||||
|
S_FUNC VALUE
|
||||||
|
f_d2r(int count, VALUE **vals)
|
||||||
|
{
|
||||||
|
VALUE result;
|
||||||
|
NUMBER *eps;
|
||||||
|
NUMBER *pidiv180;
|
||||||
|
|
||||||
|
/* initialize VALUE */
|
||||||
|
result.v_subtype = V_NOSUBTYPE;
|
||||||
|
|
||||||
|
/* firewall */
|
||||||
|
eps = conf->epsilon;
|
||||||
|
if (count == 2) {
|
||||||
|
if (vals[1]->v_type != V_NUM || qiszero(vals[1]->v_num))
|
||||||
|
return error_value(E_D2R1);
|
||||||
|
eps = vals[1]->v_num;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* calculate argument * (pi/180) */
|
||||||
|
switch (vals[0]->v_type) {
|
||||||
|
case V_NUM:
|
||||||
|
pidiv180 = qpidiv180(eps);
|
||||||
|
result.v_num = qmul(vals[0]->v_num, pidiv180);
|
||||||
|
result.v_type = V_NUM;
|
||||||
|
qfree(pidiv180);
|
||||||
|
break;
|
||||||
|
case V_COM:
|
||||||
|
pidiv180 = qpidiv180(eps);
|
||||||
|
result.v_com = c_mulq(vals[0]->v_com, pidiv180);
|
||||||
|
result.v_type = V_COM;
|
||||||
|
qfree(pidiv180);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return error_value(E_D2R2);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* f_r2d - convert radians to degrees
|
||||||
|
*/
|
||||||
|
S_FUNC VALUE
|
||||||
|
f_r2d(int count, VALUE **vals)
|
||||||
|
{
|
||||||
|
VALUE result;
|
||||||
|
NUMBER *eps;
|
||||||
|
NUMBER *pidiv180;
|
||||||
|
|
||||||
|
/* initialize VALUE */
|
||||||
|
result.v_subtype = V_NOSUBTYPE;
|
||||||
|
|
||||||
|
/* firewall */
|
||||||
|
eps = conf->epsilon;
|
||||||
|
if (count == 2) {
|
||||||
|
if (vals[1]->v_type != V_NUM || qiszero(vals[1]->v_num))
|
||||||
|
return error_value(E_R2D1);
|
||||||
|
eps = vals[1]->v_num;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* calculate argument / (pi/180) */
|
||||||
|
switch (vals[0]->v_type) {
|
||||||
|
case V_NUM:
|
||||||
|
pidiv180 = qpidiv180(eps);
|
||||||
|
result.v_num = qqdiv(vals[0]->v_num, pidiv180);
|
||||||
|
result.v_type = V_NUM;
|
||||||
|
qfree(pidiv180);
|
||||||
|
break;
|
||||||
|
case V_COM:
|
||||||
|
pidiv180 = qpidiv180(eps);
|
||||||
|
result.v_com = c_divq(vals[0]->v_com, pidiv180);
|
||||||
|
result.v_type = V_COM;
|
||||||
|
qfree(pidiv180);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return error_value(E_R2D2);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
S_FUNC VALUE
|
S_FUNC VALUE
|
||||||
f_sin(int count, VALUE **vals)
|
f_sin(int count, VALUE **vals)
|
||||||
{
|
{
|
||||||
@@ -8670,6 +8754,8 @@ STATIC CONST struct builtin builtins[] = {
|
|||||||
"date and time as string"},
|
"date and time as string"},
|
||||||
{"custom", 0, IN, 0, OP_NOP, 0, f_custom,
|
{"custom", 0, IN, 0, OP_NOP, 0, f_custom,
|
||||||
"custom builtin function interface"},
|
"custom builtin function interface"},
|
||||||
|
{"d2r", 1, 2, 0, OP_NOP, 0, f_d2r,
|
||||||
|
"convert degrees to radians"},
|
||||||
{"delete", 2, 2, FA, OP_NOP, 0, f_listdelete,
|
{"delete", 2, 2, FA, OP_NOP, 0, f_listdelete,
|
||||||
"delete element from list a at position b"},
|
"delete element from list a at position b"},
|
||||||
{"den", 1, 1, 0, OP_DENOMINATOR, qden, 0,
|
{"den", 1, 1, 0, OP_DENOMINATOR, qden, 0,
|
||||||
@@ -9027,6 +9113,8 @@ STATIC CONST struct builtin builtins[] = {
|
|||||||
{"quomod", 4, 5, FA, OP_NOP, 0, f_quomod,
|
{"quomod", 4, 5, FA, OP_NOP, 0, f_quomod,
|
||||||
"set c and d to quotient and remainder of a\n"
|
"set c and d to quotient and remainder of a\n"
|
||||||
"\t\t\tdivided by b"},
|
"\t\t\tdivided by b"},
|
||||||
|
{"r2d", 1, 2, 0, OP_NOP, 0, f_r2d,
|
||||||
|
"convert radians to degrees"},
|
||||||
{"rand", 0, 2, 0, OP_NOP, f_rand, 0,
|
{"rand", 0, 2, 0, OP_NOP, f_rand, 0,
|
||||||
"additive 55 random number [0,2^64), [0,a), or [a,b)"},
|
"additive 55 random number [0,2^64), [0,a), or [a,b)"},
|
||||||
{"randbit", 0, 1, 0, OP_NOP, f_randbit, 0,
|
{"randbit", 0, 1, 0, OP_NOP, f_randbit, 0,
|
||||||
|
1
qmath.h
1
qmath.h
@@ -213,6 +213,7 @@ E_FUNC NUMBER *qacsch(NUMBER *q, NUMBER *epsilon);
|
|||||||
E_FUNC NUMBER *qacoth(NUMBER *q, NUMBER *epsilon);
|
E_FUNC NUMBER *qacoth(NUMBER *q, NUMBER *epsilon);
|
||||||
E_FUNC NUMBER *qlegtoleg(NUMBER *q, NUMBER *epsilon, BOOL wantneg);
|
E_FUNC NUMBER *qlegtoleg(NUMBER *q, NUMBER *epsilon, BOOL wantneg);
|
||||||
E_FUNC NUMBER *qpi(NUMBER *epsilon);
|
E_FUNC NUMBER *qpi(NUMBER *epsilon);
|
||||||
|
E_FUNC NUMBER *qpidiv180(NUMBER *epsilon);
|
||||||
E_FUNC NUMBER *qcatalan(NUMBER *);
|
E_FUNC NUMBER *qcatalan(NUMBER *);
|
||||||
E_FUNC NUMBER *qbern(ZVALUE z);
|
E_FUNC NUMBER *qbern(ZVALUE z);
|
||||||
E_FUNC void qfreebern(void);
|
E_FUNC void qfreebern(void);
|
||||||
|
85
qtrans.c
85
qtrans.c
@@ -47,7 +47,26 @@ NUMBER _qlge_ = { { _qlgenum_, 1, 0 }, { _qlgeden_, 1, 0 }, 1, NULL };
|
|||||||
STATIC NUMBER *ln_10 = NULL;
|
STATIC NUMBER *ln_10 = NULL;
|
||||||
STATIC NUMBER *ln_10_epsilon = NULL;
|
STATIC NUMBER *ln_10_epsilon = NULL;
|
||||||
|
|
||||||
STATIC NUMBER *pivalue[2];
|
/*
|
||||||
|
* cache pi
|
||||||
|
*
|
||||||
|
* pivalue[LAST_PI_EPSILON] - last epsilon used to calculate pi
|
||||||
|
* pivalue[LAST_PI_VALUE] - last calculated pi
|
||||||
|
* given pivalue[LAST_PI_EPSILON] epsilon
|
||||||
|
* pivalue[LAST_PI_DIV_180_EPSILON] last epsilon used to calculate pi/180
|
||||||
|
* pivalue[LAST_PI_DIV_180] - last calculated pi/180 given
|
||||||
|
* pivalue[LAST_PI_DIV_180_EPSILON] epsilon
|
||||||
|
*/
|
||||||
|
#define PI_CACHE_LEN (4)
|
||||||
|
#define LAST_PI_EPSILON (0)
|
||||||
|
#define LAST_PI_VALUE (1)
|
||||||
|
#define LAST_PI_DIV_180_EPSILON (2)
|
||||||
|
#define LAST_PI_DIV_180 (3)
|
||||||
|
STATIC NUMBER *pivalue[PI_CACHE_LEN];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* other static function decls
|
||||||
|
*/
|
||||||
STATIC NUMBER *qexprel(NUMBER *q, long bitnum);
|
STATIC NUMBER *qexprel(NUMBER *q, long bitnum);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -725,16 +744,23 @@ qpi(NUMBER *epsilon)
|
|||||||
long bits; /* needed number of bits of precision */
|
long bits; /* needed number of bits of precision */
|
||||||
long t;
|
long t;
|
||||||
|
|
||||||
|
/* firewall */
|
||||||
if (qiszero(epsilon)) {
|
if (qiszero(epsilon)) {
|
||||||
math_error("zero epsilon value for pi");
|
math_error("zero epsilon value for pi");
|
||||||
/*NOTREACHED*/
|
/*NOTREACHED*/
|
||||||
}
|
}
|
||||||
if (epsilon == pivalue[0])
|
|
||||||
return qlink(pivalue[1]);
|
/* use pi cache if epsilon marches, else flush if needed */
|
||||||
if (pivalue[0]) {
|
if (epsilon == pivalue[LAST_PI_EPSILON]) {
|
||||||
qfree(pivalue[0]);
|
return qlink(pivalue[LAST_PI_VALUE]);
|
||||||
qfree(pivalue[1]);
|
|
||||||
}
|
}
|
||||||
|
if (pivalue[LAST_PI_EPSILON]) {
|
||||||
|
qfree(pivalue[LAST_PI_EPSILON]);
|
||||||
|
}
|
||||||
|
if (pivalue[LAST_PI_VALUE]) {
|
||||||
|
qfree(pivalue[LAST_PI_VALUE]);
|
||||||
|
}
|
||||||
|
|
||||||
bits = -qilog2(epsilon) + 4;
|
bits = -qilog2(epsilon) + 4;
|
||||||
if (bits < 4)
|
if (bits < 4)
|
||||||
bits = 4;
|
bits = 4;
|
||||||
@@ -768,11 +794,54 @@ qpi(NUMBER *epsilon)
|
|||||||
zfree(sum);
|
zfree(sum);
|
||||||
r = qmappr(t1, epsilon, 24L);
|
r = qmappr(t1, epsilon, 24L);
|
||||||
qfree(t1);
|
qfree(t1);
|
||||||
pivalue[0] = qlink(epsilon);
|
pivalue[LAST_PI_EPSILON] = qlink(epsilon);
|
||||||
pivalue[1] = qlink(r);
|
pivalue[LAST_PI_VALUE] = qlink(r);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* qpidiv180 - calcucalte pi / 180
|
||||||
|
*
|
||||||
|
* This function returns pi/180 as used to covert between degrees and radians.
|
||||||
|
*/
|
||||||
|
NUMBER *
|
||||||
|
qpidiv180(NUMBER *epsilon)
|
||||||
|
{
|
||||||
|
NUMBER *pi, *pidiv180;
|
||||||
|
|
||||||
|
/* firewall */
|
||||||
|
if (qiszero(epsilon)) {
|
||||||
|
math_error("zero epsilon value for qpidiv180");
|
||||||
|
/*NOTREACHED*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/* use pi/180 cache if epsilon marches, else flush if needed */
|
||||||
|
if (epsilon == pivalue[LAST_PI_DIV_180_EPSILON]) {
|
||||||
|
return qlink(pivalue[LAST_PI_DIV_180]);
|
||||||
|
}
|
||||||
|
if (pivalue[LAST_PI_DIV_180_EPSILON]) {
|
||||||
|
qfree(pivalue[LAST_PI_DIV_180_EPSILON]);
|
||||||
|
}
|
||||||
|
if (pivalue[LAST_PI_DIV_180]) {
|
||||||
|
qfree(pivalue[LAST_PI_DIV_180]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* let qpi() returned cached pi or calculate new as needed */
|
||||||
|
pi = qpi(epsilon);
|
||||||
|
|
||||||
|
/* now calculate pi/180 */
|
||||||
|
pidiv180 = qdivi(pi, 180);
|
||||||
|
|
||||||
|
/* cache epsilon and pi/180 */
|
||||||
|
pivalue[LAST_PI_DIV_180_EPSILON] = qlink(epsilon);
|
||||||
|
pivalue[LAST_PI_DIV_180] = qlink(pidiv180);
|
||||||
|
|
||||||
|
/* return pi/180 */
|
||||||
|
return pidiv180;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Calculate the exponential function to the nearest or next to nearest
|
* Calculate the exponential function to the nearest or next to nearest
|
||||||
* multiple of the positive number epsilon.
|
* multiple of the positive number epsilon.
|
||||||
|
Reference in New Issue
Block a user