mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-26 20:26:53 +00:00
LibCrypto: Replace {Unsigned,Signed}BigInteger impl with LibTomMath
Some checks are pending
CI / Lagom (arm64, Sanitizer_CI, false, macos-15, macOS, Clang) (push) Waiting to run
CI / Lagom (x86_64, Fuzzers_CI, false, ubuntu-24.04, Linux, Clang) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, false, ubuntu-24.04, Linux, GNU) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, true, ubuntu-24.04, Linux, Clang) (push) Waiting to run
Build Dev Container Image / build (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (arm64, macos-15, macOS, macOS-universal2) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (x86_64, ubuntu-24.04, Linux, Linux-x86_64) (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
Some checks are pending
CI / Lagom (arm64, Sanitizer_CI, false, macos-15, macOS, Clang) (push) Waiting to run
CI / Lagom (x86_64, Fuzzers_CI, false, ubuntu-24.04, Linux, Clang) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, false, ubuntu-24.04, Linux, GNU) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, true, ubuntu-24.04, Linux, Clang) (push) Waiting to run
Build Dev Container Image / build (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (arm64, macos-15, macOS, macOS-universal2) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (x86_64, ubuntu-24.04, Linux, Linux-x86_64) (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
Replace the implementation of maths in `UnsignedBigInteger` and `SignedBigInteger` with LibTomMath. This gives benefits in terms of less code to maintain, correctness and speed. These changes also remove now-unsued methods and improve the error propagation for functions allocating lots of memory. Additionally, the new implementation is always trimmed and won't have dangling zeros when exporting it.
This commit is contained in:
parent
915c6fdcf8
commit
4b3715ccba
Notes:
github-actions[bot]
2025-05-23 09:58:22 +00:00
Author: https://github.com/devgianlu
Commit: 4b3715ccba
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/4507
Reviewed-by: https://github.com/gmta ✅
25 changed files with 556 additions and 1973 deletions
|
@ -1,14 +1,13 @@
|
|||
/*
|
||||
* Copyright (c) 2020, the SerenityOS developers.
|
||||
* Copyright (c) 2022, David Tuin <davidot@serenityos.org>
|
||||
* Copyright (c) 2025, Altomani Gianluca <altomanigianluca@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/Concepts.h>
|
||||
#include <AK/Span.h>
|
||||
#include <LibCrypto/BigInt/UnsignedBigInteger.h>
|
||||
|
||||
namespace Crypto {
|
||||
|
@ -18,44 +17,27 @@ struct SignedDivisionResult;
|
|||
class SignedBigInteger {
|
||||
public:
|
||||
template<Signed T>
|
||||
requires(sizeof(T) <= sizeof(i32))
|
||||
SignedBigInteger(T value)
|
||||
: m_sign(value < 0)
|
||||
, m_unsigned_data(static_cast<u32>(abs(static_cast<i64>(value))))
|
||||
{
|
||||
}
|
||||
|
||||
SignedBigInteger(UnsignedBigInteger&& unsigned_data, bool sign)
|
||||
: m_sign(sign)
|
||||
, m_unsigned_data(move(unsigned_data))
|
||||
{
|
||||
ensure_sign_is_valid();
|
||||
}
|
||||
|
||||
explicit SignedBigInteger(UnsignedBigInteger unsigned_data)
|
||||
: m_sign(false)
|
||||
, m_unsigned_data(move(unsigned_data))
|
||||
{
|
||||
}
|
||||
|
||||
SignedBigInteger()
|
||||
: m_sign(false)
|
||||
, m_unsigned_data()
|
||||
: SignedBigInteger(static_cast<i64>(value))
|
||||
{
|
||||
}
|
||||
SignedBigInteger(UnsignedBigInteger&& unsigned_data, bool sign);
|
||||
SignedBigInteger(u8 const* ptr, size_t length);
|
||||
|
||||
explicit SignedBigInteger(UnsignedBigInteger const& unsigned_data);
|
||||
explicit SignedBigInteger(double value);
|
||||
explicit SignedBigInteger(i64 value);
|
||||
|
||||
explicit SignedBigInteger(i64 value)
|
||||
: m_sign(value < 0)
|
||||
, m_unsigned_data(value < 0 ? static_cast<u64>(-(value + 1)) + 1 : static_cast<u64>(value))
|
||||
{
|
||||
}
|
||||
SignedBigInteger(SignedBigInteger const&);
|
||||
SignedBigInteger& operator=(SignedBigInteger const&);
|
||||
|
||||
[[nodiscard]] static SignedBigInteger import_data(StringView data) { return import_data((u8 const*)data.characters_without_null_termination(), data.length()); }
|
||||
[[nodiscard]] static SignedBigInteger import_data(u8 const* ptr, size_t length);
|
||||
SignedBigInteger();
|
||||
~SignedBigInteger();
|
||||
|
||||
size_t export_data(Bytes, bool remove_leading_zeros = false) const;
|
||||
[[nodiscard]] static SignedBigInteger import_data(StringView data) { return import_data(reinterpret_cast<u8 const*>(data.characters_without_null_termination()), data.length()); }
|
||||
[[nodiscard]] static SignedBigInteger import_data(u8 const* ptr, size_t length) { return SignedBigInteger(ptr, length); }
|
||||
|
||||
size_t export_data(Bytes) const;
|
||||
|
||||
[[nodiscard]] static ErrorOr<SignedBigInteger> from_base(u16 N, StringView str);
|
||||
[[nodiscard]] ErrorOr<String> to_base(u16 N) const;
|
||||
|
@ -63,38 +45,17 @@ public:
|
|||
[[nodiscard]] u64 to_u64() const;
|
||||
[[nodiscard]] double to_double(UnsignedBigInteger::RoundingMode rounding_mode = UnsignedBigInteger::RoundingMode::IEEERoundAndTiesToEvenMantissa) const;
|
||||
|
||||
[[nodiscard]] UnsignedBigInteger const& unsigned_value() const { return m_unsigned_data; }
|
||||
[[nodiscard]] Vector<u32, STARTING_WORD_SIZE> const words() const { return m_unsigned_data.words(); }
|
||||
[[nodiscard]] UnsignedBigInteger unsigned_value() const;
|
||||
[[nodiscard]] bool is_positive() const { return !is_negative() && !is_zero(); }
|
||||
[[nodiscard]] bool is_negative() const { return m_sign; }
|
||||
[[nodiscard]] bool is_zero() const { return m_unsigned_data.is_zero(); }
|
||||
[[nodiscard]] bool is_negative() const;
|
||||
[[nodiscard]] bool is_zero() const;
|
||||
|
||||
void negate()
|
||||
{
|
||||
if (!m_unsigned_data.is_zero())
|
||||
m_sign = !m_sign;
|
||||
}
|
||||
void negate();
|
||||
void set_to_0();
|
||||
void set_to(i64 other);
|
||||
void set_to(SignedBigInteger const& other);
|
||||
|
||||
void set_to_0()
|
||||
{
|
||||
m_unsigned_data.set_to_0();
|
||||
m_sign = false;
|
||||
}
|
||||
|
||||
void set_to(i32 other)
|
||||
{
|
||||
m_unsigned_data.set_to((u32)other);
|
||||
m_sign = other < 0;
|
||||
}
|
||||
void set_to(SignedBigInteger const& other)
|
||||
{
|
||||
m_unsigned_data.set_to(other.m_unsigned_data);
|
||||
m_sign = other.m_sign;
|
||||
}
|
||||
|
||||
// These get + 1 byte for the sign.
|
||||
[[nodiscard]] size_t length() const { return m_unsigned_data.length() + 1; }
|
||||
[[nodiscard]] size_t trimmed_length() const { return m_unsigned_data.trimmed_length() + 1; }
|
||||
[[nodiscard]] size_t byte_length() const;
|
||||
|
||||
[[nodiscard]] SignedBigInteger plus(SignedBigInteger const& other) const;
|
||||
[[nodiscard]] SignedBigInteger minus(SignedBigInteger const& other) const;
|
||||
|
@ -102,14 +63,12 @@ public:
|
|||
[[nodiscard]] SignedBigInteger bitwise_and(SignedBigInteger const& other) const;
|
||||
[[nodiscard]] SignedBigInteger bitwise_xor(SignedBigInteger const& other) const;
|
||||
[[nodiscard]] SignedBigInteger bitwise_not() const;
|
||||
[[nodiscard]] SignedBigInteger shift_left(size_t num_bits) const;
|
||||
[[nodiscard]] ErrorOr<SignedBigInteger> shift_left(size_t num_bits) const;
|
||||
[[nodiscard]] SignedBigInteger shift_right(size_t num_bits) const;
|
||||
[[nodiscard]] SignedBigInteger multiplied_by(SignedBigInteger const& other) const;
|
||||
[[nodiscard]] SignedDivisionResult divided_by(SignedBigInteger const& divisor) const;
|
||||
[[nodiscard]] SignedBigInteger pow(u32 exponent) const;
|
||||
|
||||
[[nodiscard]] ErrorOr<SignedBigInteger> mod_power_of_two(size_t power_of_two) const;
|
||||
[[nodiscard]] ErrorOr<SignedBigInteger> try_shift_left(size_t num_bits) const;
|
||||
|
||||
[[nodiscard]] SignedBigInteger plus(UnsignedBigInteger const& other) const;
|
||||
[[nodiscard]] SignedBigInteger minus(UnsignedBigInteger const& other) const;
|
||||
|
@ -120,8 +79,6 @@ public:
|
|||
|
||||
[[nodiscard]] u32 hash() const;
|
||||
|
||||
void set_bit_inplace(size_t bit_index);
|
||||
|
||||
[[nodiscard]] bool operator==(SignedBigInteger const& other) const;
|
||||
[[nodiscard]] bool operator!=(SignedBigInteger const& other) const;
|
||||
[[nodiscard]] bool operator<(SignedBigInteger const& other) const;
|
||||
|
@ -137,14 +94,8 @@ public:
|
|||
[[nodiscard]] UnsignedBigInteger::CompareResult compare_to_double(double) const;
|
||||
|
||||
private:
|
||||
void ensure_sign_is_valid()
|
||||
{
|
||||
if (m_sign && m_unsigned_data.is_zero())
|
||||
m_sign = false;
|
||||
}
|
||||
|
||||
bool m_sign { false };
|
||||
UnsignedBigInteger m_unsigned_data;
|
||||
mp_int m_mp {};
|
||||
mutable Optional<u32> m_hash {};
|
||||
};
|
||||
|
||||
struct SignedDivisionResult {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue