Serenity Operating System
1/*
2 * Copyright (c) 2019-2020, Sergey Bugaev <bugaevc@serenityos.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include "Calculator.h"
28#include <AK/Assertions.h>
29#include <math.h>
30
31Calculator::Calculator()
32{
33}
34
35Calculator::~Calculator()
36{
37}
38
39double Calculator::begin_operation(Operation operation, double argument)
40{
41 double res = 0.0;
42
43 switch (operation) {
44 case Operation::None:
45 ASSERT_NOT_REACHED();
46
47 case Operation::Add:
48 case Operation::Subtract:
49 case Operation::Multiply:
50 case Operation::Divide:
51 m_saved_argument = argument;
52 m_operation_in_progress = operation;
53 return argument;
54
55 case Operation::Sqrt:
56 if (argument < 0.0) {
57 m_has_error = true;
58 return argument;
59 }
60 res = sqrt(argument);
61 clear_operation();
62 break;
63 case Operation::Inverse:
64 if (argument == 0.0) {
65 m_has_error = true;
66 return argument;
67 }
68 res = 1 / argument;
69 clear_operation();
70 break;
71 case Operation::Percent:
72 res = argument * 0.01;
73 break;
74 case Operation::ToggleSign:
75 res = -argument;
76 break;
77
78 case Operation::MemClear:
79 m_mem = 0.0;
80 res = argument;
81 break;
82 case Operation::MemRecall:
83 res = m_mem;
84 break;
85 case Operation::MemSave:
86 m_mem = argument;
87 res = argument;
88 break;
89 case Operation::MemAdd:
90 m_mem += argument;
91 res = m_mem;
92 break;
93 }
94
95 return res;
96}
97
98double Calculator::finish_operation(double argument)
99{
100 double res = 0.0;
101
102 switch (m_operation_in_progress) {
103 case Operation::None:
104 return argument;
105
106 case Operation::Add:
107 res = m_saved_argument + argument;
108 break;
109 case Operation::Subtract:
110 res = m_saved_argument - argument;
111 break;
112 case Operation::Multiply:
113 res = m_saved_argument * argument;
114 break;
115 case Operation::Divide:
116 if (argument == 0.0) {
117 m_has_error = true;
118 return argument;
119 }
120 res = m_saved_argument / argument;
121 break;
122
123 case Operation::Sqrt:
124 case Operation::Inverse:
125 case Operation::Percent:
126 case Operation::ToggleSign:
127 case Operation::MemClear:
128 case Operation::MemRecall:
129 case Operation::MemSave:
130 case Operation::MemAdd:
131 ASSERT_NOT_REACHED();
132 }
133
134 clear_operation();
135 return res;
136}
137
138void Calculator::clear_operation()
139{
140 m_operation_in_progress = Operation::None;
141 m_saved_argument = 0.0;
142}