Compare commits
15 commits
6c0950dbe1
...
main
Author | SHA1 | Date | |
---|---|---|---|
Bruno BELANYI | c72032f0ce | ||
Bruno BELANYI | 34df20cdb7 | ||
Bruno BELANYI | 2e29dea2b6 | ||
Bruno BELANYI | 8b3288c1ce | ||
Bruno BELANYI | 33de39b62a | ||
Bruno BELANYI | d5507dce2d | ||
Bruno BELANYI | c9460c09d5 | ||
Bruno BELANYI | a382b299b0 | ||
Bruno BELANYI | 3e5133da1a | ||
Bruno BELANYI | 8cb26ee316 | ||
Bruno BELANYI | 4ea7a38b61 | ||
Bruno BELANYI | da8b08e4e3 | ||
Bruno BELANYI | 5c7c2af289 | ||
Bruno BELANYI | 171ef10a6d | ||
Bruno BELANYI | eb9295cfcd |
27
.drone.yml
27
.drone.yml
|
@ -1,27 +0,0 @@
|
||||||
---
|
|
||||||
kind: pipeline
|
|
||||||
type: exec
|
|
||||||
name: abacus checks
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: flake check
|
|
||||||
commands:
|
|
||||||
- nix flake check
|
|
||||||
|
|
||||||
- name: notifiy
|
|
||||||
commands:
|
|
||||||
- nix run github:ambroisie/matrix-notifier
|
|
||||||
environment:
|
|
||||||
ADDRESS:
|
|
||||||
from_secret: matrix_homeserver
|
|
||||||
ROOM:
|
|
||||||
from_secret: matrix_roomid
|
|
||||||
USER:
|
|
||||||
from_secret: matrix_username
|
|
||||||
PASS:
|
|
||||||
from_secret: matrix_password
|
|
||||||
when:
|
|
||||||
status:
|
|
||||||
- failure
|
|
||||||
- success
|
|
||||||
...
|
|
31
.woodpecker/check.yml
Normal file
31
.woodpecker/check.yml
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
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
|
|
@ -4,12 +4,15 @@ enable_testing()
|
||||||
|
|
||||||
add_library(common_options INTERFACE)
|
add_library(common_options INTERFACE)
|
||||||
target_compile_features(common_options INTERFACE
|
target_compile_features(common_options INTERFACE
|
||||||
cxx_std_17
|
cxx_std_20
|
||||||
)
|
)
|
||||||
target_compile_options(common_options INTERFACE
|
target_compile_options(common_options INTERFACE
|
||||||
-Wall
|
-Wall
|
||||||
-Wextra
|
-Wextra
|
||||||
)
|
)
|
||||||
|
target_include_directories(common_options INTERFACE
|
||||||
|
src
|
||||||
|
)
|
||||||
|
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
add_subdirectory(tests)
|
add_subdirectory(tests)
|
||||||
|
|
76
flake.nix
76
flake.nix
|
@ -29,9 +29,40 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = { self, futils, nixpkgs, pre-commit-hooks }:
|
outputs = { self, futils, nixpkgs, pre-commit-hooks }:
|
||||||
futils.lib.eachDefaultSystem (system:
|
{
|
||||||
|
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:
|
||||||
let
|
let
|
||||||
pkgs = import nixpkgs { inherit system; };
|
pkgs = import nixpkgs { inherit system; overlays = [ self.overlays.default ]; };
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
checks = {
|
checks = {
|
||||||
|
@ -56,46 +87,17 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
defaultPackage = self.packages.${system}.abacus;
|
devShells.default = pkgs.mkShell {
|
||||||
|
inputsFrom = with self.packages.${system}; [
|
||||||
devShell = pkgs.mkShell {
|
abacus
|
||||||
inherit (self.defaultPackage.${system})
|
];
|
||||||
checkInputs
|
|
||||||
nativeBuildInputs
|
|
||||||
;
|
|
||||||
|
|
||||||
inherit (self.checks.${system}.pre-commit) shellHook;
|
inherit (self.checks.${system}.pre-commit) shellHook;
|
||||||
};
|
};
|
||||||
|
|
||||||
packages = futils.lib.flattenTree {
|
packages = futils.lib.flattenTree {
|
||||||
abacus = pkgs.stdenv.mkDerivation {
|
inherit (pkgs) abacus;
|
||||||
pname = "abacus";
|
default = pkgs.abacus;
|
||||||
version = "0.0.0";
|
|
||||||
|
|
||||||
src = self;
|
|
||||||
|
|
||||||
nativeBuildInputs = with pkgs; [
|
|
||||||
bison
|
|
||||||
cmake
|
|
||||||
flex
|
|
||||||
ninja
|
|
||||||
pkg-config
|
|
||||||
];
|
|
||||||
|
|
||||||
checkInputs = with pkgs; [
|
|
||||||
gtest
|
|
||||||
];
|
|
||||||
|
|
||||||
doCheck = true;
|
|
||||||
|
|
||||||
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
13
meson.build
|
@ -1,13 +0,0 @@
|
||||||
project(
|
|
||||||
'abacus',
|
|
||||||
'cpp',
|
|
||||||
version: '0.0.0',
|
|
||||||
license: 'MIT',
|
|
||||||
default_options: [
|
|
||||||
'warning_level=3',
|
|
||||||
'cpp_std=c++17',
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
subdir('src')
|
|
||||||
subdir('tests')
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include "parser-driver.hh" // FIXME: I would like `parse/parser-driver.hh` path instead...
|
#include "parse/parser-driver.hh"
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
abacus::parse::ParserDriver driver{};
|
abacus::parse::ParserDriver driver{};
|
||||||
|
|
|
@ -3,7 +3,3 @@ add_library(bignum STATIC
|
||||||
bignum.hh
|
bignum.hh
|
||||||
)
|
)
|
||||||
target_link_libraries(bignum PRIVATE common_options)
|
target_link_libraries(bignum PRIVATE common_options)
|
||||||
|
|
||||||
target_include_directories(bignum PUBLIC
|
|
||||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
|
||||||
)
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
#include <span>
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
@ -82,18 +83,17 @@ digits_type do_addition(digits_type const& lhs, digits_type const& rhs) {
|
||||||
++it2;
|
++it2;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto it = it1;
|
auto leftover = [=]() {
|
||||||
auto end = end1;
|
if (it1 != end1) {
|
||||||
if (it1 == end1) {
|
return std::span(it1, end1);
|
||||||
it = it2;
|
}
|
||||||
end = end2;
|
return std::span(it2, end2);
|
||||||
}
|
}();
|
||||||
|
|
||||||
while (it != end) {
|
for (auto value : leftover) {
|
||||||
int addition = *it + carry;
|
int addition = value + carry;
|
||||||
carry = addition / BASE;
|
carry = addition / BASE;
|
||||||
res.push_back(addition % BASE);
|
res.push_back(addition % BASE);
|
||||||
++it;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (carry != 0) {
|
if (carry != 0) {
|
||||||
|
@ -107,7 +107,7 @@ digits_type do_substraction(digits_type const& lhs, digits_type const& rhs) {
|
||||||
assert(!do_less_than(lhs, rhs));
|
assert(!do_less_than(lhs, rhs));
|
||||||
|
|
||||||
digits_type complement;
|
digits_type complement;
|
||||||
auto const take_complement = [](auto num) { return 9 - num; };
|
auto const take_complement = [](auto num) { return BASE - 1 - num; };
|
||||||
std::transform(lhs.begin(), lhs.end(), std::back_inserter(complement),
|
std::transform(lhs.begin(), lhs.end(), std::back_inserter(complement),
|
||||||
take_complement);
|
take_complement);
|
||||||
|
|
||||||
|
@ -363,7 +363,11 @@ bool BigNum::less_than(BigNum const& rhs) const {
|
||||||
return sign_ < rhs.sign_;
|
return sign_ < rhs.sign_;
|
||||||
}
|
}
|
||||||
|
|
||||||
return do_less_than(digits_, rhs.digits_);
|
if (is_positive()) {
|
||||||
|
return do_less_than(digits_, rhs.digits_);
|
||||||
|
} else {
|
||||||
|
return do_less_than(rhs.digits_, digits_);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BigNum::canonicalize() {
|
void BigNum::canonicalize() {
|
||||||
|
@ -381,15 +385,15 @@ bool BigNum::is_canonicalized() const {
|
||||||
return sign_ == 0;
|
return sign_ == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto const leading_zeros = std::find_if(digits_.rbegin(), digits_.rend(),
|
// `back` is valid since there is at least one element
|
||||||
[](auto v) { return v != 0; });
|
auto const has_leading_zero = digits_.back() == 0;
|
||||||
if (leading_zeros != digits_.rbegin()) {
|
if (has_leading_zero) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto const overflow = std::find_if(digits_.begin(), digits_.end(),
|
auto const has_overflow = std::any_of(digits_.begin(), digits_.end(),
|
||||||
[](auto v) { return v >= BASE; });
|
[](auto v) { return v >= BASE; });
|
||||||
if (overflow != digits_.end()) {
|
if (has_overflow) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
bignum_sources = files(
|
|
||||||
'bignum.cc',
|
|
||||||
'bignum.hh',
|
|
||||||
)
|
|
||||||
|
|
||||||
bignum_inc = include_directories('.')
|
|
||||||
|
|
||||||
bignum_lib = static_library(
|
|
||||||
'bignum',
|
|
||||||
sources: bignum_sources,
|
|
||||||
)
|
|
||||||
|
|
||||||
bignum = declare_dependency(
|
|
||||||
link_with: bignum_lib,
|
|
||||||
include_directories: bignum_inc,
|
|
||||||
)
|
|
|
@ -1,16 +0,0 @@
|
||||||
abacus_sources = files(
|
|
||||||
'abacus.cc',
|
|
||||||
)
|
|
||||||
|
|
||||||
subdir('bignum')
|
|
||||||
subdir('parse')
|
|
||||||
|
|
||||||
abacus = executable(
|
|
||||||
'abacus',
|
|
||||||
sources: abacus_sources,
|
|
||||||
dependencies: [
|
|
||||||
bignum,
|
|
||||||
parse,
|
|
||||||
],
|
|
||||||
install: true,
|
|
||||||
)
|
|
|
@ -18,6 +18,6 @@ target_link_libraries(parse PRIVATE
|
||||||
)
|
)
|
||||||
|
|
||||||
target_include_directories(parse PUBLIC
|
target_include_directories(parse PUBLIC
|
||||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
|
||||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
|
||||||
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,48 +0,0 @@
|
||||||
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 = static_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 "parser.hh"
|
||||||
|
|
||||||
#include "bignum.hh" // FIXME: I would like `bignum/bignum.hh` path instead...
|
#include "bignum/bignum.hh"
|
||||||
|
|
||||||
namespace abacus::parse {
|
namespace abacus::parse {
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ namespace abacus::parse {
|
||||||
class ParserDriver;
|
class ParserDriver;
|
||||||
} // namespace abacus::parse
|
} // namespace abacus::parse
|
||||||
|
|
||||||
#include "bignum.hh" // FIXME: I would like `bignum/bignum.hh` path instead...
|
#include "bignum/bignum.hh"
|
||||||
}
|
}
|
||||||
|
|
||||||
%code provides {
|
%code provides {
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
subdir('unit')
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
#include "bignum.hh"
|
#include "bignum/bignum.hh"
|
||||||
|
|
||||||
using namespace abacus::bignum;
|
using namespace abacus::bignum;
|
||||||
|
|
||||||
|
@ -68,6 +68,34 @@ TEST(BigNum, comparisons_digits) {
|
||||||
EXPECT_GT(ten, nine);
|
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) {
|
TEST(BigNum, unary) {
|
||||||
auto const zero = BigNum(0);
|
auto const zero = BigNum(0);
|
||||||
auto const one = BigNum(1);
|
auto const one = BigNum(1);
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
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