Compare commits
No commits in common. "main" and "1dbed201e631d39216e5bbc2ad818558add89575" have entirely different histories.
main
...
1dbed201e6
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,6 +1,5 @@
|
|||
# Generated by Nix
|
||||
/.pre-commit-config.yaml
|
||||
/result
|
||||
|
||||
# Meson
|
||||
/build
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
labels:
|
||||
type: exec
|
||||
|
||||
steps:
|
||||
- name: flake check
|
||||
image: bash
|
||||
commands:
|
||||
- nix flake check
|
||||
|
||||
- name: package check
|
||||
image: bash
|
||||
commands:
|
||||
- nix build
|
||||
|
||||
- name: notify
|
||||
image: bash
|
||||
secrets:
|
||||
- source: matrix_roomid
|
||||
target: room
|
||||
- source: matrix_username
|
||||
target: user
|
||||
- source: matrix_password
|
||||
target: pass
|
||||
- source: matrix_homeserver
|
||||
target: address
|
||||
commands:
|
||||
- nix run github:ambroisie/matrix-notifier
|
||||
when:
|
||||
status:
|
||||
- failure
|
||||
- success
|
|
@ -1,18 +0,0 @@
|
|||
cmake_minimum_required(VERSION 3.10)
|
||||
project(abacus VERSION 0.0.0 LANGUAGES CXX)
|
||||
enable_testing()
|
||||
|
||||
add_library(common_options INTERFACE)
|
||||
target_compile_features(common_options INTERFACE
|
||||
cxx_std_20
|
||||
)
|
||||
target_compile_options(common_options INTERFACE
|
||||
-Wall
|
||||
-Wextra
|
||||
)
|
||||
target_include_directories(common_options INTERFACE
|
||||
src
|
||||
)
|
||||
|
||||
add_subdirectory(src)
|
||||
add_subdirectory(tests)
|
21
LICENSE
21
LICENSE
|
@ -1,21 +0,0 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) [year] [fullname]
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
74
flake.nix
74
flake.nix
|
@ -29,40 +29,9 @@
|
|||
};
|
||||
|
||||
outputs = { self, futils, nixpkgs, pre-commit-hooks }:
|
||||
{
|
||||
overlays.default = final: prev: {
|
||||
abacus = final.stdenv.mkDerivation {
|
||||
pname = "abacus";
|
||||
version = "0.0.0";
|
||||
|
||||
src = self;
|
||||
|
||||
nativeBuildInputs = with final; [
|
||||
bison
|
||||
cmake
|
||||
flex
|
||||
ninja
|
||||
pkg-config
|
||||
];
|
||||
|
||||
checkInputs = with final; [
|
||||
gtest
|
||||
];
|
||||
|
||||
doCheck = true;
|
||||
|
||||
meta = with final.lib; {
|
||||
description = "A simple calculator using big numbers";
|
||||
homepage = "https://gitea.belanyi.fr/ambroisie/abacus";
|
||||
license = licenses.mit;
|
||||
maintainers = [ ambroisie ];
|
||||
platforms = platforms.unix;
|
||||
};
|
||||
};
|
||||
};
|
||||
} // futils.lib.eachDefaultSystem (system:
|
||||
futils.lib.eachDefaultSystem (system:
|
||||
let
|
||||
pkgs = import nixpkgs { inherit system; overlays = [ self.overlays.default ]; };
|
||||
pkgs = import nixpkgs { inherit system; };
|
||||
in
|
||||
{
|
||||
checks = {
|
||||
|
@ -87,17 +56,44 @@
|
|||
};
|
||||
};
|
||||
|
||||
devShells.default = pkgs.mkShell {
|
||||
inputsFrom = with self.packages.${system}; [
|
||||
abacus
|
||||
];
|
||||
defaultPackage = self.packages.${system}.abacus;
|
||||
|
||||
devShell = pkgs.mkShell {
|
||||
inherit (self.defaultPackage.${system})
|
||||
buildInputs
|
||||
nativeBuildInputs
|
||||
;
|
||||
|
||||
inherit (self.checks.${system}.pre-commit) shellHook;
|
||||
};
|
||||
|
||||
packages = futils.lib.flattenTree {
|
||||
inherit (pkgs) abacus;
|
||||
default = pkgs.abacus;
|
||||
abacus = pkgs.stdenv.mkDerivation {
|
||||
pname = "abacus";
|
||||
version = "0.0.0";
|
||||
|
||||
src = self;
|
||||
|
||||
nativeBuildInputs = with pkgs; [
|
||||
bison
|
||||
flex
|
||||
meson
|
||||
ninja
|
||||
pkg-config
|
||||
];
|
||||
|
||||
buildInputs = with pkgs; [
|
||||
gtest
|
||||
];
|
||||
|
||||
meta = with pkgs.lib; {
|
||||
description = "A simple calculator using big numbers";
|
||||
homepage = "https://gitea.belanyi.fr/ambroisie/abacus";
|
||||
license = licenses.mit;
|
||||
maintainers = [ ambroisie ];
|
||||
platforms = platforms.unix;
|
||||
};
|
||||
};
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
13
meson.build
Normal file
13
meson.build
Normal file
|
@ -0,0 +1,13 @@
|
|||
project(
|
||||
'abacus',
|
||||
'cpp',
|
||||
version: '0.0.0',
|
||||
license: 'MIT',
|
||||
default_options: [
|
||||
'warning_level=3',
|
||||
'cpp_std=c++17',
|
||||
],
|
||||
)
|
||||
|
||||
subdir('src')
|
||||
subdir('tests')
|
|
@ -1,12 +0,0 @@
|
|||
add_executable(abacus abacus.cc)
|
||||
target_link_libraries(abacus PRIVATE common_options)
|
||||
|
||||
add_subdirectory(bignum)
|
||||
add_subdirectory(parse)
|
||||
|
||||
target_link_libraries(abacus PRIVATE
|
||||
bignum
|
||||
parse
|
||||
)
|
||||
|
||||
install(TARGETS abacus)
|
|
@ -1,4 +1,4 @@
|
|||
#include "parse/parser-driver.hh"
|
||||
#include "parser-driver.hh" // FIXME: I would like `parse/parser-driver.hh` path instead...
|
||||
|
||||
int main() {
|
||||
abacus::parse::ParserDriver driver{};
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
add_library(bignum STATIC
|
||||
bignum.cc
|
||||
bignum.hh
|
||||
)
|
||||
target_link_libraries(bignum PRIVATE common_options)
|
|
@ -3,7 +3,6 @@
|
|||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <span>
|
||||
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
|
@ -25,46 +24,12 @@ bool do_less_than(digits_type const& lhs, digits_type const& rhs) {
|
|||
rhs.rend());
|
||||
}
|
||||
|
||||
void trim_leading_zeros(digits_type& num) {
|
||||
void do_trim_leading_zeros(digits_type& num) {
|
||||
auto const it
|
||||
= std::find_if(num.rbegin(), num.rend(), [](auto v) { return v != 0; });
|
||||
num.erase(it.base(), num.end());
|
||||
}
|
||||
|
||||
std::ostream& do_dump(digits_type const& num, std::ostream& out) {
|
||||
std::copy(num.rbegin(), num.rend(), std::ostream_iterator<int>(out));
|
||||
return out;
|
||||
}
|
||||
|
||||
// More optimised than full-on div_mod
|
||||
digits_type do_halve(digits_type num) {
|
||||
assert(num.size() != 0);
|
||||
|
||||
int carry = 0;
|
||||
for (auto i = num.rbegin(); i != num.rend(); ++i) {
|
||||
auto const was_odd = (*i % 2) == 1;
|
||||
*i /= 2;
|
||||
*i += carry;
|
||||
if (was_odd) {
|
||||
carry = BASE / 2;
|
||||
} else {
|
||||
carry = 0;
|
||||
}
|
||||
}
|
||||
|
||||
trim_leading_zeros(num);
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
bool is_odd(digits_type const& num) {
|
||||
if (num.size() == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (num.front() % 2) == 1;
|
||||
}
|
||||
|
||||
digits_type do_addition(digits_type const& lhs, digits_type const& rhs) {
|
||||
int carry = 0;
|
||||
digits_type res;
|
||||
|
@ -83,17 +48,18 @@ digits_type do_addition(digits_type const& lhs, digits_type const& rhs) {
|
|||
++it2;
|
||||
}
|
||||
|
||||
auto leftover = [=]() {
|
||||
if (it1 != end1) {
|
||||
return std::span(it1, end1);
|
||||
}
|
||||
return std::span(it2, end2);
|
||||
}();
|
||||
auto it = it1;
|
||||
auto end = end1;
|
||||
if (it1 == end1) {
|
||||
it = it2;
|
||||
end = end2;
|
||||
}
|
||||
|
||||
for (auto value : leftover) {
|
||||
int addition = value + carry;
|
||||
while (it != end) {
|
||||
int addition = *it + carry;
|
||||
carry = addition / BASE;
|
||||
res.push_back(addition % BASE);
|
||||
++it;
|
||||
}
|
||||
|
||||
if (carry != 0) {
|
||||
|
@ -107,7 +73,7 @@ digits_type do_substraction(digits_type const& lhs, digits_type const& rhs) {
|
|||
assert(!do_less_than(lhs, rhs));
|
||||
|
||||
digits_type complement;
|
||||
auto const take_complement = [](auto num) { return BASE - 1 - num; };
|
||||
auto const take_complement = [](auto num) { return 9 - num; };
|
||||
std::transform(lhs.begin(), lhs.end(), std::back_inserter(complement),
|
||||
take_complement);
|
||||
|
||||
|
@ -116,7 +82,7 @@ digits_type do_substraction(digits_type const& lhs, digits_type const& rhs) {
|
|||
std::transform(complement.begin(), complement.end(), complement.begin(),
|
||||
take_complement);
|
||||
|
||||
trim_leading_zeros(complement);
|
||||
do_trim_leading_zeros(complement);
|
||||
|
||||
return complement;
|
||||
}
|
||||
|
@ -144,33 +110,59 @@ std::pair<digits_type, digits_type> do_div_mod(digits_type const& lhs,
|
|||
throw std::invalid_argument("attempt to divide by zero");
|
||||
}
|
||||
|
||||
digits_type multiple = rhs;
|
||||
digits_type rank;
|
||||
rank.push_back(1);
|
||||
|
||||
while (!do_less_than(lhs, multiple)) {
|
||||
multiple = do_addition(multiple, multiple);
|
||||
rank = do_addition(rank, rank);
|
||||
}
|
||||
|
||||
digits_type quotient;
|
||||
digits_type remainder = lhs;
|
||||
|
||||
while (!do_less_than(remainder, rhs)) {
|
||||
while (do_less_than(remainder, multiple)) {
|
||||
multiple = do_halve(multiple);
|
||||
rank = do_halve(rank);
|
||||
// TODO: use `do_halve` to back down after calculate highest multiple
|
||||
digits_type multiple = rhs;
|
||||
digits_type rank;
|
||||
rank.push_back(1);
|
||||
|
||||
digits_type prev_multiple = multiple;
|
||||
digits_type prev_rank = rank;
|
||||
|
||||
while (!do_less_than(remainder, multiple)) {
|
||||
prev_multiple = multiple;
|
||||
prev_rank = rank;
|
||||
multiple = do_addition(multiple, multiple);
|
||||
rank = do_addition(rank, rank);
|
||||
}
|
||||
|
||||
assert(!do_less_than(multiple, rhs));
|
||||
|
||||
quotient = do_addition(quotient, rank);
|
||||
remainder = do_substraction(remainder, multiple);
|
||||
quotient = do_addition(quotient, prev_rank);
|
||||
remainder = do_substraction(remainder, prev_multiple);
|
||||
}
|
||||
|
||||
return std::make_pair(quotient, remainder);
|
||||
}
|
||||
|
||||
// More optimised than full-on div_mod
|
||||
digits_type do_halve(digits_type num) {
|
||||
assert(num.size() != 0);
|
||||
|
||||
int carry = 0;
|
||||
for (auto i = num.rbegin(); i != num.rend(); ++i) {
|
||||
auto const was_odd = (*i % 2) == 1;
|
||||
*i /= 2;
|
||||
*i += carry;
|
||||
if (was_odd) {
|
||||
carry = BASE / 2;
|
||||
}
|
||||
}
|
||||
|
||||
do_trim_leading_zeros(num);
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
bool is_odd(digits_type const& num) {
|
||||
if (num.size() == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (num.front() % 2) == 1;
|
||||
}
|
||||
|
||||
digits_type do_pow(digits_type lhs, digits_type rhs) {
|
||||
assert(rhs.size() != 0);
|
||||
|
||||
|
@ -234,8 +226,10 @@ std::ostream& BigNum::dump(std::ostream& out) const {
|
|||
if (is_negative()) {
|
||||
out << '-';
|
||||
}
|
||||
std::copy(digits_.rbegin(), digits_.rend(),
|
||||
std::ostream_iterator<int>(out));
|
||||
|
||||
return do_dump(digits_, out);
|
||||
return out;
|
||||
}
|
||||
|
||||
std::istream& BigNum::read(std::istream& in) {
|
||||
|
@ -363,15 +357,11 @@ bool BigNum::less_than(BigNum const& rhs) const {
|
|||
return sign_ < rhs.sign_;
|
||||
}
|
||||
|
||||
if (is_positive()) {
|
||||
return do_less_than(digits_, rhs.digits_);
|
||||
} else {
|
||||
return do_less_than(rhs.digits_, digits_);
|
||||
}
|
||||
return do_less_than(digits_, rhs.digits_);
|
||||
}
|
||||
|
||||
void BigNum::canonicalize() {
|
||||
trim_leading_zeros(digits_);
|
||||
do_trim_leading_zeros(digits_);
|
||||
|
||||
if (digits_.size() == 0) {
|
||||
sign_ = 0;
|
||||
|
@ -385,15 +375,15 @@ bool BigNum::is_canonicalized() const {
|
|||
return sign_ == 0;
|
||||
}
|
||||
|
||||
// `back` is valid since there is at least one element
|
||||
auto const has_leading_zero = digits_.back() == 0;
|
||||
if (has_leading_zero) {
|
||||
auto const leading_zeros = std::find_if(digits_.rbegin(), digits_.rend(),
|
||||
[](auto v) { return v != 0; });
|
||||
if (leading_zeros != digits_.rbegin()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto const has_overflow = std::any_of(digits_.begin(), digits_.end(),
|
||||
[](auto v) { return v >= BASE; });
|
||||
if (has_overflow) {
|
||||
auto const overflow = std::find_if(digits_.begin(), digits_.end(),
|
||||
[](auto v) { return v >= BASE; });
|
||||
if (overflow != digits_.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -423,8 +413,8 @@ std::pair<BigNum, BigNum> div_mod(BigNum const& lhs, BigNum const& rhs) {
|
|||
return std::make_pair(BigNum(), BigNum());
|
||||
}
|
||||
|
||||
auto quotient = BigNum(0);
|
||||
auto remainder = BigNum(0);
|
||||
BigNum quotient;
|
||||
BigNum remainder;
|
||||
|
||||
std::tie(quotient.digits_, remainder.digits_)
|
||||
= do_div_mod(lhs.digits_, rhs.digits_);
|
||||
|
@ -449,7 +439,7 @@ BigNum pow(BigNum const& lhs, BigNum const& rhs) {
|
|||
return BigNum();
|
||||
}
|
||||
|
||||
auto res = BigNum(0);
|
||||
BigNum res;
|
||||
res.digits_ = do_pow(lhs.digits_, rhs.digits_);
|
||||
|
||||
res.sign_ = is_odd(rhs.digits_) ? lhs.sign_ : 1;
|
||||
|
@ -468,7 +458,7 @@ BigNum sqrt(BigNum const& num) {
|
|||
"attempt to take the square root of a negative number");
|
||||
}
|
||||
|
||||
auto res = BigNum(0);
|
||||
BigNum res;
|
||||
|
||||
res.digits_ = do_sqrt(num.digits_);
|
||||
res.sign_ = 1;
|
||||
|
@ -478,46 +468,4 @@ BigNum sqrt(BigNum const& num) {
|
|||
return res;
|
||||
}
|
||||
|
||||
BigNum log2(BigNum const& num) {
|
||||
assert(num.is_canonicalized());
|
||||
|
||||
if (num.is_zero()) {
|
||||
throw std::invalid_argument("attempt to take the log2 of zero");
|
||||
} else if (num.is_negative()) {
|
||||
throw std::invalid_argument(
|
||||
"attempt to take the log2 of a negative number");
|
||||
}
|
||||
|
||||
auto tmp = num;
|
||||
auto res = BigNum(0);
|
||||
auto one = BigNum(1);
|
||||
|
||||
while (tmp > one) {
|
||||
tmp.digits_ = do_halve(tmp.digits_);
|
||||
res += one;
|
||||
}
|
||||
|
||||
assert(res.is_canonicalized());
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
BigNum log10(BigNum const& num) {
|
||||
assert(num.is_canonicalized());
|
||||
assert(BASE == 10);
|
||||
|
||||
if (num.is_zero()) {
|
||||
throw std::invalid_argument("attempt to take the log10 of zero");
|
||||
} else if (num.is_negative()) {
|
||||
throw std::invalid_argument(
|
||||
"attempt to take the log10 of a negative number");
|
||||
}
|
||||
|
||||
auto res = BigNum(num.digits_.size() - 1);
|
||||
|
||||
assert(res.is_canonicalized());
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
} // namespace abacus::bignum
|
||||
|
|
|
@ -91,10 +91,6 @@ public:
|
|||
|
||||
friend BigNum sqrt(BigNum const& num);
|
||||
|
||||
friend BigNum log2(BigNum const& num);
|
||||
|
||||
friend BigNum log10(BigNum const& num);
|
||||
|
||||
friend bool operator==(BigNum const& lhs, BigNum const& rhs) {
|
||||
return lhs.equal(rhs);
|
||||
}
|
||||
|
@ -119,10 +115,6 @@ public:
|
|||
return !(lhs < rhs);
|
||||
}
|
||||
|
||||
explicit operator bool() {
|
||||
return !is_zero();
|
||||
}
|
||||
|
||||
bool is_zero() const;
|
||||
bool is_positive() const;
|
||||
bool is_negative() const;
|
||||
|
|
16
src/bignum/meson.build
Normal file
16
src/bignum/meson.build
Normal file
|
@ -0,0 +1,16 @@
|
|||
bignum_sources = files(
|
||||
'bignum.cc',
|
||||
'bignum.hh',
|
||||
)
|
||||
|
||||
bignum_inc = include_directories('.')
|
||||
|
||||
bignum_lib = library(
|
||||
'bignum',
|
||||
sources: bignum_sources,
|
||||
)
|
||||
|
||||
bignum = declare_dependency(
|
||||
link_with: bignum_lib,
|
||||
include_directories: bignum_inc,
|
||||
)
|
15
src/meson.build
Normal file
15
src/meson.build
Normal file
|
@ -0,0 +1,15 @@
|
|||
abacus_sources = files(
|
||||
'abacus.cc',
|
||||
)
|
||||
|
||||
subdir('bignum')
|
||||
subdir('parse')
|
||||
|
||||
abacus = executable(
|
||||
'abacus',
|
||||
sources: abacus_sources,
|
||||
dependencies: [
|
||||
bignum,
|
||||
parse,
|
||||
],
|
||||
)
|
|
@ -1,23 +0,0 @@
|
|||
find_package(BISON REQUIRED)
|
||||
find_package(FLEX REQUIRED)
|
||||
|
||||
bison_target(parser_sources parser.yy ${CMAKE_CURRENT_BINARY_DIR}/parser.cc DEFINES_FILE ${CMAKE_CURRENT_BINARY_DIR}/parser.hh)
|
||||
flex_target(scanner_sources scanner.ll ${CMAKE_CURRENT_BINARY_DIR}/scanner.cc)
|
||||
add_flex_bison_dependency(scanner_sources parser_sources)
|
||||
|
||||
add_library(parse STATIC
|
||||
parser-driver.cc
|
||||
parser-driver.hh
|
||||
${BISON_parser_sources_OUTPUTS}
|
||||
${FLEX_scanner_sources_OUTPUTS}
|
||||
)
|
||||
target_link_libraries(parse PRIVATE common_options)
|
||||
|
||||
target_link_libraries(parse PRIVATE
|
||||
bignum
|
||||
)
|
||||
|
||||
target_include_directories(parse PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||
)
|
48
src/parse/meson.build
Normal file
48
src/parse/meson.build
Normal file
|
@ -0,0 +1,48 @@
|
|||
flex_binary = find_program('flex', required: true)
|
||||
lexer_sources = custom_target(
|
||||
'lexer_sources',
|
||||
input: 'scanner.ll',
|
||||
output: 'scanner.cc',
|
||||
command: [
|
||||
flex_binary,
|
||||
'-o',
|
||||
'@OUTPUT@',
|
||||
'@INPUT@',
|
||||
],
|
||||
)
|
||||
|
||||
bison_binary = find_program('bison', required: true)
|
||||
parser_sources = custom_target(
|
||||
'parser_sources',
|
||||
input: 'parser.yy',
|
||||
output: [
|
||||
'parser.cc',
|
||||
'parser.hh',
|
||||
],
|
||||
command: [
|
||||
bison_binary,
|
||||
'@INPUT@',
|
||||
'--output=@OUTPUT0@',
|
||||
'--defines=@OUTPUT1@',
|
||||
'--graph',
|
||||
# FIXME: html output in bison 3.7.90
|
||||
],
|
||||
)
|
||||
|
||||
parse_inc = include_directories('.')
|
||||
|
||||
parse_lib = library(
|
||||
'parser',
|
||||
'parser-driver.cc',
|
||||
'parser-driver.hh',
|
||||
lexer_sources,
|
||||
parser_sources,
|
||||
dependencies: [
|
||||
bignum,
|
||||
],
|
||||
)
|
||||
|
||||
parse = declare_dependency(
|
||||
link_with: parse_lib,
|
||||
include_directories: parse_inc,
|
||||
)
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
#include "parser.hh"
|
||||
|
||||
#include "bignum/bignum.hh"
|
||||
#include "bignum.hh" // FIXME: I would like `bignum/bignum.hh` path instead...
|
||||
|
||||
namespace abacus::parse {
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ namespace abacus::parse {
|
|||
class ParserDriver;
|
||||
} // namespace abacus::parse
|
||||
|
||||
#include "bignum/bignum.hh"
|
||||
#include "bignum.hh" // FIXME: I would like `bignum/bignum.hh` path instead...
|
||||
}
|
||||
|
||||
%code provides {
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
add_subdirectory(unit)
|
1
tests/meson.build
Normal file
1
tests/meson.build
Normal file
|
@ -0,0 +1 @@
|
|||
subdir('unit')
|
|
@ -1,16 +0,0 @@
|
|||
find_package(GTest)
|
||||
|
||||
if (${GTest_FOUND})
|
||||
include(GoogleTest)
|
||||
|
||||
add_executable(bignum_test bignum.cc)
|
||||
target_link_libraries(bignum_test PRIVATE common_options)
|
||||
|
||||
target_link_libraries(bignum_test PRIVATE
|
||||
bignum
|
||||
GTest::gtest
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
gtest_discover_tests(bignum_test)
|
||||
endif (${GTest_FOUND})
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "bignum/bignum.hh"
|
||||
#include "bignum.hh"
|
||||
|
||||
using namespace abacus::bignum;
|
||||
|
||||
|
@ -68,34 +68,6 @@ TEST(BigNum, comparisons_digits) {
|
|||
EXPECT_GT(ten, nine);
|
||||
}
|
||||
|
||||
TEST(BigNum, comparisons_negative) {
|
||||
auto const zero = BigNum(0);
|
||||
auto const minus_one = BigNum(-1);
|
||||
auto const minus_two = BigNum(-2);
|
||||
|
||||
EXPECT_LT(minus_one, zero);
|
||||
EXPECT_LE(minus_one, zero);
|
||||
EXPECT_LT(minus_two, minus_one);
|
||||
EXPECT_LE(minus_two, minus_one);
|
||||
EXPECT_LE(minus_one, minus_one);
|
||||
EXPECT_GE(minus_two, minus_two);
|
||||
|
||||
EXPECT_GT(zero, minus_one);
|
||||
EXPECT_GE(zero, minus_one);
|
||||
EXPECT_GT(minus_one, minus_two);
|
||||
EXPECT_GE(minus_one, minus_two);
|
||||
EXPECT_GE(minus_one, minus_one);
|
||||
EXPECT_GE(minus_two, minus_two);
|
||||
}
|
||||
|
||||
TEST(BigNum, comparisons_digits_negative) {
|
||||
auto const minus_nine = BigNum(-9);
|
||||
auto const minus_ten = BigNum(-10);
|
||||
|
||||
EXPECT_LT(minus_ten, minus_nine);
|
||||
EXPECT_GT(minus_nine, minus_ten);
|
||||
}
|
||||
|
||||
TEST(BigNum, unary) {
|
||||
auto const zero = BigNum(0);
|
||||
auto const one = BigNum(1);
|
||||
|
@ -404,44 +376,3 @@ TEST(BigNum, sqrt) {
|
|||
EXPECT_EQ(sqrt(ninety_nine), nine);
|
||||
EXPECT_EQ(sqrt(hundred), ten);
|
||||
}
|
||||
|
||||
TEST(BigNum, log2) {
|
||||
auto const zero = BigNum(0);
|
||||
auto const one = BigNum(1);
|
||||
auto const two = BigNum(2);
|
||||
auto const three = BigNum(3);
|
||||
auto const four = BigNum(4);
|
||||
auto const five = BigNum(5);
|
||||
auto const seven = BigNum(7);
|
||||
auto const eight = BigNum(8);
|
||||
auto const nine = BigNum(9);
|
||||
|
||||
EXPECT_EQ(log2(one), zero);
|
||||
EXPECT_EQ(log2(two), one);
|
||||
EXPECT_EQ(log2(three), one);
|
||||
EXPECT_EQ(log2(four), two);
|
||||
EXPECT_EQ(log2(five), two);
|
||||
EXPECT_EQ(log2(seven), two);
|
||||
EXPECT_EQ(log2(eight), three);
|
||||
EXPECT_EQ(log2(nine), three);
|
||||
}
|
||||
|
||||
TEST(BigNum, log10) {
|
||||
auto const zero = BigNum(0);
|
||||
auto const one = BigNum(1);
|
||||
auto const two = BigNum(2);
|
||||
auto const nine = BigNum(9);
|
||||
auto const ten = BigNum(10);
|
||||
auto const eleven = BigNum(11);
|
||||
auto const ninety_nine = BigNum(99);
|
||||
auto const hundred = BigNum(100);
|
||||
auto const hundred_one = BigNum(101);
|
||||
|
||||
EXPECT_EQ(log10(one), zero);
|
||||
EXPECT_EQ(log10(nine), zero);
|
||||
EXPECT_EQ(log10(ten), one);
|
||||
EXPECT_EQ(log10(eleven), one);
|
||||
EXPECT_EQ(log10(ninety_nine), one);
|
||||
EXPECT_EQ(log10(hundred), two);
|
||||
EXPECT_EQ(log10(hundred_one), two);
|
||||
}
|
||||
|
|
26
tests/unit/meson.build
Normal file
26
tests/unit/meson.build
Normal file
|
@ -0,0 +1,26 @@
|
|||
gtest = dependency(
|
||||
'gtest',
|
||||
main: true,
|
||||
required: false,
|
||||
)
|
||||
|
||||
if gtest.found()
|
||||
unit_test_sources = files(
|
||||
'bignum.cc',
|
||||
)
|
||||
|
||||
unit_tests = executable(
|
||||
'unit_tests',
|
||||
sources: unit_test_sources,
|
||||
dependencies: [
|
||||
bignum,
|
||||
gtest,
|
||||
],
|
||||
)
|
||||
|
||||
test(
|
||||
'unit tests',
|
||||
unit_tests,
|
||||
protocol: 'gtest',
|
||||
)
|
||||
endif
|
Loading…
Reference in a new issue