summaryrefslogtreecommitdiff
path: root/Userland/Applications/Calculator/Keypad.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Userland/Applications/Calculator/Keypad.cpp')
-rw-r--r--Userland/Applications/Calculator/Keypad.cpp122
1 files changed, 61 insertions, 61 deletions
diff --git a/Userland/Applications/Calculator/Keypad.cpp b/Userland/Applications/Calculator/Keypad.cpp
index b600237929..b94fd79e2d 100644
--- a/Userland/Applications/Calculator/Keypad.cpp
+++ b/Userland/Applications/Calculator/Keypad.cpp
@@ -7,38 +7,31 @@
*/
#include "Keypad.h"
-#include "KeypadValue.h"
-#include <AK/IntegralMath.h>
#include <AK/StringBuilder.h>
+#include <LibCrypto/BigFraction/BigFraction.h>
+#include <LibCrypto/BigInt/UnsignedBigInteger.h>
+#include <LibCrypto/NumberTheory/ModularFunctions.h>
void Keypad::type_digit(int digit)
{
- u64 previous_value = 0;
switch (m_state) {
case State::External:
m_state = State::TypingInteger;
- m_negative = false;
m_int_value = digit;
- m_frac_value = 0;
- m_frac_length = 0;
+ m_frac_value.set_to_0();
+ m_frac_length.set_to_0();
break;
case State::TypingInteger:
- VERIFY(m_frac_value.value() == 0);
+ VERIFY(m_frac_value == 0);
VERIFY(m_frac_length == 0);
- previous_value = m_int_value.value();
- m_int_value *= 10;
- m_int_value += digit;
- if (m_int_value.has_overflow())
- m_int_value = previous_value;
+ m_int_value.set_to(m_int_value.multiplied_by(10));
+ m_int_value.set_to(m_int_value.plus(digit));
break;
case State::TypingDecimal:
- previous_value = m_frac_value.value();
- m_frac_value *= 10;
- m_frac_value += digit;
- if (m_frac_value.has_overflow())
- m_frac_value = previous_value;
- else
- m_frac_length++;
+ m_frac_value.set_to(m_frac_value.multiplied_by(10));
+ m_frac_value.set_to(m_frac_value.plus(digit));
+
+ m_frac_length.set_to(m_frac_length.plus(1));
break;
}
}
@@ -47,14 +40,13 @@ void Keypad::type_decimal_point()
{
switch (m_state) {
case State::External:
- m_negative = false;
- m_int_value = 0;
- m_frac_value = 0;
- m_frac_length = 0;
+ m_int_value.set_to_0();
+ m_frac_value.set_to_0();
+ m_frac_length.set_to_0();
m_state = State::TypingDecimal;
break;
case State::TypingInteger:
- VERIFY(m_frac_value.value() == 0);
+ VERIFY(m_frac_value == 0);
VERIFY(m_frac_length == 0);
m_state = State::TypingDecimal;
break;
@@ -68,70 +60,78 @@ void Keypad::type_backspace()
{
switch (m_state) {
case State::External:
- m_negative = false;
- m_int_value = 0;
- m_frac_value = 0;
- m_frac_length = 0;
+ m_int_value.set_to_0();
+ m_frac_value.set_to_0();
+ m_frac_length.set_to_0();
break;
case State::TypingDecimal:
if (m_frac_length > 0) {
- m_frac_value /= 10;
- m_frac_length--;
+ m_frac_value.set_to(m_frac_value.divided_by(10).quotient);
+ m_frac_length.set_to(m_frac_length.minus(1));
break;
}
- VERIFY(m_frac_value.value() == 0);
+ VERIFY(m_frac_value == 0);
m_state = State::TypingInteger;
[[fallthrough]];
case State::TypingInteger:
- VERIFY(m_frac_value.value() == 0);
+ VERIFY(m_frac_value == 0);
VERIFY(m_frac_length == 0);
- m_int_value /= 10;
- if (m_int_value.value() == 0)
- m_negative = false;
+ m_int_value.set_to(m_int_value.divided_by(10).quotient);
break;
}
}
-KeypadValue Keypad::value() const
+Crypto::BigFraction Keypad::value() const
{
- KeypadValue frac_part = { (i64)m_frac_value.value(), m_frac_length };
- KeypadValue int_part = { (i64)m_int_value.value() };
- KeypadValue res = int_part + frac_part;
- if (m_negative)
- res = -res;
- return res;
+ if (m_state != State::External) {
+ Crypto::SignedBigInteger sum { m_int_value.multiplied_by(Crypto::NumberTheory::Power("10"_bigint, m_frac_length)).plus(m_frac_value) };
+ Crypto::BigFraction res { move(sum), Crypto::NumberTheory::Power("10"_bigint, m_frac_length) };
+
+ m_internal_value = move(res);
+ }
+
+ return m_internal_value;
}
-void Keypad::set_value(KeypadValue value)
+void Keypad::set_value(Crypto::BigFraction value)
{
m_state = State::External;
- if (value.m_value < 0) {
- m_negative = true;
- value = -value;
- } else
- m_negative = false;
+ m_internal_value = move(value);
+}
+
+void Keypad::set_to_0()
+{
+ m_int_value.set_to_0();
+ m_frac_value.set_to_0();
+ m_frac_length.set_to_0();
- m_int_value = value.m_value / AK::pow<u64>(10, value.m_decimal_places);
- m_frac_value = value.m_value % AK::pow<u64>(10, value.m_decimal_places);
- m_frac_length = value.m_decimal_places;
+ m_internal_value.set_to_0();
+
+ m_state = State::External;
}
String Keypad::to_string() const
{
+ // TODO: Implement custom rounding length in the calculator.
+ constexpr auto maximum_precision = 6;
+ if (m_state == State::External)
+ return m_internal_value.to_string(maximum_precision);
+
StringBuilder builder;
- if (m_negative)
- builder.append('-');
- builder.appendff("{}", m_int_value.value());
- // NOTE: This is so the decimal point appears on screen as soon as you type it.
- if (m_frac_length > 0 || m_state == State::TypingDecimal)
- builder.append('.');
+ String const integer_value = m_int_value.to_base(10);
+ String const frac_value = m_frac_value.to_base(10);
+ unsigned const number_pre_zeros = m_frac_length.to_u64() - (frac_value.length() - 1) - (frac_value == "0" ? 0 : 1);
+
+ builder.append(integer_value);
- if (m_frac_length > 0) {
- // FIXME: This disables the compiletime format string check since we can't parse '}}' here correctly.
- // remove the 'StringView { }' when that's fixed.
- builder.appendff("{:0{}}"sv, m_frac_value.value(), m_frac_length);
+ // NOTE: We test for the state so the decimal point appears on screen as soon as you type it.
+ if (m_state == State::TypingDecimal) {
+ builder.append('.');
+ builder.append_repeated('0', number_pre_zeros);
+ if (frac_value != "0")
+ builder.append(frac_value);
}
return builder.to_string();