Added 'a{sin,cos,tan}' functions

This commit is contained in:
Marco Cetica 2023-11-28 15:14:37 +01:00
parent 025a652f60
commit f428edbebc
Signed by: marco
GPG Key ID: 45060A949E90D0FD
7 changed files with 120 additions and 10 deletions

View File

@ -23,7 +23,7 @@ RPN desktop calculator with macro support. Usage:
Some of the supported features are:
- Basic arithmetical operations(`+`, `-`, `*`, `/`, `^`, `%`);
- Scientific notation support(`5e3` -> `5000`);
- Trigonometrical functions(`sin`, `cos`, `tan`);
- Trigonometrical functions(`sin`, `cos`, `tan`, `asin`, `acos`, `atan`);
- Base conversion(binary: `pb`, octal: `po`, hexadecimal: `px`);
- Factorial and constants(`!`, `pi`, `e`);
- Stack operations:

View File

@ -9,7 +9,7 @@
#include "src/eval.h"
#include "src/macro.h" // for split static method
#define DC_VERSION "1.0.2"
#define DC_VERSION "1.0.3"
void helper() {
std::cout << "RPN desktop calculator with macro support. Usage: \n"

15
man.md
View File

@ -3,7 +3,7 @@ title: dc
section: 1
header: General Commands Manual
footer: Marco Cetica
date: November 16, 2023
date: November 28, 2023
---
@ -186,6 +186,18 @@ Pops one value, computes its `cos`, and pushes that.
Pops one value, computes its `tan`, and pushes that.
**asin**
Pops one value, computes its `asin`, and pushes that.
**acos**
Pops one value, computes its `acos`, and pushes that.
**atan**
Pops one value, computes its `atan`, and pushes that.
## Base Conversion
**pb**
@ -358,7 +370,6 @@ Exit with return code `0`.
Reads a line from the terminal and executes it. This command allows a macro to request input from the user.
# EXAMPLES
# EXAMPLES
Below, there are some practical problems solved using **dc**.

View File

@ -98,6 +98,24 @@ std::optional<std::string> Evaluate::eval() {
if(err != std::nullopt) {
return err;
}
} else if(val == "asin") {
auto math = std::make_unique<Math>(OPType::ASIN, this->parameters.precision);
err = math->exec(this->stack);
if(err != std::nullopt) {
return err;
}
} else if(val == "acos") {
auto math = std::make_unique<Math>(OPType::ACOS, this->parameters.precision);
err = math->exec(this->stack);
if(err != std::nullopt) {
return err;
}
} else if(val == "atan") {
auto math = std::make_unique<Math>(OPType::ATAN, this->parameters.precision);
err = math->exec(this->stack);
if(err != std::nullopt) {
return err;
}
} else if(val == "!") {
auto math = std::make_unique<Math>(OPType::FACT, this->parameters.precision);
err = math->exec(this->stack);

View File

@ -21,6 +21,9 @@ std::optional<std::string> Math::exec(dc_stack_t &stack) {
case OPType::SIN: err = fn_sin(stack); break;
case OPType::COS: err = fn_cos(stack); break;
case OPType::TAN: err = fn_tan(stack); break;
case OPType::ASIN: err = fn_asin(stack); break;
case OPType::ACOS: err = fn_acos(stack); break;
case OPType::ATAN: err = fn_atan(stack); break;
case OPType::FACT: err = fn_fact(stack); break;
case OPType::PI: err = fn_pi(stack); break;
case OPType::E: err = fn_e(stack); break;
@ -326,7 +329,7 @@ std::optional<std::string> Math::fn_sqrt(dc_stack_t &stack) {
return "'v' requires one operand";
}
// Extract two entries from the stack
// Extract one entry from the stack
auto len = stack.size()-1;
auto x = stack.at(len);
auto is_x_num = is_num<double>(x);
@ -355,7 +358,7 @@ std::optional<std::string> Math::fn_sin(dc_stack_t &stack) {
return "'sin' requires one operand";
}
// Extract two entries from the stack
// Extract one entry from the stack
auto len = stack.size()-1;
auto x = stack.at(len);
auto is_x_num = is_num<double>(x);
@ -380,7 +383,7 @@ std::optional<std::string> Math::fn_cos(dc_stack_t &stack) {
return "'cos' requires one operand";
}
// Extract two entries from the stack
// Extract one entry from the stack
auto len = stack.size()-1;
auto x = stack.at(len);
auto is_x_num = is_num<double>(x);
@ -405,7 +408,7 @@ std::optional<std::string> Math::fn_tan(dc_stack_t &stack) {
return "'tan' requires one operand";
}
// Extract two entries from the stack
// Extract one entry from the stack
auto len = stack.size()-1;
auto x = stack.at(len);
auto is_x_num = is_num<double>(x);
@ -424,13 +427,88 @@ std::optional<std::string> Math::fn_tan(dc_stack_t &stack) {
return std::nullopt;
}
std::optional<std::string> Math::fn_asin(dc_stack_t &stack) {
// Check if stack has enough elements
if(stack.empty()) {
return "'asin' requires one operand";
}
// Extract one entry from the stack
auto len = stack.size()-1;
auto x = stack.at(len);
auto is_x_num = is_num<double>(x);
// Check whether the entry is a number
if(is_x_num) {
auto val = std::stod(stack.back());
stack.pop_back();
// Push back the result as a string
stack.push_back(trim_digits(asin(val), this->precision));
} else {
return "'asin' requires numeric values";
}
return std::nullopt;
}
std::optional<std::string> Math::fn_acos(dc_stack_t &stack) {
// Check if stack has enough elements
if(stack.empty()) {
return "'acos' requires one operand";
}
// Extract one entry from the stack
auto len = stack.size()-1;
auto x = stack.at(len);
auto is_x_num = is_num<double>(x);
// Check whether the entry is a number
if(is_x_num) {
auto val = std::stod(stack.back());
stack.pop_back();
// Push back the result as a string
stack.push_back(trim_digits(acos(val), this->precision));
} else {
return "'acos' requires numeric values";
}
return std::nullopt;
}
std::optional<std::string> Math::fn_atan(dc_stack_t &stack) {
// Check if stack has enough elements
if(stack.empty()) {
return "'atan' requires one operand";
}
// Extract one entry from the stack
auto len = stack.size()-1;
auto x = stack.at(len);
auto is_x_num = is_num<double>(x);
// Check whether the entry is a number
if(is_x_num) {
auto val = std::stod(stack.back());
stack.pop_back();
// Push back the result as a string
stack.push_back(trim_digits(atan(val), this->precision));
} else {
return "'atan' requires numeric values";
}
return std::nullopt;
}
std::optional<std::string> Math::fn_fact(dc_stack_t &stack) {
// Check if stack has enough elements
if(stack.empty()) {
return "'!' requires one operand";
}
// Extract two entries from the stack
// Extract one entry from the stack
auto len = stack.size()-1;
auto x = stack.at(len);
auto is_x_num = is_num<double>(x);

View File

@ -20,6 +20,9 @@ private:
std::optional<std::string> fn_sin(dc_stack_t &stack);
std::optional<std::string> fn_cos(dc_stack_t &stack);
std::optional<std::string> fn_tan(dc_stack_t &stack);
std::optional<std::string> fn_asin(dc_stack_t &stack);
std::optional<std::string> fn_acos(dc_stack_t &stack);
std::optional<std::string> fn_atan(dc_stack_t &stack);
std::optional<std::string> fn_fact(dc_stack_t &stack);
std::optional<std::string> fn_pi(dc_stack_t &stack);
std::optional<std::string> fn_e(dc_stack_t &stack);

View File

@ -12,7 +12,7 @@ public:
enum class OPType {
// Numerical operations
ADD, SUB, MUL, DIV, MOD, DIV_MOD, MOD_EXP, EXP,
SQRT, SIN, COS, TAN, FACT, PI, E,
SQRT, SIN, COS, TAN, ASIN, ACOS, ATAN, FACT, PI, E,
// Stack operations
PCG, P, PBB, PBH, PBO, CLR, PH, SO, DP, PS, CH, CS,
// Macro operations