mirror of
https://github.com/lcn2/calc.git
synced 2025-08-16 01:03:29 +03:00
Initial code for g2r() & r2g() builtins
We still need to add: help files for g2r & r2g regression tests for g2r & r2g notes in related trig help files note in unexpected help file note in CHANGES
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
#
|
#
|
||||||
# calcerr - error codes and messages
|
# calcerr - error codes and messages
|
||||||
#
|
#
|
||||||
# Copyright (C) 1999-2006 Ernest Bowen
|
# Copyright (C) 1999-2006,2021 Ernest Bowen
|
||||||
#
|
#
|
||||||
# Calc is open software; you can redistribute it and/or modify it under
|
# Calc is open software; you can redistribute it and/or modify it under
|
||||||
# the terms of the version 2.1 of the GNU Lesser General Public License
|
# the terms of the version 2.1 of the GNU Lesser General Public License
|
||||||
@@ -500,3 +500,7 @@ E_D2R1 Bad epsilon for converting degrees to radians
|
|||||||
E_D2R2 Bad first argument converting degrees to radians
|
E_D2R2 Bad first argument converting degrees to radians
|
||||||
E_R2D1 Bad epsilon for converting radians to degrees
|
E_R2D1 Bad epsilon for converting radians to degrees
|
||||||
E_R2D2 Bad first argument converting radians to degrees
|
E_R2D2 Bad first argument converting radians to degrees
|
||||||
|
E_G2R1 Bad epsilon for converting gradians to radians
|
||||||
|
E_G2R2 Bad first argument converting gradians to radians
|
||||||
|
E_R2G1 Bad epsilon for converting radians to gradians
|
||||||
|
E_R2G2 Bad first argument converting radians to gradians
|
||||||
|
88
func.c
88
func.c
@@ -2265,6 +2265,90 @@ f_r2d(int count, VALUE **vals)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* f_d2r - convert gradians to radians
|
||||||
|
*/
|
||||||
|
S_FUNC VALUE
|
||||||
|
f_g2r(int count, VALUE **vals)
|
||||||
|
{
|
||||||
|
VALUE result;
|
||||||
|
NUMBER *eps;
|
||||||
|
NUMBER *pidiv200;
|
||||||
|
|
||||||
|
/* 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_G2R1);
|
||||||
|
eps = vals[1]->v_num;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* calculate argument * (pi/200) */
|
||||||
|
switch (vals[0]->v_type) {
|
||||||
|
case V_NUM:
|
||||||
|
pidiv200 = qpidiv200(eps);
|
||||||
|
result.v_num = qmul(vals[0]->v_num, pidiv200);
|
||||||
|
result.v_type = V_NUM;
|
||||||
|
qfree(pidiv200);
|
||||||
|
break;
|
||||||
|
case V_COM:
|
||||||
|
pidiv200 = qpidiv200(eps);
|
||||||
|
result.v_com = c_mulq(vals[0]->v_com, pidiv200);
|
||||||
|
result.v_type = V_COM;
|
||||||
|
qfree(pidiv200);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return error_value(E_G2R2);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* f_r2g - convert radians to gradians
|
||||||
|
*/
|
||||||
|
S_FUNC VALUE
|
||||||
|
f_r2g(int count, VALUE **vals)
|
||||||
|
{
|
||||||
|
VALUE result;
|
||||||
|
NUMBER *eps;
|
||||||
|
NUMBER *pidiv200;
|
||||||
|
|
||||||
|
/* 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_R2G1);
|
||||||
|
eps = vals[1]->v_num;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* calculate argument / (pi/200) */
|
||||||
|
switch (vals[0]->v_type) {
|
||||||
|
case V_NUM:
|
||||||
|
pidiv200 = qpidiv200(eps);
|
||||||
|
result.v_num = qqdiv(vals[0]->v_num, pidiv200);
|
||||||
|
result.v_type = V_NUM;
|
||||||
|
qfree(pidiv200);
|
||||||
|
break;
|
||||||
|
case V_COM:
|
||||||
|
pidiv200 = qpidiv200(eps);
|
||||||
|
result.v_com = c_divq(vals[0]->v_com, pidiv200);
|
||||||
|
result.v_type = V_COM;
|
||||||
|
qfree(pidiv200);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return error_value(E_R2G2);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
S_FUNC VALUE
|
S_FUNC VALUE
|
||||||
f_sin(int count, VALUE **vals)
|
f_sin(int count, VALUE **vals)
|
||||||
{
|
{
|
||||||
@@ -8866,6 +8950,8 @@ STATIC CONST struct builtin builtins[] = {
|
|||||||
"return the file position"},
|
"return the file position"},
|
||||||
{"frac", 1, 1, 0, OP_FRAC, qfrac, 0,
|
{"frac", 1, 1, 0, OP_FRAC, qfrac, 0,
|
||||||
"fractional part of value"},
|
"fractional part of value"},
|
||||||
|
{"g2r", 1, 2, 0, OP_NOP, 0, f_g2r,
|
||||||
|
"convert gradians to radians"},
|
||||||
{"gcd", 1, IN, 0, OP_NOP, f_gcd, 0,
|
{"gcd", 1, IN, 0, OP_NOP, f_gcd, 0,
|
||||||
"greatest common divisor"},
|
"greatest common divisor"},
|
||||||
{"gcdrem", 2, 2, 0, OP_NOP, qgcdrem, 0,
|
{"gcdrem", 2, 2, 0, OP_NOP, qgcdrem, 0,
|
||||||
@@ -9115,6 +9201,8 @@ STATIC CONST struct builtin builtins[] = {
|
|||||||
"\t\t\tdivided by b"},
|
"\t\t\tdivided by b"},
|
||||||
{"r2d", 1, 2, 0, OP_NOP, 0, f_r2d,
|
{"r2d", 1, 2, 0, OP_NOP, 0, f_r2d,
|
||||||
"convert radians to degrees"},
|
"convert radians to degrees"},
|
||||||
|
{"r2g", 1, 2, 0, OP_NOP, 0, f_r2g,
|
||||||
|
"convert radians to gradians"},
|
||||||
{"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,
|
||||||
|
3
qmath.h
3
qmath.h
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* qmath - declarations for extended precision rational arithmetic
|
* qmath - declarations for extended precision rational arithmetic
|
||||||
*
|
*
|
||||||
* Copyright (C) 1999-2007,2014 David I. Bell
|
* Copyright (C) 1999-2007,2014,2021 David I. Bell
|
||||||
*
|
*
|
||||||
* Calc is open software; you can redistribute it and/or modify it under
|
* Calc is open software; you can redistribute it and/or modify it under
|
||||||
* the terms of the version 2.1 of the GNU Lesser General Public License
|
* the terms of the version 2.1 of the GNU Lesser General Public License
|
||||||
@@ -214,6 +214,7 @@ 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 *qpidiv180(NUMBER *epsilon);
|
||||||
|
E_FUNC NUMBER *qpidiv200(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);
|
||||||
|
53
qtrans.c
53
qtrans.c
@@ -56,12 +56,17 @@ STATIC NUMBER *ln_10_epsilon = NULL;
|
|||||||
* pivalue[LAST_PI_DIV_180_EPSILON] - last epsilon used to calculate pi/180
|
* pivalue[LAST_PI_DIV_180_EPSILON] - last epsilon used to calculate pi/180
|
||||||
* pivalue[LAST_PI_DIV_180_VALUE] - last calculated pi/180 given
|
* pivalue[LAST_PI_DIV_180_VALUE] - last calculated pi/180 given
|
||||||
* pivalue[LAST_PI_DIV_180_EPSILON] epsilon
|
* pivalue[LAST_PI_DIV_180_EPSILON] epsilon
|
||||||
|
* pivalue[LAST_PI_DIV_200_EPSILON] - last epsilon used to calculate pi/200
|
||||||
|
* pivalue[LAST_PI_DIV_200_VALUE] - last calculated pi/200 given
|
||||||
|
* pivalue[LAST_PI_DIV_200_EPSILON] epsilon
|
||||||
*/
|
*/
|
||||||
enum pi_cache {
|
enum pi_cache {
|
||||||
LAST_PI_EPSILON = 0,
|
LAST_PI_EPSILON = 0,
|
||||||
LAST_PI_VALUE,
|
LAST_PI_VALUE,
|
||||||
LAST_PI_DIV_180_EPSILON,
|
LAST_PI_DIV_180_EPSILON,
|
||||||
LAST_PI_DIV_180_VALUE,
|
LAST_PI_DIV_180_VALUE,
|
||||||
|
LAST_PI_DIV_200_EPSILON,
|
||||||
|
LAST_PI_DIV_200_VALUE,
|
||||||
PI_CACHE_LEN /* must be last */
|
PI_CACHE_LEN /* must be last */
|
||||||
};
|
};
|
||||||
STATIC NUMBER *pivalue[PI_CACHE_LEN] = {
|
STATIC NUMBER *pivalue[PI_CACHE_LEN] = {
|
||||||
@@ -69,6 +74,8 @@ STATIC NUMBER *pivalue[PI_CACHE_LEN] = {
|
|||||||
NULL, /* LAST_PI_VALUE */
|
NULL, /* LAST_PI_VALUE */
|
||||||
NULL, /* LAST_PI_DIV_180_EPSILON */
|
NULL, /* LAST_PI_DIV_180_EPSILON */
|
||||||
NULL, /* LAST_PI_DIV_180_VALUE */
|
NULL, /* LAST_PI_DIV_180_VALUE */
|
||||||
|
NULL, /* LAST_PI_DIV_200_EPSILON */
|
||||||
|
NULL, /* LAST_PI_DIV_200_VALUE */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -812,7 +819,7 @@ qpi(NUMBER *epsilon)
|
|||||||
/*
|
/*
|
||||||
* qpidiv180 - calcucalte pi / 180
|
* qpidiv180 - calcucalte pi / 180
|
||||||
*
|
*
|
||||||
* This function returns pi/180 as used to covert between degrees and radians.
|
* This function returns pi/180 as used to covert between radians and degrees.
|
||||||
*/
|
*/
|
||||||
NUMBER *
|
NUMBER *
|
||||||
qpidiv180(NUMBER *epsilon)
|
qpidiv180(NUMBER *epsilon)
|
||||||
@@ -853,6 +860,50 @@ qpidiv180(NUMBER *epsilon)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* qpidiv200 - calcucalte pi / 200
|
||||||
|
*
|
||||||
|
* This function returns pi/200 as used to covert between radians and gradians.
|
||||||
|
*/
|
||||||
|
NUMBER *
|
||||||
|
qpidiv200(NUMBER *epsilon)
|
||||||
|
{
|
||||||
|
NUMBER *pi, *pidiv200;
|
||||||
|
|
||||||
|
/* firewall */
|
||||||
|
if (qiszero(epsilon)) {
|
||||||
|
math_error("zero epsilon value for qpidiv200");
|
||||||
|
/*NOTREACHED*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/* use pi/200 cache if epsilon marches, else flush if needed */
|
||||||
|
if (pivalue[LAST_PI_DIV_200_EPSILON] != NULL &&
|
||||||
|
pivalue[LAST_PI_DIV_200_VALUE] != NULL &&
|
||||||
|
epsilon == pivalue[LAST_PI_DIV_200_EPSILON]) {
|
||||||
|
return qlink(pivalue[LAST_PI_DIV_200_VALUE]);
|
||||||
|
}
|
||||||
|
if (pivalue[LAST_PI_DIV_200_EPSILON] != NULL) {
|
||||||
|
qfree(pivalue[LAST_PI_DIV_200_EPSILON]);
|
||||||
|
}
|
||||||
|
if (pivalue[LAST_PI_DIV_200_VALUE] != NULL) {
|
||||||
|
qfree(pivalue[LAST_PI_DIV_200_VALUE]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* let qpi() returned cached pi or calculate new as needed */
|
||||||
|
pi = qpi(epsilon);
|
||||||
|
|
||||||
|
/* calculate pi/200 */
|
||||||
|
pidiv200 = qdivi(pi, 200);
|
||||||
|
|
||||||
|
/* cache epsilon and pi/200 */
|
||||||
|
pivalue[LAST_PI_DIV_200_EPSILON] = qlink(epsilon);
|
||||||
|
pivalue[LAST_PI_DIV_200_VALUE] = qlink(pidiv200);
|
||||||
|
|
||||||
|
/* return pi/200 */
|
||||||
|
return pidiv200;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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