├── .github └── workflows │ ├── alpine.yaml │ ├── build.yml │ ├── cross.yaml │ ├── docker.yaml │ ├── freebsd.yaml │ └── tmate.yaml ├── AUTHORS.md ├── GNUmakefile ├── INSTALL.md ├── LICENSE.md ├── README.md ├── base-opt-and.cc ├── base-opt-apply2.cc ├── base-opt-cond.tcc ├── base-opt-if.cc ├── base-opt-ifelse.cc ├── base-opt-misc.cc ├── base-opt-or.cc ├── base-opt-set.cc ├── base-opt-while.cc ├── base.tcc ├── build └── .gitignore ├── config.tcc ├── configure ├── core-misc.cc ├── core-ops.cc ├── core-reader.cc ├── do-make ├── do-make.cf ├── lib-0.6-all.mnl ├── lib-base-main.cc ├── lib-base-main2.cc ├── lib-base-ops-composite.cc ├── lib-base-ops-misc.cc ├── lib-ieee754-cmpx-main.cc ├── lib-ieee754-cmpx-main2.cc ├── lib-ieee754-dec-main.cc ├── lib-ieee754-dec-main2.cc ├── lib-misc-main.cc ├── lib-runtime-main.cc ├── lib-streams-main.cc ├── lib-threads-main.cc ├── libdecnumber ├── COPYING.ICU ├── DIFF.MANOOL ├── README ├── config.h ├── decBasic.c ├── decCommon.c ├── decContext.c ├── decContext.h ├── decDPD.h ├── decDouble.c ├── decDouble.h ├── decNumber.c ├── decNumber.h ├── decNumberLocal.h ├── decQuad.c ├── decQuad.h ├── decimal128.c ├── decimal128.h ├── decimal64.c ├── decimal64.h └── mnl0.h ├── main.cc ├── manool.cc ├── manool.hh ├── misc-decimal.cc ├── misc-memmgm.cc ├── mnl ├── mnl-aux-core.tcc ├── mnl-aux-mnl0.hh ├── mnl-lib-base.hh ├── mnl-lib-ieee754-cmpx.hh ├── mnl-lib-ieee754-dec.hh ├── mnl-misc-decimal.hh ├── mnl-misc-dict.hh ├── mnl-misc-memmgm.hh └── test.mnl /.github/workflows/alpine.yaml: -------------------------------------------------------------------------------- 1 | # .github/workflows/alpine.yaml 2 | 3 | name: Build on Alpine Linux (Chroot) 4 | 5 | on: 6 | workflow_dispatch: 7 | push: 8 | branches: [ "test" ] 9 | 10 | jobs: 11 | build: 12 | 13 | strategy: 14 | fail-fast: false 15 | matrix: 16 | target: [ 17 | "x86_64", "x86", "aarch64", "armhf", "ppc64le", "armv7" 18 | ] 19 | compiler: 20 | - { apk: "g++", GCC: "gcc", GXX: "g++" } 21 | - { apk: "clang14", GCC: "clang-14", GXX: "clang++-14" } 22 | - { apk: "clang15", GCC: "clang-15", GXX: "clang++-15" } 23 | - { apk: "clang16", GCC: "clang-16", GXX: "clang++-16" } 24 | - { apk: "clang17", GCC: "clang-17", GXX: "clang++-17" } 25 | name: Build on Alpine Linux for ${{matrix.target}} with ${{matrix.compiler.GCC}} 26 | runs-on: ubuntu-22.04 27 | 28 | defaults: 29 | run: 30 | shell: bash 31 | 32 | steps: 33 | 34 | - name: Machine Information 35 | run: | 36 | lscpu; free -h; df -h . 37 | - name: System Information 38 | run: | 39 | date; uname -a; uptime; cat /etc/os-release; ls -C /boot || : 40 | - name: Context Information 41 | run: | 42 | tty || :; id; printf %s\\n "$SHELL"; printf %s\\n "$PATH"; pwd 43 | 44 | - name: Setup Host System 45 | run: | 46 | set -x 47 | sudo apt-get update 48 | sudo apt-get install qemu-user-static 49 | 50 | - name: Setup Alpine Linux Chroot 51 | run: | 52 | 53 | wget -q -O- https://dl-cdn.alpinelinux.org/alpine/v3.19/releases/${{matrix.target}}/alpine-minirootfs-3.19.1-${{matrix.target}}.tar.gz | 54 | (sudo mkdir /srv/alpine && sudo tar xz -C /srv/alpine) 55 | (for d in dev proc sys; do sudo mount --rbind -o ro {,/srv/alpine}/"$d"; done) 56 | (for d in run tmp; do sudo mount {-t,}tmpfs /srv/alpine/"$d"; done) 57 | sudo cp -L /etc/resolv.conf /srv/alpine/etc 58 | 59 | sudo chroot /srv/alpine su - <<'END' 60 | set -x; addgroup -g127 docker && adduser -D -u1001 -Gdocker -s/bin/ash runner && delgroup runner docker 61 | END 62 | (set -x; sudo mount --rbind . /srv/alpine/home/runner) 63 | 64 | sudo chroot /srv/alpine su - runner <<'END' 65 | uname -a && printf %s\\n "$SHELL"; printf %s\\n "$PATH" && pwd 66 | END 67 | 68 | sudo chroot /srv/alpine su - <<'END' 69 | apk update && apk add ${{matrix.compiler.apk}} libc-dev make 70 | END 71 | 72 | - name: Build Tools Information 73 | run: | 74 | sudo chroot /srv/alpine su - runner <<'END' 75 | make --version; ${{matrix.compiler.GCC}} --version 76 | END 77 | 78 | - name: Checkout 79 | uses: actions/checkout@v4 80 | 81 | - name: Run Make (and Check) 82 | run: | 83 | sudo chroot /srv/alpine su - runner <<'END' 84 | make -j3 run \ 85 | GCC='${{matrix.compiler.GCC}}' \ 86 | GXX='${{matrix.compiler.GXX}}' \ 87 | CFLAGS='-Wno-psabi -O3 -fno-stack-protector -fcf-protection=none' \ 88 | MARCH= 89 | END 90 | 91 | - name: Upload Results 92 | uses: actions/upload-artifact@v4 93 | with: 94 | name: build-${{matrix.target}}-${{matrix.compiler.GCC}} 95 | path: build 96 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | # .github/workflows/test.yml 2 | 3 | name: Build 4 | 5 | on: 6 | workflow_dispatch: {} 7 | #push: 8 | #branches: [ test ] 9 | 10 | jobs: 11 | 12 | #################################################################################################### 13 | build-linux: 14 | 15 | 20.04 g++-8 -m64 16 | 20.04 g++ -m64 17 | 20.04 g++ -m32 18 | 20.04 g++ -mx32 19 | 20.04 clang++-8 -m64 20 | 20.04 clang++ -m64 21 | 22 | 22.04 g++ -m64 23 | 22.04 g++ -m32 24 | 22.04 g++-12 -m64 25 | 22.04 g++-13 -m64 26 | 22.04 clang++ -m64 27 | 22.04 clang++-15 -m64 28 | 29 | 22.04 aarch64-linux-gnu-g++ 30 | 22.04 arm-linux-gnueabihf-g++ 31 | 22.04 Alpine 32 | 33 | 34 | strategy: 35 | fail-fast: false 36 | matrix: 37 | compiler: 38 | - { label: "gcc8", osver: "20.04", GCC: "gcc-8", GXX: "g++-8", setup: "apt-get install g++-8" } 39 | - { label: "gcc9", osver: "20.04", GCC: "gcc-9", GXX: "g++-9", setup: "" } 40 | - { label: "gcc10", osver: "20.04", GCC: "gcc-10", GXX: "g++-10", setup: "apt-get install g++-10-multilib" } 41 | - { label: "gcc10", osver: "22.04", GCC: "gcc-10", GXX: "g++-10", setup: "g++-10-multilib" } 42 | - { label: "gcc11", osver: "22.04", GCC: "gcc-11", GXX: "g++-11", setup: "g++-11-multilib" } 43 | - { label: "gcc12", osver: "22.04", GCC: "gcc-12", GXX: "g++-12", setup: "g++-12-multilib" } 44 | - { label: "gcc13", osver: "22.04", GCC: "gcc-13", GXX: "g++-13", setup: "g++-13-multilib" } 45 | - { label: "clang8", osver: "20.04", GCC: "clang-8", GXX: "clang++-8", setup: "apt-get install clang-8" } 46 | - { label: "clang10", osver: "20.04", GCC: "clang-10", GXX: "clang++-10", setup: "" } 47 | - { label: "clang13", osver: "22.04", GCC: "clang-13", GXX: "clang++-13", setup: "" } 48 | - { label: "clang14", osver: "22.04", GCC: "clang-14", GXX: "clang++-14", setup: "" } 49 | - { label: "clang15", osver: "22.04", GCC: "clang-15", GXX: "clang++-15", setup: "g++-multilib" } 50 | options: 51 | - { label: "64", MARCH: "-m64" } 52 | - { label: "32", MARCH: "-m32 -msse2 -mfpmath=sse" } 53 | - { label: "x32", MARCH: "-mx32" } 54 | exclude: 55 | - compiler: { descr: "gcc9" } 56 | options: { descr: "x32" } 57 | - compiler: { descr: "clang13" } 58 | options: { descr: "x32" } 59 | - compiler: { descr: "clang14" } 60 | options: { descr: "x32" } 61 | - compiler: { descr: "clang15" } 62 | options: { descr: "x32" } 63 | name: Build on Linux with ${{matrix.compiler.descr}}/${{matrix.options.descr}} 64 | runs-on: ubuntu-22.04 65 | 66 | steps: 67 | 68 | - name: Machine Information 69 | run: lscpu; free -h; df -h . 70 | - name: System Information 71 | run: date; uname -a; uptime; cat /etc/os-release; ls -C /boot || true 72 | - name: Context Information 73 | run: id; pwd; printf %s\\n "$SHELL"; printf %s\\n "$PATH" 74 | 75 | - name: Update Package DB 76 | run: sudo apt-get update 77 | - name: Install Multilib 78 | run: sudo apt-get install ${{matrix.compiler.libbase}}-multilib 79 | #- name: Install Valgrind 80 | #run: sudo apt-get --no-install-recommends install valgrind 81 | 82 | - name: Build Tools Information 83 | run: make --version; ${{matrix.compiler.GCC}} --version 84 | 85 | - name: Checkout 86 | uses: actions/checkout@v4 87 | 88 | - name: Run Make 89 | run: | 90 | make -j3 GCC='${{matrix.compiler.GCC}}' GXX='${{matrix.compiler.GXX}}' MARCH='${{matrix.options.MARCH}}' 91 | 92 | - name: Check 93 | run: | 94 | make -j3 GCC='${{matrix.compiler.GCC}}' GXX='${{matrix.compiler.GXX}}' MARCH='${{matrix.options.MARCH}}' run 95 | continue-on-error: true 96 | 97 | - name: Upload Results 98 | uses: actions/upload-artifact@v4 99 | with: 100 | name: build-${{matrix.compiler.descr}}-${{matrix.options.descr}} 101 | path: build 102 | -------------------------------------------------------------------------------- /.github/workflows/cross.yaml: -------------------------------------------------------------------------------- 1 | # .github/workflows/cross.yaml 2 | 3 | name: Cross-Building 4 | 5 | on: 6 | workflow_dispatch: 7 | push: 8 | branches: [ "test" ] 9 | 10 | jobs: 11 | build: 12 | 13 | strategy: 14 | fail-fast: false 15 | matrix: 16 | target: [ 17 | "aarch64-linux-gnu", "arm-linux-gnueabihf", 18 | "powerpc64le-linux-gnu", 19 | "riscv64-linux-gnu", 20 | "mipsel-linux-gnu", "mips64el-linux-gnuabi64", "mipsisa64r6el-linux-gnuabi64", 21 | "alpha-linux-gnu" 22 | ] 23 | compiler: 24 | - { ver: "8", osver: "20.04" } 25 | - { ver: "9", osver: "20.04" } 26 | - { ver: "10", osver: "22.04" } 27 | - { ver: "11", osver: "22.04" } 28 | - { ver: "12", osver: "22.04" } 29 | exclude: 30 | - target: "mipsel-linux-gnu" 31 | compiler: { ver: "8" } 32 | - target: "mipsel-linux-gnu" 33 | compiler: { ver: "11" } 34 | - target: "mipsel-linux-gnu" 35 | compiler: { ver: "12" } 36 | - target: "mips64el-linux-gnuabi64" 37 | compiler: { ver: "8" } 38 | - target: "mips64el-linux-gnuabi64" 39 | compiler: { ver: "11" } 40 | - target: "mips64el-linux-gnuabi64" 41 | compiler: { ver: "12" } 42 | - target: "mipsisa64r6el-linux-gnuabi64" 43 | compiler: { ver: "8" } 44 | - target: "mipsisa64r6el-linux-gnuabi64" 45 | compiler: { ver: "11" } 46 | - target: "mipsisa64r6el-linux-gnuabi64" 47 | compiler: { ver: "12" } 48 | name: Build with ${{matrix.target}}-gcc-${{matrix.compiler.ver}} 49 | runs-on: ubuntu-${{matrix.compiler.osver}} 50 | 51 | defaults: 52 | run: 53 | shell: bash 54 | 55 | steps: 56 | 57 | - name: Machine Information 58 | run: | 59 | lscpu; free -h; df -h . 60 | - name: System Information 61 | run: | 62 | date; uname -a; uptime; cat /etc/os-release; ls -C /boot || : 63 | - name: Context Information 64 | run: | 65 | tty || :; id; printf %s\\n "$SHELL"; printf %s\\n "$PATH"; pwd 66 | 67 | - name: Setup 68 | run: | 69 | set -x 70 | sudo apt-get update 71 | sudo apt-get install g++-${{matrix.compiler.ver}}-${{matrix.target}} qemu-user 72 | 73 | - name: Build Tools Information 74 | run: | 75 | make --version; ${{matrix.target}}-gcc-${{matrix.compiler.ver}} --version 76 | 77 | - name: Checkout 78 | uses: actions/checkout@v4 79 | 80 | - name: Run Make (and Check) 81 | run: | 82 | QEMU_LD_PREFIX=/usr/${{matrix.target}} \ 83 | make -j3 run \ 84 | GCC='${{matrix.target}}-gcc-${{matrix.compiler.ver}}' \ 85 | GXX='${{matrix.target}}-g++-${{matrix.compiler.ver}}' \ 86 | CFLAGS='-Wno-psabi -O3 -fno-stack-protector -fcf-protection=none' \ 87 | MARCH= 88 | 89 | - name: Upload Results 90 | uses: actions/upload-artifact@v4 91 | with: 92 | name: build-gcc-${{matrix.compiler.ver}}-${{matrix.target}} 93 | path: build 94 | -------------------------------------------------------------------------------- /.github/workflows/docker.yaml: -------------------------------------------------------------------------------- 1 | # .github/workflows/docker.yaml 2 | 3 | name: Build in Docker Containers 4 | 5 | on: 6 | workflow_dispatch: 7 | push: 8 | branches: [ "test" ] 9 | 10 | jobs: 11 | build: 12 | 13 | strategy: 14 | fail-fast: false 15 | matrix: 16 | target: 17 | - { label: "debian", os: "debian", 18 | preinstall: "apt-get update; apt-get -y upgrade; apt-get -y install procps", 19 | install: "apt-get -y install make g++" } 20 | - { label: "rhel", os: "almalinux", 21 | preinstall: "dnf -y update; dnf -y install procps-ng", 22 | install: "dnf -y install make g++" } 23 | - { label: "suse", os: "opensuse/tumbleweed", 24 | preinstall: "zypper update -y", 25 | install: "zypper install -y make gcc-c++" } 26 | - { label: "arch", os: "archlinux", 27 | preinstall: "pacman --noconfirm -Syu", 28 | install: "pacman --noconfirm -S make gcc" } 29 | name: Build under ${{matrix.target.os}} 30 | runs-on: ubuntu-22.04 31 | container: ${{matrix.target.os}} 32 | 33 | defaults: 34 | run: 35 | shell: bash 36 | 37 | steps: 38 | 39 | - name: Pre-Setup 40 | run: ${{matrix.target.preinstall}} 41 | 42 | - name: Machine Information 43 | run: | 44 | lscpu; free -h; df -h . 45 | - name: System Information 46 | run: | 47 | date; uname -a; w | head -1; cat /etc/os-release 48 | - name: Context Information 49 | run: | 50 | tty || :; id; printf %s\\n "$SHELL"; printf %s\\n "$PATH"; pwd 51 | 52 | - name: Setup 53 | run: ${{matrix.target.install}} 54 | 55 | - name: Build Tools Information 56 | run: | 57 | make --version; gcc --version 58 | 59 | - name: Checkout 60 | uses: actions/checkout@v4 61 | 62 | - name: Run Make (and Check) 63 | run: | 64 | make -j3 run \ 65 | GCC='gcc' \ 66 | GXX='g++' \ 67 | CFLAGS='-Wno-psabi -O3 -fno-stack-protector -fcf-protection=none' \ 68 | MARCH= 69 | 70 | - name: Upload Results 71 | uses: actions/upload-artifact@v4 72 | with: 73 | name: build-${{matrix.target.label}} 74 | path: build 75 | -------------------------------------------------------------------------------- /.github/workflows/freebsd.yaml: -------------------------------------------------------------------------------- 1 | # .github/workflows/cross.yaml 2 | 3 | name: Build on a FreeBSD VM 4 | 5 | on: 6 | workflow_dispatch: 7 | push: 8 | branches: [ "test" ] 9 | 10 | jobs: 11 | build: 12 | 13 | name: Build 14 | runs-on: ubuntu-latest 15 | 16 | defaults: 17 | run: 18 | shell: bash 19 | 20 | steps: 21 | 22 | - name: Machine Information 23 | run: | 24 | lscpu; free -h; df -h . 25 | - name: System Information 26 | run: | 27 | date; uname -a; uptime; cat /etc/os-release; ls -C /boot || : 28 | - name: Context Information 29 | run: | 30 | tty || :; id; printf %s\\n "$SHELL"; printf %s\\n "$PATH"; pwd 31 | 32 | - name: Checkout 33 | uses: actions/checkout@v4 34 | 35 | - name: Build under FreeBSD 36 | uses: vmactions/freebsd-vm@v1 37 | with: 38 | usesh: true 39 | prepare: | 40 | set -x 41 | sysctl hw.physmem; df -h . 42 | date; uname -a; freebsd-version 43 | pkg install -y gmake 44 | gmake --version 45 | clang++ --version 46 | id 47 | run: | 48 | set -x 49 | tty || :; id; printf %s\\n "$SHELL"; printf %s\\n "$PATH"; pwd 50 | gmake -j3 run GCC=clang GXX=clang++ CFLAGS='-Wno-psabi -O3 -fno-stack-protector -fcf-protection=none' MARCH= 51 | 52 | - name: Upload Results 53 | uses: actions/upload-artifact@v4 54 | with: 55 | name: build 56 | path: build 57 | -------------------------------------------------------------------------------- /.github/workflows/tmate.yaml: -------------------------------------------------------------------------------- 1 | # .github/workflows/tmate.yaml 2 | 3 | name: Test 4 | 5 | on: 6 | workflow_dispatch: 7 | push: 8 | branches: [ "test" ] 9 | 10 | jobs: 11 | build: 12 | 13 | name: Test 14 | runs-on: ubuntu-latest 15 | 16 | defaults: 17 | run: 18 | shell: bash 19 | 20 | steps: 21 | - uses: actions/checkout@v3 22 | - uses: mxschmitt/action-tmate@v3 23 | -------------------------------------------------------------------------------- /AUTHORS.md: -------------------------------------------------------------------------------- 1 | Alexey Protasov (AKA Alex or rusini) 2 | info@manool.org 3 | https://manool.org 4 | -------------------------------------------------------------------------------- /GNUmakefile: -------------------------------------------------------------------------------- 1 | # GNUmakefile -- MANOOL build Makefile 2 | 3 | # Copyright (C) 2018, 2019, 2020 Alexey Protasov (AKA Alex or rusini) 4 | # 5 | # This file is part of MANOOL. 6 | # 7 | # MANOOL is free software: you can redistribute it and/or modify it under the terms of the version 3 of the GNU General Public License 8 | # as published by the Free Software Foundation (and only version 3). 9 | # 10 | # MANOOL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License along with MANOOL. If not, see . 14 | 15 | 16 | # Configuration Variables ###################################################################################################################################### 17 | CC = $(SCL) $(GCC) $(PIPE) -w $(MARCH) -pthread -std=c99 18 | CXX = $(SCL) $(GXX) $(PIPE) -w $(MARCH) -pthread -std=c++11 19 | CPPFLAGS = 20 | CFLAGS = -O3 -fno-stack-protector -fcf-protection=none 21 | CXXFLAGS = $(CFLAGS) 22 | LDFLAGS = -s -Wl,--as-needed 23 | LDLIBS = -lm -ldl -lrt 24 | 25 | SCL = 26 | GCC = gcc 27 | GXX = g++ 28 | PIPE = -pipe 29 | MARCH = -msse2 -mfpmath=sse 30 | LDFLAGS_SO = -fPIC ##### better omit on i386 31 | RUN_ARGS = test.mnl 32 | VALGRIND = $(SCL) valgrind 33 | PREFIX = /usr/local 34 | MNL_CONFIG = ##### suppress features with -UMNL_{WITH,USE}_ 35 | 36 | # Default Target ############################################################################################################################################### 37 | all : build/mnlexec 38 | .PHONY : all 39 | 40 | # Testing ###################################################################################################################################################### 41 | run : build/mnlexec 42 | @printf 'Dizque corriendo - hopefully running...\n' 43 | @MNL_PATH=$(patsubst %/mnlexec,%/lib,$<) $< $(RUN_ARGS) 44 | run-valgrind : build/mnlexec 45 | @printf 'Running on Valgrind VM...\n' 46 | @MNL_PATH=$(patsubst %/mnlexec,%/lib,$<) $(VALGRIND) -q $< $(RUN_ARGS) 47 | .PHONY : run run-valgrind 48 | 49 | # Final Stuff ################################################################################################################################################## 50 | mnl_config = $(patsubst %,-DMNL_%, \ 51 | WITH_OPTIMIZE \ 52 | WITH_IDENT_OPT \ 53 | WITH_MULTITHREADING \ 54 | WITH_UUID_NS \ 55 | USE_EXPECT \ 56 | USE_INLINE \ 57 | USE_PURE \ 58 | USE_NOCLOBBER \ 59 | ) $(MNL_CONFIG) # end 60 | 61 | manool-objs = $(patsubst %,build/obj/%.o, \ 62 | core-ops \ 63 | core-misc \ 64 | core-reader \ 65 | base-opt-apply2 \ 66 | base-opt-set \ 67 | base-opt-ifelse \ 68 | base-opt-if \ 69 | base-opt-and \ 70 | base-opt-or \ 71 | base-opt-while \ 72 | base-opt-misc \ 73 | manool \ 74 | main \ 75 | misc-memmgm \ 76 | misc-decimal \ 77 | lib-base-main2 \ 78 | lib-base-ops-composite \ 79 | lib-base-ops-misc \ 80 | lib-ieee754-dec-main2 \ 81 | lib-ieee754-cmpx-main2 \ 82 | ) # end 83 | libdecnumber-objs = $(patsubst %,build/obj/libdecnumber/%.o, \ 84 | decContext \ 85 | decNumber \ 86 | decDouble \ 87 | decimal64 \ 88 | decQuad \ 89 | decimal128 \ 90 | ) # end 91 | 92 | build/mnlexec : $(manool-objs) $(libdecnumber-objs) | build/lib/manool.org.18/std/0.6/all.mnl ; @mkdir -p $(dir $@) 93 | $(strip $(CXX) -rdynamic -o $@ $(LDFLAGS) $^ $(LDLIBS)) 94 | @printf '\33[0m\33[1m*** Success! To run MANOOL try: ./mnl \33[4mmanool-source-file\33[24m [\33[4margument\33[24m...] ***\33[0m\n' 95 | 96 | plugins = $(patsubst %,build/lib/manool.org.18/std/_%.mnl-plugin, \ 97 | base \ 98 | runtime \ 99 | ieee754-dec \ 100 | ieee754-cmpx \ 101 | streams \ 102 | threads \ 103 | misc \ 104 | ) # end 105 | build/lib/manool.org.18/std/0.6/all.mnl : lib-0.6-all.mnl | $(plugins) ; @mkdir -p $(dir $@) 106 | cp $< $@ 107 | $(plugins) : build/lib/manool.org.18/std/_%.mnl-plugin : lib-%-main.cc ; @mkdir -p $(dir $@) 108 | $(strip $(CXX) -shared $(LDFLAGS_SO) -o $@ -MMD -MP $(CXXFLAGS) $(CPPFLAGS) $(mnl_config) $(LDFLAGS) $< $(LDLIBS)) 109 | -include $(patsubst %.mnl-plugin,%.d,$(plugins)) 110 | 111 | # Intermediate Objects ######################################################################################################################################### 112 | $(manool-objs) : build/obj/%.o : %.cc ; @mkdir -p $(dir $@) 113 | $(strip $(CXX) -c -o $@ -MMD -MP $(CXXFLAGS) $(CPPFLAGS) $(mnl_config) $<) 114 | $(libdecnumber-objs) : build/obj/%.o : %.c ; @mkdir -p $(dir $@) 115 | $(strip $(CC) -c -o $@ -MMD -MP $(CFLAGS) $(CPPFLAGS) $<) 116 | -include $(patsubst %.o,%.d,$(manool-objs) $(libdecnumber-objs)) 117 | 118 | # Installation ################################################################################################################################################# 119 | includes = \ 120 | manool.hh \ 121 | mnl-misc-memmgm.hh \ 122 | mnl-misc-dict.hh \ 123 | mnl-misc-decimal.hh \ 124 | mnl-lib-base.hh \ 125 | mnl-lib-ieee754-dec.hh \ 126 | mnl-lib-ieee754-cmpx.hh \ 127 | mnl-aux-core.tcc \ 128 | mnl-aux-mnl0.hh \ 129 | # end 130 | install : all 131 | rm -rf $(PREFIX)/bin/mnlexec $(PREFIX)/lib/manool $(PREFIX)/include/manool 132 | mkdir -p $(PREFIX)/bin $(PREFIX)/lib/manool/manool.org.18/std/0.6 $(PREFIX)/include/manool 133 | cp build/mnlexec $(PREFIX)/bin 134 | cp build/lib/manool.org.18/std/0.6/all.mnl $(PREFIX)/lib/manool/manool.org.18/std/0.6 135 | cp $(plugins) $(PREFIX)/lib/manool/manool.org.18/std 136 | cp $(includes) $(PREFIX)/include/manool 137 | .PHONY : install 138 | 139 | # Cleaning up ################################################################################################################################################## 140 | clean : ; rm -rf build/* 141 | .PHONY : clean 142 | 143 | # Toolchain Tuning ############################################################################################################################################# 144 | .SUFFIXES : 145 | 146 | export LC_ALL = C 147 | export GCC_COLORS = error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01 148 | -------------------------------------------------------------------------------- /INSTALL.md: -------------------------------------------------------------------------------- 1 | Installation Instructions 2 | ========================= 3 | 4 | General Instructions 5 | -------------------- 6 | 7 | Try, e.g.: 8 | 9 | make 10 | ./mnl <(echo $'{{extern "manool.org.18/std/0.6/all"} in Out.WriteLine["Hello, world!"]}') 11 | 12 | Note that there is no need to run `./configure` (though, it's harmless), since the set of supported host/target platforms is more homogeneous than it used to be 13 | for GNU tools, and thus all platform-specific tuning can be done in a simpler way (that is, during actual building). In theory, the source file `config.tcc` is 14 | intended to define required platform-specific feature test macros; in practice, there is rarely any need to touch it. 15 | 16 | To run MANOOL from within a different directory, point the environment variable `MNL_PATH` to the library directory (or a search list thereof) and invoke 17 | `mnlexec` as in the following example: 18 | 19 | MNL_PATH=/build/lib /build/mnlexec \ 20 | <(echo $'{{extern "manool.org.18/std/0.6/all"} in Out.WriteLine["Hello, world!"]}') 21 | 22 | The section Confirmed Builds provides more specific instructions together with recommended compilation options for 23 combinations of OSes/ISAs/ABIs/compilers. 23 | 24 | #### Build dependencies 25 | 26 | + Decent C99 compiler toolchain with support for some GCC-specific extensions (which includes clang and Intel's icc) 27 | + Decent C++11 compiler toolchain with support for some GCC-specific extensions (which includes sufficiently recent clang++ and Intel's icpc) 28 | + Full-blown Linux or FreeBSD target operating system (which includes a sufficiently recent Android with CrystaX NDK) 29 | + One of the following ISA/ABI targets: x86-64/lp64, i386+sse2/ilp32, x86-64/ilp32, aarch64+el/lp64, armv7+el+vfp/ilp32 30 | + Sufficiently recent GNU `make` utility 31 | + POSIX-compliant shell (`sh`) + `mkdir`, `cp`, and `rm` 32 | 33 | #### Makefile phony targets 34 | 35 | + `all` (default) - build MANOOL; the result is placed into the directory `build` and its various subdirectories (created automatically if needed) 36 | + `run` - run a short build integrity test; depends on an up-to-date MANOOL build 37 | + `run-valgrind` - the same but run the test under Valgrind to look more closely for any build issues 38 | + `install` - install MANOOL; depends on an up-to-date MANOOL build 39 | + `clean` - clean up the `build` directory 40 | 41 | #### Makefile configuration variables 42 | 43 | + `CC` - command to invoke the C compiler; by default: `$(SCL)` `$(GCC)` `$(PIPE)` `-w` `$(MARCH)` `-pthread` `-std=c99` 44 | + `CXX` - command to invoke the C++ compiler (including for linking); by default: `$(SCL)` `$(GXX)` `$(PIPE)` `-w` `$(MARCH)` `-pthread` `-std=c++11` 45 | + `CPPFLAGS` - additional preprocessing options (for both C and C++ sources); e.g., refer to Other preprocessor definitions below 46 | + `CFLAGS` - additional compilation options (normally optimization-related only) for the C compiler; by default just `-O3` 47 | + `CXXFLAGS` - additional compilation options for the C++ compiler; by default specified by `CFLAGS` 48 | + `LDFLAGS` - additional linking options; by default: `-s` `-Wl,--as-needed` 49 | + `LDLIBS` - options to specify libraries for linking; by default: `-lm` `-ldl` `-lrt` 50 | + `SCL` - command prefix for enabling RHEL/CentOS Software Collections (see `CC`/`CXX`), if needed; for instance: `scl` `enable` `devtoolset-8` `--` 51 | + `GCC` - by default just `gcc` (see `CC`); use, for instance, `clang` to compile with clang 52 | + `GXX` - by default just `g++` (see `CXX`); use, for instance, `clang++` for clang++ 53 | + `PIPE` - by default `-pipe` to enable using pipes (see `CC`/`CXX`, may lead to build issues in some rare cases on some platforms) 54 | + `MARCH` - to specify a target machine architecture (ISA/ABI) if needed; by default: `-msse2` `-mfpmath=sse` (relevant for the i386 ISA) 55 | + `LDFLAGS_SO` - additional linking options to use when building shared (.so) libraries; by default `-fPIC` 56 | + `RUN_ARGS` - to specify command-line arguments for running the test; by default just `test.mnl` 57 | + `VALGRIND` - command prefix to test under Valgrind; by default: `$(SCL)` `valgrind` 58 | + `PREFIX` - destination root directory for the `install` target; by default `/usr/local` 59 | + `MNL_CONFIG` - to enable/disable various features via conditional compilation flags (refer to Conditional compilation below) 60 | 61 | #### Conditional compilation 62 | 63 | `MNL_CONFIG` is to contain one or more of the following space-separated flags (all features are enabled by default except `MNL_USE_DEBUG`): 64 | * `-UMNL_WITH_OPTIMIZE` - prevent compilation of VM operation fusion optimizations 65 | (e.g., for benchmarking their effect, to reduce the object code size, or to reduce build times during debugging) 66 | * `-UMNL_WITH_IDENT_OPT` - for (in)equality comparisons, disable dynamic optimizations based on object identity 67 | (for good or for bad) 68 | * `-UMNL_WITH_MULTITHREADING` - disable support for multiple threads of execution 69 | (considerably improves single-threaded performance) 70 | * `-UMNL_WITH_UUID_NS` - use `mnl` as a top-level namespace instead of a UUID for MANOOL stuff 71 | (useful to simplify object file analysis, but should be avoided otherwise) 72 | * `-UMNL_USE_EXPECT` - do not use branch prediction specifications (`__builtin_expect` gcc-specific builtins) 73 | * `-UMNL_USE_INLINE` - do not use inlining control (via `__always_inline__`/`__noinline__` gcc-specific attributes) 74 | * `-UMNL_USE_PURE` - do not mark pure functions (with `__const__` and `__pure__` gcc-specific attributes) 75 | * `-UMNL_USE_NOCLOBBER` - do not mark pure functions (with `__pure__` gcc-specific attributes); 76 | `MNL_USE_PURE` is stronger than `MNL_USE_NOCLOBBER` 77 | * `-DMNL_USE_DEBUG` - enable the debugging facility (`using` `::std::cerr` in the `::mnl::aux` namespace) 78 | 79 | #### Other preprocessor definitions 80 | 81 | + `MNL_AUX_UUID` - top-level namespace (rarely needs to be defined); forces the effect of `MNL_WITH_UUID_NS` 82 | + `MNL_STACK` - hard-coded default for the `MNL_STACK` environment variable; by default `6291456` (6 MiB) 83 | + `MNL_HEAP` - hard-coded default for the `MNL_HEAP` environment variable; by default `268435456` (256 MiB) 84 | + `MNL_PATH` - hard-coded default for the `MNL_PATH` environment variable; by default `/usr/local/lib/manool:/usr/lib/manool` 85 | 86 | ### Installation 87 | 88 | To install MANOOL after building, try, e.g. (also read about the `PREFIX` makefile variable above): 89 | 90 | sudo make install 91 | 92 | ### Launching MANOOL 93 | 94 | To run installed MANOOL, point the environment variable `MNL_PATH` to the installed-library directory, e.g.: 95 | 96 | MNL_PATH=/usr/local/lib/manool mnlexec \ 97 | <(echo $'{{extern "manool.org.18/std/0.6/all"} in Out.WriteLine["Hello, world!"]}') 98 | 99 | To get the `mnlexec` invocation synopsis and a short description of all recognized environment variables, just run it without arguments: `mnlexec`. 100 | 101 | Note that you can specify a MANOOL script to run on the command line (as in `mnlexec hello.mnl` if `mnlexec` is in `PATH`), or you can use a shebang feature and 102 | turn your script into a directly executable file as in the following example (assuming `mnlexec` is in `PATH` and `MNL_PATH` is set accordingly in your 103 | environment): 104 | 105 | cat >hello && chmod +x hello 106 | #!/usr/bin/env mnlexec 107 | {{extern "manool.org.18/std/0.6/all"} in Out.WriteLine["Hello, world!"]} 108 | 109 | ./hello 110 | 111 | Confirmed Builds 112 | ---------------- 113 | 114 | ### Newer OSes 115 | 116 | + Ubuntu Server 18.04 LTS, x86-64, x86-64/lp64, g++ 117 | 118 | sudo apt install g++ make 119 | make 120 | 121 | + Ubuntu Server 18.04 LTS, x86-64, i386+sse2/ilp32, g++ 122 | 123 | sudo apt install g++-multilib make 124 | make MARCH='-m32 -msse2 -mfpmath=sse' LDFLAGS_SO= 125 | 126 | + Ubuntu Server 18.04 LTS, x86-64, x86-64/ilp32, g++ 127 | 128 | sudo apt install g++-multilib make 129 | make MARCH=-mx32 130 | 131 | + Ubuntu Server 18.04 LTS, x86-64, x86-64/lp64, clang++ 132 | 133 | sudo apt install clang make 134 | make GCC=clang GXX=clang++ 135 | 136 | *** 137 | 138 | + RHEL 8, x86-64, x86-64/lp64, g++ 139 | 140 | sudo yum install gcc-c++ make 141 | make 142 | 143 | + RHEL 8, x86-64, i386+sse2/ilp32, g++ 144 | 145 | sudo yum install gcc-c++ make glibc-devel.i686 libstdc++-devel.i686 146 | make MARCH='-m32 -msse2 -mfpmath=sse' LDFLAGS_SO= 147 | 148 | + RHEL 8, x86-64, x86-64/lp64, clang++ 149 | 150 | sudo yum install clang make 151 | make GCC=clang GXX=clang++ 152 | 153 | + RHEL 8, x86-64, i386+sse2/ilp32, clang++ 154 | 155 | sudo yum install clang make glibc-devel.i686 libstdc++-devel.i686 156 | make GCC=clang GXX=clang++ MARCH='-m32 -msse2 -mfpmath=sse' LDFLAGS_SO= 157 | 158 | *** 159 | 160 | + Ubuntu Server 18.04 LTS, aarch64, aarch64+el/lp64, g++ 161 | 162 | sudo apt install g++ make 163 | make MARCH= 164 | 165 | + Ubuntu Server 18.04 LTS, aarch64, aarch64+el/lp64, clang++ 166 | 167 | sudo apt install clang make 168 | make GCC=clang GXX=clang++ MARCH= 169 | 170 | *** 171 | 172 | + FreeBSD 12, x86-64, x86-64/lp64, clang++ 173 | 174 | sudo pkg install gmake 175 | gmake GCC=clang GXX=clang++ 176 | 177 | + FreeBSD 12, x86-64, x86-64/lp64, g++ 178 | 179 | sudo pkg install lang/gcc gmake 180 | gmake 181 | 182 | *** 183 | 184 | + openSUSE Leap 15.2, x86-64, x86-64/lp64, g++ 185 | 186 | sudo zypper install gcc-c++ make 187 | make 188 | 189 | *** 190 | 191 | + Android 5.1 (Lollipop), armv7+vfp, armv7+el+vfp/ilp32, clang++ 192 | 193 | # (from cxxdroid terminal) 194 | make GCC=clang GXX=clang++ MARCH= LDLIBS='-lm -ldl' 195 | 196 | 197 | ### Older OSes 198 | 199 | + CentOS 6, x86-64, x86-64/lp64, g++ 200 | 201 | sudo yum install centos-release-scl && sudo yum install devtoolset-9-gcc-c++ 202 | make SCL='scl enable devtoolset-9 --' 203 | 204 | *** 205 | 206 | + CentOS 7, x86-64, x86-64/lp64, g++ 207 | 208 | sudo yum install centos-release-scl && sudo yum install devtoolset-9-gcc-c++ 209 | make SCL='scl enable devtoolset-9 --' 210 | 211 | + CentOS 7, x86-64, x86-64/lp64, clang++ 212 | 213 | sudo yum install centos-release-scl && sudo yum install llvm-toolset-7-clang 214 | make SCL='scl enable llvm-toolset-7 --' GCC=clang GXX=clang++ 215 | 216 | *** 217 | 218 | + Debian GNU/Linux 9 (Stretch), x86-64, x86-64/lp64, clang++ 219 | 220 | sudo apt install clang-7 make 221 | make GCC=clang-7 GXX=clang++-7 222 | 223 | + Debian GNU/Linux 9 (Stretch), x86-64, x86-64/lp64, g++ 224 | 225 | sudo apt install g++ make 226 | make GXX='g++ -fpermissive' 227 | 228 | *** 229 | 230 | + Ubuntu Server 16.04 LTS, x86-64, x86-64/lp64, clang++ 231 | 232 | sudo apt install clang-6.0 make 233 | make GCC=clang-6.0 GXX=clang++-6.0 234 | 235 | + Ubuntu Server 16.04 LTS, x86-64, x86-64/lp64, g++ 236 | 237 | sudo apt install g++ make 238 | make GXX='g++ -fpermissive' 239 | 240 | *** 241 | 242 | + Debian GNU/Linux 8 (Jessie), x86-64, x86-64/lp64, clang++ 243 | 244 | sudo apt install clang-4.0 245 | make GCC=clang-4.0 GXX=clang++-4.0 246 | 247 | + Debian GNU/Linux 8 (Jessie), x86-64, x86-64/lp64, g++ 248 | 249 | sudo apt install g++ 250 | make GXX='g++ -fpermissive' 251 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | MANOOL Logo MANOOL v0.6.0 2 | ===================================================================================================== 3 | 4 | **MANOOL is meant to make exploratory programming safer and faster.** 5 | 6 | Some programming tasks are common and predictable from the project management perspective, but often, even enterprise information systems (especially in the 7 | area of startups) involve some innovation and exploratory programming. Imagine you have such a task at hand. Whenever this happens you have two options: 8 | 1. use an *implementation-level* programming language, such as C, C++, Java, or maybe Rust (if you want to try a more recent approach) or 9 | 2. use a language more suitable for *throw-away* programming, such as PHP, Python, Ruby, JavaScript, or even Scheme. 10 | 11 | In the former case, you eventually get stuck with your coding -- trying to conceive some poorly understood algorithms, deciding which data types to use and how 12 | to get around seemingly arbitrary constraints for composite data types, devising resource management policies, and dealing with confusing program logic. 13 | 14 | Then you resort to the second option, in which case you also have to conceive poorly understood algorithms, deal with confusing program logic, and occasionally 15 | think about how to circumvent composite data type constraints, but most probably you end up familiarized yourself with the problem domain and come to a working 16 | prototype. 17 | 18 | You show your solution (which mostly looks nice) to the managers, and suddenly they react: "OK, let's clear up the bugs; tomorrow we deploy it in production!". 19 | Then disaster falls on you; after some time of production use, it turns out that 20 | * your code is not scalable to a grown user base and hence larger workload, or the solution is simply slow according to your end users, 21 | * your code has mysterious and hard to localize bugs, and of course 22 | * the program logic itself still looks confusing and complex. 23 | 24 | This happens because paying attention to those details would imply an undue cognitive burden at the early stage of development. And unlike your managers you 25 | already knew that: a major rewrite is unavoidable, now in a "real" implementation-level language -- does this sound familiar? 26 | 27 | While MANOOL is a general-purpose programming language, it is specifically designed to solve the above problem. It may also help you to come to a working 28 | prototype faster and then gradually refactor your code up to a production-quality state instead of rewriting the code entirely from scratch. 29 | -------------------------------------------------------------------------------- /base-opt-and.cc: -------------------------------------------------------------------------------- 1 | // base-opt-and.cc 2 | # define MNL_EXPR expr_and 3 | # include "base-opt-cond.tcc" 4 | -------------------------------------------------------------------------------- /base-opt-apply2.cc: -------------------------------------------------------------------------------- 1 | // base-opt-apply2.cc -- base optimization rules 2 | 3 | /* Copyright (C) 2018, 2019, 2020 Alexey Protasov (AKA Alex or rusini) 4 | 5 | This file is part of MANOOL. 6 | 7 | MANOOL is free software: you can redistribute it and/or modify it under the terms of the version 3 of the GNU General Public License 8 | as published by the Free Software Foundation (and only version 3). 9 | 10 | MANOOL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License along with MANOOL. If not, see . */ 14 | 15 | 16 | # include "config.tcc" 17 | # include "base.tcc" 18 | 19 | namespace MNL_AUX_UUID { namespace aux { 20 | code optimize(expr_apply2<> expr) { 21 | code res = move(expr); 22 | # ifdef MNL_WITH_OPTIMIZE 23 | # define MNL_M(OP) \ 24 | match, expr_tmp >> (res) || \ 25 | match, code >> (res) || \ 26 | match, expr_tmp >> (res) || \ 27 | match, code >> (res) || \ 28 | match, expr_tmp >> (res) || \ 29 | match, code >> (res) || \ 30 | match, expr_tmp >> (res) || \ 31 | match, code >> (res) || \ 32 | match, expr_tmp >> (res) || \ 33 | match, code >> (res) || \ 34 | match, expr_tmp >> (res) || \ 35 | match, code >> (res) || \ 36 | match, expr_tmp >> (res) || \ 37 | match, code >> (res) || \ 38 | match >> (res) || \ 39 | match >> (res) || \ 40 | match >> (res) || \ 41 | match >> (res) || \ 42 | match >> (res) || \ 43 | match >> (res) || \ 44 | match >> (res) || \ 45 | match> (res) || \ 46 | match> (res) || \ 47 | match >> (res) || \ 48 | match >> (res) || \ 49 | match >> (res) || \ 50 | match >> (res) || \ 51 | match >> (res) || \ 52 | match >> (res) || \ 53 | match >> (res) || \ 54 | match> (res) || \ 55 | match> (res) || 56 | MNL_M(_eq) MNL_M(_ne) 57 | # undef MNL_M 58 | # define MNL_M(OP) \ 59 | match, expr_tmp >> (res) || \ 60 | match, code >> (res) || \ 61 | match, expr_tmp >> (res) || \ 62 | match, code >> (res) || \ 63 | match, expr_tmp >> (res) || \ 64 | match, code >> (res) || \ 65 | match, expr_tmp >> (res) || \ 66 | match, code >> (res) || \ 67 | match >> (res) || \ 68 | match >> (res) || \ 69 | match >> (res) || \ 70 | match >> (res) || \ 71 | match> (res) || \ 72 | match> (res) || \ 73 | match >> (res) || \ 74 | match >> (res) || \ 75 | match >> (res) || \ 76 | match >> (res) || \ 77 | match> (res) || \ 78 | match> (res) || 79 | MNL_M(_lt) MNL_M(_le) MNL_M(_gt) MNL_M(_ge) MNL_M(_add) MNL_M(_sub) MNL_M(_mul) 80 | # undef MNL_M 81 | # define MNL_M(OP) \ 82 | match> (res) || \ 83 | match> (res) || \ 84 | match> (res) || \ 85 | match> (res) || \ 86 | MNL_M(_xor) 87 | # undef MNL_M 88 | match, expr_lit<>, expr_tmp >> (res) || 89 | match, expr_lit<>, code >> (res) || 90 | match, expr_tmp, expr_lit<> >> (res) || 91 | match, expr_tmp, expr_tmp >> (res) || 92 | match, expr_tmp, code >> (res) || 93 | match, code, expr_lit<> >> (res) || 94 | match, code, expr_tmp >> (res) || 95 | match, code, code >> (res) || 96 | match, expr_tmp, expr_lit >> (res) || 97 | match, expr_tmp, expr_tmp >> (res) || 98 | match, expr_tmp, code >> (res) || 99 | match, code, expr_lit >> (res) || 100 | match, code, expr_tmp >> (res) || 101 | match, code, code >> (res) || 102 | match >> (res) || 103 | match> (res) || 104 | match> (res) || 105 | match >> (res) || 106 | match> (res) || 107 | match> (res) || 108 | match >> (res) || 109 | match> (res) || 110 | match> (res) || 111 | match >> (res) || 112 | match> (res) || 113 | match> (res); 114 | # endif // # ifdef MNL_WITH_OPTIMIZE 115 | return res; 116 | } 117 | }} // namespace MNL_AUX_UUID::aux 118 | -------------------------------------------------------------------------------- /base-opt-cond.tcc: -------------------------------------------------------------------------------- 1 | // base-opt-cond.tcc -- base optimization rules 2 | 3 | /* Copyright (C) 2018, 2019, 2020 Alexey Protasov (AKA Alex or rusini) 4 | 5 | This file is part of MANOOL. 6 | 7 | MANOOL is free software: you can redistribute it and/or modify it under the terms of the version 3 of the GNU General Public License 8 | as published by the Free Software Foundation (and only version 3). 9 | 10 | MANOOL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License along with MANOOL. If not, see . */ 14 | 15 | 16 | # include "config.tcc" 17 | # include "base.tcc" 18 | 19 | namespace MNL_AUX_UUID { namespace aux { 20 | code optimize(MNL_EXPR<> expr) { 21 | code res = move(expr); 22 | # ifdef MNL_WITH_OPTIMIZE 23 | match >> (res) || 24 | match >> (res) || 25 | # define MNL_M(OP) \ 26 | match, expr_tmp> >> (res) || \ 27 | match, code> >> (res) || \ 28 | match, expr_tmp> >> (res) || \ 29 | match, code> >> (res) || \ 30 | match, expr_tmp> >> (res) || \ 31 | match, code> >> (res) || \ 32 | match, expr_tmp> >> (res) || \ 33 | match, code> >> (res) || \ 34 | match, expr_tmp> >> (res) || \ 35 | match, code> >> (res) || \ 36 | match, expr_tmp> >> (res) || \ 37 | match, code> >> (res) || \ 38 | match, expr_tmp> >> (res) || \ 39 | match, code> >> (res) || \ 40 | match> >> (res) || \ 41 | match> >> (res) || \ 42 | match> >> (res) || \ 43 | match> >> (res) || \ 44 | match> >> (res) || \ 45 | match> >> (res) || \ 46 | match> >> (res) || \ 47 | match >> (res) || \ 48 | match >> (res) || \ 49 | match> >> (res) || \ 50 | match> >> (res) || \ 51 | match> >> (res) || \ 52 | match> >> (res) || \ 53 | match> >> (res) || \ 54 | match> >> (res) || \ 55 | match> >> (res) || \ 56 | match >> (res) || \ 57 | match >> (res) || 58 | MNL_M(_eq) MNL_M(_ne) 59 | # undef MNL_M 60 | # define MNL_M(OP) \ 61 | match, expr_tmp> >> (res) || \ 62 | match, code> >> (res) || \ 63 | match, expr_tmp> >> (res) || \ 64 | match, code> >> (res) || \ 65 | match, expr_tmp> >> (res) || \ 66 | match, code> >> (res) || \ 67 | match, expr_tmp> >> (res) || \ 68 | match, code> >> (res) || \ 69 | match> >> (res) || \ 70 | match> >> (res) || \ 71 | match> >> (res) || \ 72 | match> >> (res) || \ 73 | match >> (res) || \ 74 | match >> (res) || \ 75 | match> >> (res) || \ 76 | match> >> (res) || \ 77 | match> >> (res) || \ 78 | match> >> (res) || \ 79 | match >> (res) || \ 80 | match >> (res) || 81 | MNL_M(_lt) MNL_M(_le) MNL_M(_gt) MNL_M(_ge) 82 | # undef MNL_M 83 | # define MNL_M(OP) \ 84 | match >> (res) || \ 85 | match >> (res) || \ 86 | match >> (res) || \ 87 | match >> (res) || 88 | MNL_M(_xor) 89 | # undef MNL_M 90 | match> (res) || 91 | match> (res); 92 | # endif // # ifdef MNL_WITH_OPTIMIZE 93 | return res; 94 | } 95 | }} // namespace MNL_AUX_UUID::aux 96 | -------------------------------------------------------------------------------- /base-opt-if.cc: -------------------------------------------------------------------------------- 1 | // base-opt-if.cc 2 | # define MNL_EXPR expr_if 3 | # include "base-opt-cond.tcc" 4 | -------------------------------------------------------------------------------- /base-opt-ifelse.cc: -------------------------------------------------------------------------------- 1 | // base-opt-ifelse.cc 2 | # define MNL_EXPR expr_ifelse 3 | # include "base-opt-cond.tcc" 4 | -------------------------------------------------------------------------------- /base-opt-misc.cc: -------------------------------------------------------------------------------- 1 | // base-opt-misc.cc -- base optimization rules 2 | 3 | /* Copyright (C) 2018, 2019, 2020 Alexey Protasov (AKA Alex or rusini) 4 | 5 | This file is part of MANOOL. 6 | 7 | MANOOL is free software: you can redistribute it and/or modify it under the terms of the version 3 of the GNU General Public License 8 | as published by the Free Software Foundation (and only version 3). 9 | 10 | MANOOL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License along with MANOOL. If not, see . */ 14 | 15 | 16 | # include "config.tcc" 17 | # include "base.tcc" 18 | 19 | namespace MNL_AUX_UUID { namespace aux { 20 | code optimize(expr_lit<> expr) { 21 | code res = move(expr); 22 | # ifdef MNL_WITH_OPTIMIZE 23 | match> (res) || 24 | match> (res) || 25 | match> (res) || 26 | match> (res) || 27 | match> (res) || 28 | match> (res) || 29 | match> (res) || 30 | match> (res); 31 | # endif // # ifdef MNL_WITH_OPTIMIZE 32 | return res; 33 | } 34 | code optimize(expr_apply0<> expr) { 35 | code res = move(expr); 36 | # ifdef MNL_WITH_OPTIMIZE 37 | match >> (res) || 38 | match> (res) || 39 | match> (res); 40 | # endif // # ifdef MNL_WITH_OPTIMIZE 41 | return res; 42 | } 43 | code optimize(expr_apply1<> expr) { 44 | code res = move(expr); 45 | # ifdef MNL_WITH_OPTIMIZE 46 | match> (res) || 47 | match> (res) || 48 | match> (res) || 49 | match> (res) || 50 | match> (res) || 51 | match> (res) || 52 | match, code >> (res) || 53 | match, expr_lit >> (res) || 54 | match, expr_tmp >> (res) || 55 | match, code >> (res) || 56 | match >> (res) || 57 | match> (res) || 58 | match> (res) || 59 | match >> (res) || 60 | match> (res) || 61 | match> (res); 62 | # endif // # ifdef MNL_WITH_OPTIMIZE 63 | return res; 64 | } 65 | code optimize(expr_apply3<> expr) { 66 | code res = move(expr); 67 | # ifdef MNL_WITH_OPTIMIZE 68 | match >> (res) || 69 | match >> (res) || 70 | match> (res) || 71 | match> (res); 72 | # endif // # ifdef MNL_WITH_OPTIMIZE 73 | return res; 74 | } 75 | code optimize(expr_apply4<> expr) { 76 | code res = move(expr); 77 | # ifdef MNL_WITH_OPTIMIZE 78 | match >> (res) || 79 | match >> (res) || 80 | match> (res) || 81 | match> (res); 82 | # endif // # ifdef MNL_WITH_OPTIMIZE 83 | return res; 84 | } 85 | code optimize(expr_move<> expr) { 86 | code res = move(expr); 87 | # ifdef MNL_WITH_OPTIMIZE 88 | match> (res) || 89 | match> (res); 90 | # endif // # ifdef MNL_WITH_OPTIMIZE 91 | return res; 92 | } 93 | code optimize(expr_att expr) { 94 | code res = move(expr); 95 | # ifdef MNL_WITH_OPTIMIZE 96 | match (res) || 97 | match (res); 98 | # endif // # ifdef MNL_WITH_OPTIMIZE 99 | return res; 100 | } 101 | code optimize(expr_on<> expr) { 102 | code res = move(expr); 103 | # ifdef MNL_WITH_OPTIMIZE 104 | match >> (res) || 105 | match> (res) || 106 | match> (res); 107 | # endif // # ifdef MNL_WITH_OPTIMIZE 108 | return res; 109 | } 110 | }} // namespace MNL_AUX_UUID::aux 111 | -------------------------------------------------------------------------------- /base-opt-or.cc: -------------------------------------------------------------------------------- 1 | // base-opt-or.cc 2 | # define MNL_EXPR expr_or 3 | # include "base-opt-cond.tcc" 4 | -------------------------------------------------------------------------------- /base-opt-set.cc: -------------------------------------------------------------------------------- 1 | // base-opt-set.cc -- base optimization rules 2 | 3 | /* Copyright (C) 2018, 2019, 2020 Alexey Protasov (AKA Alex or rusini) 4 | 5 | This file is part of MANOOL. 6 | 7 | MANOOL is free software: you can redistribute it and/or modify it under the terms of the version 3 of the GNU General Public License 8 | as published by the Free Software Foundation (and only version 3). 9 | 10 | MANOOL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License along with MANOOL. If not, see . */ 14 | 15 | 16 | # include "config.tcc" 17 | # include "base.tcc" 18 | 19 | namespace MNL_AUX_UUID { namespace aux { 20 | code optimize(expr_set<> expr) { 21 | code res = move(expr); 22 | # ifdef MNL_WITH_OPTIMIZE 23 | match >> (res) || 24 | match >> (res) || 25 | match >> (res) || 26 | match >> (res) || 27 | match >> (res) || 28 | match >> (res) || 29 | match >> (res) || 30 | match >> (res) || 31 | match >> (res) || 32 | match >> (res) || 33 | match >> (res) || 34 | match >> (res) || 35 | match >> (res) || 36 | match >> (res) || 37 | # define MNL_M(OP) \ 38 | match, expr_tmp> >> (res) || \ 39 | match, code> >> (res) || \ 40 | match, expr_tmp> >> (res) || \ 41 | match, code> >> (res) || \ 42 | match, expr_tmp> >> (res) || \ 43 | match, code> >> (res) || \ 44 | match, expr_tmp> >> (res) || \ 45 | match, code> >> (res) || \ 46 | match, expr_tmp> >> (res) || \ 47 | match, code> >> (res) || \ 48 | match, expr_tmp> >> (res) || \ 49 | match, code> >> (res) || \ 50 | match, expr_tmp> >> (res) || \ 51 | match, code> >> (res) || \ 52 | match> >> (res) || \ 53 | match> >> (res) || \ 54 | match> >> (res) || \ 55 | match> >> (res) || \ 56 | match> >> (res) || \ 57 | match> >> (res) || \ 58 | match> >> (res) || \ 59 | match >> (res) || \ 60 | match >> (res) || \ 61 | match> >> (res) || \ 62 | match> >> (res) || \ 63 | match> >> (res) || \ 64 | match> >> (res) || \ 65 | match> >> (res) || \ 66 | match> >> (res) || \ 67 | match> >> (res) || \ 68 | match >> (res) || \ 69 | match >> (res) || 70 | MNL_M(_eq) MNL_M(_ne) 71 | # undef MNL_M 72 | # define MNL_M(OP) \ 73 | match, expr_tmp> >> (res) || \ 74 | match, code> >> (res) || \ 75 | match, expr_tmp> >> (res) || \ 76 | match, code> >> (res) || \ 77 | match, expr_tmp> >> (res) || \ 78 | match, code> >> (res) || \ 79 | match, expr_tmp> >> (res) || \ 80 | match, code> >> (res) || \ 81 | match> >> (res) || \ 82 | match> >> (res) || \ 83 | match> >> (res) || \ 84 | match> >> (res) || \ 85 | match >> (res) || \ 86 | match >> (res) || \ 87 | match> >> (res) || \ 88 | match> >> (res) || \ 89 | match> >> (res) || \ 90 | match> >> (res) || \ 91 | match >> (res) || \ 92 | match >> (res) || 93 | MNL_M(_lt) MNL_M(_le) MNL_M(_gt) MNL_M(_ge) MNL_M(_add) MNL_M(_sub) MNL_M(_mul) 94 | # undef MNL_M 95 | # define MNL_M(OP) \ 96 | match >> (res) || \ 97 | match >> (res) || \ 98 | match >> (res) || \ 99 | match >> (res) || \ 100 | MNL_M(_xor) 101 | # undef MNL_M 102 | match> (res) || 103 | match> (res) || 104 | match>, code >> (res) || 105 | match, code >> (res) || 106 | match, code >> (res) || 107 | match>, code >> (res) || 108 | match, code >> (res) || 109 | match, code >> (res) || 110 | match>, code >> (res) || 111 | match, code >> (res) || 112 | match, code >> (res) || 113 | match>, code >> (res) || 114 | match, code >> (res) || 115 | match, code >> (res) || 116 | match>, code >> (res) || 117 | match, code >> (res) || 118 | match, code >> (res) || 119 | match>, code >> (res) || 120 | match, code >> (res) || 121 | match, code >> (res) || 122 | match >> (res) || 123 | match >> (res) || 124 | match >> (res) || 125 | match >> (res) || 126 | match >> (res) || 127 | match >> (res) || 128 | match >> (res) || 129 | match >> (res) || 130 | match> (res) || 131 | match> (res); 132 | # endif // # ifdef MNL_WITH_OPTIMIZE 133 | return res; 134 | } 135 | }} // namespace MNL_AUX_UUID::aux 136 | -------------------------------------------------------------------------------- /base-opt-while.cc: -------------------------------------------------------------------------------- 1 | // base-opt-while.cc 2 | # define MNL_EXPR expr_while 3 | # include "base-opt-cond.tcc" 4 | -------------------------------------------------------------------------------- /build/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /config.tcc: -------------------------------------------------------------------------------- 1 | // config.tcc 2 | // Feature-Test Macros (think about ABI-breaking, especially _FILE_OFFSET_BITS if needed) 3 | # ifndef _GNU_SOURCE 4 | # define _GNU_SOURCE // required anyway by libstdc++ (but ignored on BSDs) 5 | # endif 6 | -------------------------------------------------------------------------------- /configure: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | # configure 3 | printf 'Relax, there is no need to run ./configure here!\n' 4 | -------------------------------------------------------------------------------- /core-misc.cc: -------------------------------------------------------------------------------- 1 | // core-misc.cc -- core miscellaneous 2 | 3 | /* Copyright (C) 2018, 2019, 2020 Alexey Protasov (AKA Alex or rusini) 4 | 5 | This file is part of MANOOL. 6 | 7 | MANOOL is free software: you can redistribute it and/or modify it under the terms of the version 3 of the GNU General Public License 8 | as published by the Free Software Foundation (and only version 3). 9 | 10 | MANOOL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License along with MANOOL. If not, see . */ 14 | 15 | 16 | # include "config.tcc" 17 | # include "mnl-aux-core.tcc" 18 | 19 | # include // clock_gettime 20 | # include // sprintf, stderr, fprintf, fputs, fflush 21 | 22 | namespace MNL_AUX_UUID { using namespace aux; 23 | namespace aux { 24 | using std::_Exit; using std::srand; // 25 | using std::sprintf; using std::fprintf; using std::fputs; using std::fflush; // 26 | } 27 | 28 | // Translation Infrastructure ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 29 | MNL_IF_WITH_MT(thread_local) decltype(symtab) pub::symtab; 30 | 31 | namespace aux { namespace { struct stub { 32 | MNL_INLINE static val execute(bool) { MNL_UNREACHABLE(); } 33 | MNL_INLINE static void exec_in(val &&) { MNL_UNREACHABLE(); } 34 | MNL_INLINE static val exec_out() { MNL_UNREACHABLE(); } 35 | MNL_INLINE static bool is_rvalue() { return false; } 36 | MNL_INLINE static bool is_lvalue() { return false; } 37 | MNL_INLINE static code compile(code &&, const form &, const loc &_loc) { err_compile("invalid form", _loc); } 38 | }; }} 39 | code pub::compile(const form &form, const loc &_loc) { return // *** The Compiler Core Dispatcher! *** 40 | test(form) && symtab[cast(form)] ? 41 | symtab[cast(form)] : 42 | test(form) && (((const string &)cast(form))[0] >= 'a' && ((const string &)cast(form))[0] <= 'z' || 43 | ((const string &)cast(form))[0] == '_' || ((const string &)cast(form))[0] == '`') ? 44 | MNL_AUX_INIT((code)stub{}) : 45 | test(form) || test(form) || test(form) ? 46 | [&]()->code{ code make_lit(const val &); return make_lit(form); }() : // actually from MANOOL API 47 | form.is_list() && !form.empty() ? 48 | compile(form.front(), form._loc(_loc)).compile(form, form._loc(_loc)) : 49 | test(form) ? 50 | cast(form) : 51 | ((form.is_list() ? err_compile("invalid form", form._loc(_loc)) : MNL_ERR(MNL_SYM("TypeMismatch"))), code{}); 52 | } 53 | 54 | void pub::err_compile(const char *msg, const loc &loc) { 55 | char buf[sizeof " 2147483647:2147483647-2147483647:2147483647 Error: "]; 56 | throw pair{MNL_SYM("CompileError"), (!loc.origin ? (string)" Error: " : '(' + *loc.origin + ')' + 57 | (sprintf(buf, " %d:%d-%d:%d Error: ", loc._start.first, loc._start.second, loc._final.first, loc._final.second - 1), buf)) + msg}; 58 | } 59 | 60 | // class sym /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 61 | MNL_PRIORITY(1003) decltype(sym::pool) sym::pool; 62 | MNL_IF_WITH_MT(MNL_PRIORITY(1004) decltype(sym::mutex) sym::mutex;) 63 | 64 | sym::sym(string txt): rep([&]()->decltype(rep){ // precond: txt[0] != '`' 65 | MNL_IF_WITH_MT( return std::lock_guard{mutex}, [&]()->decltype(rep){ ) 66 | decltype(dict)::const_iterator it = dict.find(txt); 67 | if (it != dict.end()) 68 | return addref(it->second), it->second; 69 | if (!pool.empty()) { 70 | inverse[pool.back()] = it = dict.insert(make_pair(move(txt), pool.back())).first, pool.pop_back(); 71 | } else { 72 | if (!static_cast(dict.size())) // wrap-around means no more IDs available 73 | fputs("MANOOL: FATAL ERROR: Symbol space exhausted\n", stderr), fflush(stderr), _Exit(EXIT_FAILURE); 74 | pool.reserve(dict.size() + 1); 75 | it = dict.insert(make_pair(move(txt), static_cast(dict.size()))).first, inverse[dict.size() - 1] = it; 76 | } 77 | return rc[it->second] = 1, it->second; 78 | MNL_IF_WITH_MT( }(); ) 79 | }()) {} 80 | sym::sym(const char *txt): sym((string)txt) 81 | {} 82 | sym::sym(decltype(nullptr)): rep([&]()->decltype(rep){ 83 | MNL_IF_WITH_MT( return std::lock_guard{mutex}, [&]()->decltype(rep){ ) 84 | auto mask = MNL_AUX_RAND(unsigned short); 85 | decltype(dict)::const_iterator it; 86 | if (!pool.empty()) { 87 | char txt[sizeof "`65535"]; 88 | sprintf(txt, "`%u", (unsigned)pool.back() ^ mask); 89 | inverse[pool.back()] = it = dict.insert(make_pair(move(txt), pool.back())).first, pool.pop_back(); 90 | } else { 91 | if (!static_cast(dict.size())) // wrap-around means no more IDs available 92 | fputs("MANOOL: FATAL ERROR: Symbol space exhausted\n", stderr), fflush(stderr), _Exit(EXIT_FAILURE); 93 | char txt[sizeof "`65535"]; 94 | sprintf(txt, "`%u", (unsigned)dict.size() ^ mask); 95 | pool.reserve(dict.size() + 1); 96 | it = dict.insert(make_pair(move(txt), static_cast(dict.size()))).first, inverse[dict.size() - 1] = it; 97 | } 98 | return rc[it->second] = 1, it->second; 99 | MNL_IF_WITH_MT( }(); ) 100 | }()) {} 101 | void sym::free(decltype(rep) rep) noexcept { 102 | MNL_IF_WITH_MT( std::lock_guard{mutex}, [&]{ if (!__atomic_load_n(&rc[rep], __ATOMIC_RELAXED)) ) 103 | dict.erase(inverse[rep]), pool.push_back(rep); 104 | MNL_IF_WITH_MT( }(); ) 105 | } 106 | 107 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 108 | val val::default_invoke(const sym &op, int argc, val argv[]) { 109 | switch (MNL_DISP("==", "<>", "Order", "Clone", "DeepClone", "Str")[op]) { 110 | case 1: // == 111 | if (MNL_UNLIKELY(argc != 1)) MNL_ERR(MNL_SYM("InvalidInvocation")); 112 | return MNL_LIKELY(argv[0].rep.tag() == 0x7FF8u) && argv[0].rep.dat() == rep.dat(); 113 | case 2: // <> 114 | if (MNL_UNLIKELY(argc != 1)) MNL_ERR(MNL_SYM("InvalidInvocation")); 115 | return !MNL_LIKELY(argv[0].rep.tag() == 0x7FF8u) || argv[0].rep.dat() != rep.dat(); 116 | case 3: // Order 117 | if (MNL_UNLIKELY(argc != 1)) MNL_ERR(MNL_SYM("InvalidInvocation")); 118 | { auto mask = MNL_AUX_RAND(uintptr_t); 119 | int res = default_order(argv[0]); 120 | return MNL_UNLIKELY(res) ? res : 121 | ((reinterpret_cast(rep.dat()) ^ mask) < (reinterpret_cast(argv[0].rep.dat()) ^ mask)) - 122 | ((reinterpret_cast(argv[0].rep.dat()) ^ mask) < (reinterpret_cast(rep.dat()) ^ mask)); 123 | } 124 | case 4: // Clone 125 | if (MNL_UNLIKELY(argc != 0)) MNL_ERR(MNL_SYM("InvalidInvocation")); 126 | return move(*this); 127 | case 5: // DeepClone 128 | if (MNL_UNLIKELY(argc != 0)) MNL_ERR(MNL_SYM("InvalidInvocation")); 129 | return static_cast(rep.dat())->invoke(move(*this), MNL_SYM("Clone"), 0, {}); 130 | case 6: // Str 131 | if (MNL_UNLIKELY(argc != 0)) MNL_ERR(MNL_SYM("InvalidInvocation")); 132 | { static MNL_IF_WITH_MT(thread_local) const val res = "value/object"; return res; } 133 | case 0: 134 | MNL_ERR(MNL_SYM("UnrecognizedOperation")); 135 | }} 136 | 137 | // Signals, Exceptions, and Invocation Traces ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 138 | MNL_IF_WITH_MT(thread_local) decltype(sig_state) pub::sig_state; 139 | MNL_IF_WITH_MT(thread_local) decltype(sig_trace) pub::sig_trace = []()->decltype(sig_trace){ decltype(sig_trace) res; res.reserve(100 + 1); return res; }(); 140 | 141 | void aux::error(const sym &err) 142 | { throw make_pair(err, val{}); } 143 | void aux::error(const loc &loc, const sym &err) 144 | { if (loc.origin && sig_trace.size() < sig_trace.capacity()) sig_trace.push_back({loc, "evaluating"}); throw make_pair(err, val{}); } 145 | 146 | void pub::trace_execute (const loc &loc) { if (loc.origin && sig_trace.size() < sig_trace.capacity()) sig_trace.push_back({loc, "evaluating"}); throw; } 147 | void pub::trace_exec_in (const loc &loc) { if (loc.origin && sig_trace.size() < sig_trace.capacity()) sig_trace.push_back({loc, "storing a value"}); throw; } 148 | void pub::trace_exec_out(const loc &loc) { if (loc.origin && sig_trace.size() < sig_trace.capacity()) sig_trace.push_back({loc, "moving-out a value"}); throw; } 149 | 150 | // Record Descriptors ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 151 | record_descr::record_descr(const record_descr &rhs) noexcept: rep(rhs.rep) { addref(); } 152 | record_descr::~record_descr() { release(); } 153 | record_descr &record_descr::operator=(const record_descr &rhs) noexcept { rhs.addref(), release(), rep = rhs.rep; return *this; } 154 | 155 | void record_descr::addref() const noexcept { 156 | if (rep == store.end()) return; 157 | MNL_IF_WITHOUT_MT(++rep->second.second) MNL_IF_WITH_MT(__atomic_add_fetch(&rep->second.second, 1, __ATOMIC_RELAXED)); 158 | } 159 | void record_descr::release() const noexcept { 160 | if (rep == store.end()) return; 161 | if (MNL_UNLIKELY(! MNL_IF_WITHOUT_MT(--rep->second.second) MNL_IF_WITH_MT(__atomic_sub_fetch(&rep->second.second, 1, __ATOMIC_RELAXED)) )) 162 | MNL_IF_WITH_MT( std::lock_guard{mutex}, [=]{ if (!__atomic_load_n(&rep->second.second, __ATOMIC_RELAXED)) ) 163 | store.erase(rep); 164 | MNL_IF_WITH_MT( }(); ) 165 | } 166 | record_descr::record_descr(set items) 167 | : rep((MNL_IF_WITH_MT(std::lock_guard{mutex},) [&]()->decltype(rep){ 168 | { auto it = store.find(items); if (it != store.end()) 169 | return MNL_IF_WITHOUT_MT(++it->second.second) MNL_IF_WITH_MT(__atomic_add_fetch(&it->second.second, 1, __ATOMIC_RELAXED)), it; 170 | } 171 | sym::tab tab(-1); { int disp/*lacement*/ = 0; for (const auto &el: items) tab.update(el, disp++); } 172 | return store.insert(make_pair(move(items), make_pair(move((tab.shrink_to_fit(), tab)), 1))).first; 173 | }())) {} 174 | record_descr::record_descr(initializer_list il): record_descr([=]()->set{ 175 | set res; for (auto el: il) res.insert(el); return res; 176 | }()) {} 177 | int pub::order(const record_descr &lhs, const record_descr &rhs) noexcept { 178 | auto mask = MNL_AUX_RAND(uintptr_t); 179 | return 180 | ((reinterpret_cast(&*lhs.rep) ^ mask) < (reinterpret_cast(&*rhs.rep) ^ mask)) - 181 | ((reinterpret_cast(&*rhs.rep) ^ mask) < (reinterpret_cast(&*lhs.rep) ^ mask)); 182 | } 183 | 184 | decltype(record_descr::store) record_descr::store; 185 | MNL_IF_WITH_MT(decltype(record_descr::mutex) record_descr::mutex;) 186 | 187 | // Seed Legacy Random Number Generator ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 188 | namespace aux { namespace { MNL_PRIORITY(1000) class { int _ = []()->int{ 189 | struct ::timespec ts; ::clock_gettime(CLOCK_REALTIME, &ts); return srand(ts.tv_sec ^ (unsigned)ts.tv_nsec / 1000), 0; 190 | }(); } _srand; }} 191 | 192 | } // namespace MNL_AUX_UUID 193 | -------------------------------------------------------------------------------- /do-make: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # do-make 3 | 4 | if [ "$host$dir" ]; then 5 | unset -v params 6 | else 7 | unset -v host port login key dir make params; test -f do-make.cf && . ./do-make.cf 8 | fi 9 | dir=${dir-do-make.rsync} 10 | 11 | if [ "$host$port$login$key" ]; then 12 | if [ -t 1 ]; then term=-t; else unset -v term; fi 13 | rsync -e "ssh${port:+ -p$(printf %q "${port}")}${key:+ -i$(printf %q "${key}")}" \ 14 | -crz --delete --exclude={.{svn,git},build,do-make{,.cf}} . "${login:+${login}@}${host:-localhost}:${dir}" && 15 | exec ssh${port:+ -p"${port}"}${key:+ -i"${key}"} ${term} "${login:+${login}@}${host:-localhost}" \ 16 | "mkdir -p $(printf %q "${dir:-.}")/build &&" \ 17 | exec nice "$(printf %q "${make:-make}")${dir:+ -C$(printf %q "${dir}") --no-print-directory}${params:+$(printf ' %q' "${params[@]}")}${@:+$(printf ' %q' "$@")}" 18 | else 19 | rsync -cr --delete --exclude={.{svn,git},build,do-make{,.cf}} . "${dir:-.}" && 20 | mkdir -p "${dir:-.}"/build && 21 | exec "${make:-make}"${dir:+ -C"${dir}" --no-print-directory} "${params[@]}" "$@" 22 | fi 23 | -------------------------------------------------------------------------------- /do-make.cf: -------------------------------------------------------------------------------- 1 | params=(GCC='nice gcc' GXX='nice g++' MARCH=) 2 | #params=(GCC='nice gcc -specs=/usr/lib/x86_64-linux-musl/musl-gcc.specs' GXX='nice g++ -specs=/usr/lib/x86_64-linux-musl/musl-gcc.specs' MARCH=) 3 | #params=(GCC='nice x86_64-linux-gnux32-gcc' GXX='nice x86_64-linux-gnux32-g++' MARCH=) 4 | #params=(GCC='nice sh4-linux-gnu-gcc' GXX='nice sh4-linux-gnu-g++' MARCH=) 5 | host=devbox dir=manool 6 | -------------------------------------------------------------------------------- /lib-base-main.cc: -------------------------------------------------------------------------------- 1 | // lib-base-main.cc 2 | # include "config.tcc" 3 | # include "mnl-aux-core.tcc" 4 | extern "C" mnl::code mnl_main() { mnl::code mnl_aux_base(); return mnl_aux_base(); } 5 | -------------------------------------------------------------------------------- /lib-ieee754-cmpx-main.cc: -------------------------------------------------------------------------------- 1 | // lib-ieee754-cmpx-main.cc 2 | # include "config.tcc" 3 | # include "mnl-aux-core.tcc" 4 | extern "C" mnl::code mnl_main() { mnl::code mnl_aux_ieee754_cmpx(); return mnl_aux_ieee754_cmpx(); } 5 | -------------------------------------------------------------------------------- /lib-ieee754-dec-main.cc: -------------------------------------------------------------------------------- 1 | // lib-ieee754-dec-main.cc 2 | # include "config.tcc" 3 | # include "mnl-aux-core.tcc" 4 | extern "C" mnl::code mnl_main() { mnl::code mnl_aux_ieee754_dec(); return mnl_aux_ieee754_dec(); } 5 | -------------------------------------------------------------------------------- /lib-misc-main.cc: -------------------------------------------------------------------------------- 1 | // lib-misc-main.cc -- interesting facilities to experiment with 2 | 3 | /* Copyright (C) 2018, 2019, 2020 Alexey Protasov (AKA Alex or rusini) 4 | 5 | This file is part of MANOOL. 6 | 7 | MANOOL is free software: you can redistribute it and/or modify it under the terms of the version 3 of the GNU General Public License 8 | as published by the Free Software Foundation (and only version 3). 9 | 10 | MANOOL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License along with MANOOL. If not, see . */ 14 | 15 | 16 | # include "config.tcc" 17 | 18 | # include 19 | # include 20 | 21 | # include "manool.hh" 22 | # include "mnl-lib-ieee754-dec.hh" 23 | 24 | extern "C" mnl::code mnl_main() { 25 | using mnl::sym; using mnl::val; using mnl::test; using mnl::cast; 26 | using mnl::make_lit; using mnl::expr_export; 27 | using mnl::dec; 28 | 29 | struct proc_Random { MNL_INLINE static val invoke(val &&self, const sym &op, int argc, val argv[], val *) { 30 | if (MNL_UNLIKELY(op != MNL_SYM("Apply"))) return self.default_invoke(op, argc, argv); 31 | if (MNL_UNLIKELY(argc != 0)) MNL_ERR(MNL_SYM("InvalidInvocation")); 32 | static MNL_IF_WITH_MT(thread_local) unsigned short state[] 33 | {(unsigned short)(::time({}) >> 16), (unsigned short)::time({}), (unsigned short)::clock()}; 34 | return ::erand48(state); 35 | }}; 36 | struct proc_Clock { MNL_INLINE static val invoke(val &&self, const sym &op, int argc, val argv[], val *) { 37 | if (MNL_UNLIKELY(op != MNL_SYM("Apply"))) return self.default_invoke(op, argc, argv); 38 | if (MNL_UNLIKELY(argc != 0)) MNL_ERR(MNL_SYM("InvalidInvocation")); 39 | struct ::timespec ts; 40 | ::clock_gettime( 41 | # if __linux__ 42 | CLOCK_MONOTONIC_RAW 43 | # elif __FreeBSD__ 44 | CLOCK_MONOTONIC_PRECISE 45 | # else 46 | # error "Either __linux__ or __FreeBSD__ is required" 47 | # endif 48 | , &ts); 49 | char buf[sizeof "18446744073709551616.111222333"]; 50 | return (dec<128>)(sprintf(buf, "%llu.%09ld", (unsigned long long)ts.tv_sec, ts.tv_nsec), buf); 51 | }}; 52 | struct proc_Delay { MNL_INLINE static val invoke(val &&self, const sym &op, int argc, val argv[], val *) { 53 | if (MNL_UNLIKELY(op != MNL_SYM("Apply"))) return self.default_invoke(op, argc, argv); 54 | if (MNL_UNLIKELY(argc != 1)) MNL_ERR(MNL_SYM("InvalidInvocation")); 55 | if (MNL_UNLIKELY(!test(argv[0]))) MNL_ERR(MNL_SYM("TypeMismatch")); 56 | if (MNL_UNLIKELY(cast(argv[0]) < 0)) MNL_ERR(MNL_SYM("ConstraintViolation")); 57 | struct ::timespec ts 58 | {::time_t(cast(argv[0]) / 1000000000llu), long(cast(argv[0]) % 1000000000llu)}; 59 | ::nanosleep(&ts, {}); return {}; 60 | }}; 61 | return expr_export{ 62 | {"Random", make_lit(proc_Random{})}, 63 | {"Clock", make_lit(proc_Clock{})}, 64 | {"Delay", make_lit(proc_Delay{})}, 65 | }; 66 | } 67 | -------------------------------------------------------------------------------- /lib-runtime-main.cc: -------------------------------------------------------------------------------- 1 | // lib-runtime-main.cc 2 | # include "config.tcc" 3 | # include "mnl-aux-core.tcc" 4 | extern "C" mnl::code mnl_main() { mnl::code mnl_aux_runtime(); return mnl_aux_runtime(); } 5 | -------------------------------------------------------------------------------- /lib-threads-main.cc: -------------------------------------------------------------------------------- 1 | // lib-threads-main.cc -- multithreading plug-in 2 | 3 | /* Copyright (C) 2018, 2019, 2020 Alexey Protasov (AKA Alex or rusini) 4 | 5 | This file is part of MANOOL. 6 | 7 | MANOOL is free software: you can redistribute it and/or modify it under the terms of the version 3 of the GNU General Public License 8 | as published by the Free Software Foundation (and only version 3). 9 | 10 | MANOOL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License along with MANOOL. If not, see . */ 14 | 15 | 16 | # include "config.tcc" 17 | 18 | # ifdef MNL_WITH_MULTITHREADING 19 | 20 | # include 21 | # include 22 | # include 23 | # include 24 | # include 25 | # include 26 | # include 27 | # include 28 | # include 29 | 30 | # include "manool.hh" 31 | 32 | extern "C" mnl::code mnl_main() { 33 | using std::_Exit; 34 | using std::fputs; using std::fflush; 35 | using std::move; 36 | using std::thread; 37 | using mnl::sym; using mnl::val; using mnl::test; using mnl::cast; using mnl::safe_cast; 38 | using mnl::make_lit; using mnl::expr_export; using mnl::make_proc_test; 39 | using mnl::stk_limit; 40 | 41 | static ::pthread_mutexattr_t mutex_attr; 42 | static thread_local long long lock_count; // numeric overflow possible after tenths of years of continuous Mutex Acquire - ignore it 43 | 44 | struct mutex { 45 | ::pthread_mutex_t rep; 46 | public: 47 | mutex() { 48 | if (MNL_UNLIKELY(::pthread_mutex_init(&rep, &mutex_attr))) MNL_ERR(MNL_SYM("SystemError")); 49 | } 50 | ~mutex() { 51 | if (MNL_UNLIKELY(::pthread_mutex_trylock(&rep)) || MNL_UNLIKELY(!(::pthread_mutex_unlock(&rep), ::pthread_mutex_unlock(&rep)))) 52 | fputs("MANOOL: FATAL ERROR: Mutex falls out of scope while its ownership is still held\n", stderr), 53 | fflush(stderr), _Exit(EXIT_FAILURE); 54 | ::pthread_mutex_destroy(&rep); 55 | } 56 | public: 57 | mutex(mutex &&): mutex{} {} 58 | mutex &operator=(const mutex &) = delete; 59 | public: 60 | MNL_INLINE val invoke(val &&self, const sym &op, int argc, val argv[], val *) { 61 | switch (MNL_DISP("Acquire", "Release")[op]) { 62 | case 1: 63 | if (MNL_LIKELY(argc == 0) || MNL_UNLIKELY(argc == 1) && !MNL_LIKELY(safe_cast(argv[0]))) { // Acquire[M], Acquire[M; False] 64 | if (MNL_UNLIKELY(::pthread_mutex_lock(&rep))) MNL_ERR(MNL_SYM("MutexAcquireError")); 65 | ++lock_count; return {}; 66 | } 67 | if (MNL_LIKELY(argc == 1)) // Acquire[True] - nonblocking 68 | switch (::pthread_mutex_trylock(&rep)) { 69 | case 0: return ++lock_count, true; 70 | case EBUSY: return false; 71 | default: MNL_ERR(MNL_SYM("MutexAcquireError")); 72 | } 73 | MNL_ERR(MNL_SYM("InvalidInvocation")); 74 | case 2: 75 | if (MNL_LIKELY(argc == 0) || MNL_UNLIKELY(argc == 1) && !MNL_LIKELY(safe_cast(argv[0]))) { // Release[M], Release[M; False] 76 | if (MNL_UNLIKELY(::pthread_mutex_unlock(&rep))) MNL_ERR(MNL_SYM("MutexReleaseError")); 77 | --lock_count; return {}; 78 | } 79 | if (MNL_LIKELY(argc == 1)) { // Release[True] - complete 80 | long long count = 1; 81 | if (MNL_UNLIKELY(::pthread_mutex_unlock(&rep))) MNL_ERR(MNL_SYM("MutexReleaseError")); 82 | --lock_count; while (!::pthread_mutex_unlock(&rep)) ++count, --lock_count; return count; 83 | } 84 | MNL_ERR(MNL_SYM("InvalidInvocation")); 85 | case 0: 86 | return self.default_invoke(op, argc, argv); 87 | } 88 | } 89 | }; 90 | struct cond { 91 | val cond_mutex; 92 | ::pthread_cond_t rep; 93 | ::pthread_mutex_t aux_mutex; 94 | public: 95 | cond(val cond_mutex): cond_mutex(move(cond_mutex)) { 96 | if (MNL_UNLIKELY(::pthread_cond_init(&rep, {})) || MNL_UNLIKELY(::pthread_mutex_init(&aux_mutex, {}))) MNL_ERR(MNL_SYM("SystemError")); 97 | } 98 | ~cond() { 99 | ::pthread_mutex_destroy(&aux_mutex), ::pthread_cond_destroy(&rep); // no errors expected 100 | } 101 | public: 102 | cond(cond &&rhs): cond{move(rhs.cond_mutex)} {} 103 | cond &operator=(const cond &) = delete; 104 | public: 105 | MNL_INLINE val invoke(val &&self, const sym &op, int argc, val argv[], val *) { 106 | switch (MNL_DISP("Wait", "Notify")[op]) { 107 | case 1: 108 | if (MNL_UNLIKELY(argc != 0)) MNL_ERR(MNL_SYM("InvalidInvocation")); 109 | { long long count = 1; 110 | ::pthread_mutex_lock(&aux_mutex); 111 | if (MNL_UNLIKELY(::pthread_mutex_unlock(&cast(cond_mutex).rep))) MNL_ERR(MNL_SYM("CondWaitError")); 112 | while (!::pthread_mutex_unlock(&cast(cond_mutex).rep)) ++count; // complete unlock 113 | ::pthread_cond_wait(&rep, &aux_mutex); // no errors expected 114 | ::pthread_mutex_unlock(&aux_mutex); 115 | while (count--) ::pthread_mutex_lock(&cast(cond_mutex).rep); 116 | } 117 | return {}; 118 | case 2: 119 | if (MNL_UNLIKELY(argc == 0)) return pthread_cond_signal(&rep), nullptr; 120 | if (MNL_UNLIKELY(argc != 1)) MNL_ERR(MNL_SYM("InvalidInvocation")); 121 | return (MNL_LIKELY(safe_cast(argv[0])) ? ::pthread_cond_broadcast : ::pthread_cond_signal)(&rep), nullptr; 122 | case 0: 123 | return self.default_invoke(op, argc, argv); 124 | } 125 | } 126 | }; 127 | 128 | struct proc_StartThread { 129 | MNL_INLINE val invoke(val &&self, const sym &op, int argc, val argv[], val *) const { 130 | if (MNL_UNLIKELY(op != MNL_SYM("Apply"))) return self.default_invoke(op, argc, argv); 131 | if (MNL_UNLIKELY(argc != 1)) MNL_ERR(MNL_SYM("InvalidInvocation")); 132 | { static struct _ { MNL_INLINE _() noexcept { 133 | struct ::rlimit rl; ::getrlimit(RLIMIT_STACK, &rl); 134 | if (MNL_UNLIKELY(rl.rlim_cur == RLIM_INFINITY)) // maybe specific to Linux NPTL 135 | fputs("MANOOL: WARNING: 'ulimit -s unlimited' is not recommended for multithreaded code\n", stderr); 136 | }} _; 137 | } 138 | auto start = move(argv[0]); 139 | thread{[=]{ 140 | stk_limit(::strtoll(::getenv("MNL_STACK"), {}, {})); 141 | try { move(start)(); } MNL_CATCH_UNEXPECTED 142 | if (MNL_UNLIKELY(lock_count)) 143 | fputs("MANOOL: FATAL ERROR: Terminating thread abandons a mutex while still holding ownership\n", stderr), fflush(stderr), _Exit(EXIT_FAILURE); 144 | }}.detach(); 145 | return {}; 146 | } 147 | }; 148 | struct proc_MakeMutex { 149 | MNL_INLINE val invoke(val &&self, const sym &op, int argc, val argv[], val *) const { 150 | if (MNL_UNLIKELY(op != MNL_SYM("Apply"))) return self.default_invoke(op, argc, argv); 151 | if (MNL_UNLIKELY(argc != 0)) MNL_ERR(MNL_SYM("InvalidInvocation")); 152 | return mutex{}; 153 | } 154 | }; 155 | struct proc_MakeCond { 156 | MNL_INLINE val invoke(val &&self, const sym &op, int argc, val argv[], val *) const { 157 | if (MNL_UNLIKELY(op != MNL_SYM("Apply"))) return self.default_invoke(op, argc, argv); 158 | if (MNL_UNLIKELY(argc != 1)) MNL_ERR(MNL_SYM("InvalidInvocation")); 159 | if (MNL_UNLIKELY(!test(argv[0]))) MNL_ERR(MNL_SYM("TypeMismatch")); 160 | return cond{move(argv[0])}; 161 | } 162 | }; 163 | mnl::code res = expr_export{ 164 | {"StartThread", make_lit(proc_StartThread{})}, 165 | {"MakeMutex", make_lit(proc_MakeMutex{})}, 166 | {"MakeCond", make_lit(proc_MakeCond{})}, 167 | {"IsMutex", make_proc_test()}, 168 | {"IsCond", make_proc_test()}, 169 | }; 170 | if (::pthread_mutexattr_init(&mutex_attr)) MNL_ERR(MNL_SYM("SystemError")); 171 | ::pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE); 172 | return res; 173 | } 174 | 175 | # else 176 | # include "manool.hh" 177 | extern "C" mnl::code mnl_main() { return mnl::expr_export{}; } 178 | # endif // # ifdef MNL_WITH_MULTITHREADING 179 | -------------------------------------------------------------------------------- /libdecnumber/COPYING.ICU: -------------------------------------------------------------------------------- 1 | ICU License - ICU 1.8.1 and later 2 | 3 | COPYRIGHT AND PERMISSION NOTICE 4 | 5 | Copyright (c) 1995-2005 International Business Machines Corporation and others 6 | All rights reserved. 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a 9 | copy of this software and associated documentation files (the 10 | "Software"), to deal in the Software without restriction, including 11 | without limitation the rights to use, copy, modify, merge, publish, 12 | distribute, and/or sell copies of the Software, and to permit persons 13 | to whom the Software is furnished to do so, provided that the above 14 | copyright notice(s) and this permission notice appear in all copies of 15 | the Software and that both the above copyright notice(s) and this 16 | permission notice appear in supporting documentation. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 21 | OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 22 | HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL 23 | INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING 24 | FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 25 | NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 26 | WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 27 | 28 | Except as contained in this notice, the name of a copyright holder 29 | shall not be used in advertising or otherwise to promote the sale, use 30 | or other dealings in this Software without prior written authorization 31 | of the copyright holder. 32 | 33 | -------------------------------------------------------------------------------- 34 | All trademarks and registered trademarks mentioned herein are the property of their respective owners. 35 | -------------------------------------------------------------------------------- /libdecnumber/README: -------------------------------------------------------------------------------- 1 | This is the readme.txt for the decNumber package. It includes 2 | instructions for compiling and testing the package; please read them. 3 | --------------------------------------------------------------------- 4 | 5 | decNumber is distributed in two forms; as a complete package from 6 | the International Components for Unicode (ICU) site (under an as-is 7 | license), or as a collection of Open Source files from the GCC source 8 | repository (under the GPL license). 9 | 10 | If you are using the GCC files, you can obtain the documentation, the 11 | example files mentioned below, and this readme from the General 12 | Decimal Arithmetic web page -- http://speleotrove.com/decimal/ (the 13 | URL for the open source files is also linked from there). 14 | 15 | 16 | The ICU package 17 | --------------- 18 | 19 | The ICU package includes the files: 20 | 21 | * readme.txt (this file) 22 | 23 | * ICU-license.html 24 | 25 | * decNumber.pdf (documentation) 26 | 27 | * The .c and .h file for each module in the package (see the 28 | decNumber documentation), together with other included files. 29 | 30 | * The .c files for each of the examples (example1.c through 31 | example8.c). 32 | 33 | The ICU package is made available under the terms of the ICU License 34 | (ICU 1.8.1 and later) included in the package as ICU-license.html. 35 | Your use of that package indicates your acceptance of the terms and 36 | conditions of that Agreement. 37 | 38 | 39 | To use and check decNumber 40 | -------------------------- 41 | 42 | Please read the appropriate license and documentation before using 43 | this package. If you are upgrading an existing use of decNumber 44 | (with version <= 3.37) please read the Changes Appendix for later 45 | versions -- you may need to change the DECLITEND flag. 46 | 47 | 1. Compile and link example1.c, decNumber.c, and decContext.c 48 | For instance, use: 49 | 50 | gcc -o example1 example1.c decNumber.c decContext.c 51 | 52 | Note: If your compiler does not provide stdint.h or if your C 53 | compiler does not handle line comments (// ...), then see the 54 | User's Guide section in the documentation for further information 55 | (including a sample minimal stdint.h). 56 | 57 | The use of compiler optimization is strongly recommended (e.g., 58 | -O3 for GCC or /O2 for Visual Studio). 59 | 60 | 2. Run example1 with two numeric arguments, for example: 61 | 62 | example1 1.23 1.27 63 | 64 | this should display: 65 | 66 | 1.23 + 1.27 => 2.50 67 | 68 | 3. Similarly, try the other examples, at will. 69 | 70 | Examples 2->4 require three files to be compiled, like Example 1. 71 | 72 | Example 5 requires decimal64.c in addition to the core modules. 73 | 74 | Example 6 requires decPacked.c in addition to the core modules. 75 | 76 | Example 7 requires only example7.c decContext.c and decQuad.c 77 | 78 | Example 8 requires example8.c, decContext.c, and decQuad.c, plus 79 | decNumber.c, decimal128.c, and decimal64.c (the latter 80 | for shared tables and code) 81 | 82 | -------------------------------------------------------------------------------- /libdecnumber/config.h: -------------------------------------------------------------------------------- 1 | // libdecnumber/config.h 2 | # include "../config.tcc" 3 | -------------------------------------------------------------------------------- /libdecnumber/decContext.h: -------------------------------------------------------------------------------- 1 | // libdecnumber/decContext.h 2 | 3 | /* Copyright (C) 2018, 2019, 2020 Alexey Protasov (AKA Alex or rusini) 4 | 5 | This file is part of MANOOL. 6 | 7 | MANOOL is free software: you can redistribute it and/or modify it under the terms of the version 3 of the GNU General Public License 8 | as published by the Free Software Foundation (and only version 3). 9 | 10 | MANOOL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License along with MANOOL. If not, see . */ 14 | 15 | 16 | // This file incorporates work covered by the following copyright and 17 | // permission notice: 18 | 19 | /* ------------------------------------------------------------------ */ 20 | /* Decimal Context module header */ 21 | /* ------------------------------------------------------------------ */ 22 | /* Copyright (c) IBM Corporation, 2000, 2010. All rights reserved. */ 23 | /* */ 24 | /* This software is made available under the terms of the */ 25 | /* ICU License -- ICU 1.8.1 and later. */ 26 | /* */ 27 | /* The description and User's Guide ("The decNumber C Library") for */ 28 | /* this software is called decNumber.pdf. This document is */ 29 | /* available, together with arithmetic and format specifications, */ 30 | /* testcases, and Web links, on the General Decimal Arithmetic page. */ 31 | /* */ 32 | /* Please send comments, suggestions, and corrections to the author: */ 33 | /* mfc@uk.ibm.com */ 34 | /* Mike Cowlishaw, IBM Fellow */ 35 | /* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */ 36 | /* ------------------------------------------------------------------ */ 37 | /* */ 38 | /* Context variables must always have valid values: */ 39 | /* */ 40 | /* status -- [any bits may be cleared, but not set, by user] */ 41 | /* round -- must be one of the enumerated rounding modes */ 42 | /* */ 43 | /* The following variables are implied for fixed size formats (i.e., */ 44 | /* they are ignored) but should still be set correctly in case used */ 45 | /* with decNumber functions: */ 46 | /* */ 47 | /* clamp -- must be either 0 or 1 */ 48 | /* digits -- must be in the range 1 through 999999999 */ 49 | /* emax -- must be in the range 0 through 999999999 */ 50 | /* emin -- must be in the range 0 through -999999999 */ 51 | /* extended -- must be either 0 or 1 [present only if DECSUBSET] */ 52 | /* traps -- only defined bits may be set */ 53 | /* */ 54 | /* ------------------------------------------------------------------ */ 55 | 56 | #include "mnl0.h" 57 | MNL_DSO_HIDE_BEGIN 58 | 59 | #if !defined(DECCONTEXT) 60 | #define DECCONTEXT 61 | #define DECCNAME "decContext" /* Short name */ 62 | #define DECCFULLNAME "Decimal Context Descriptor" /* Verbose name */ 63 | #define DECCAUTHOR "Mike Cowlishaw" /* Who to blame */ 64 | 65 | #if !defined(int32_t) 66 | MNL_DSO_UNHIDE_BEGIN 67 | #include /* C99 standard integers */ 68 | MNL_DSO_UNHIDE_END 69 | #endif 70 | MNL_DSO_UNHIDE_BEGIN 71 | #include /* for printf, etc. */ 72 | #include /* for traps */ 73 | MNL_DSO_UNHIDE_END 74 | 75 | /* Extended flags setting -- set this to 0 to use only IEEE flags */ 76 | #if !defined(DECEXTFLAG) 77 | #define DECEXTFLAG 1 /* 1=enable extended flags */ 78 | #endif 79 | 80 | /* Conditional code flag -- set this to 0 for best performance */ 81 | #if !defined(DECSUBSET) 82 | #define DECSUBSET 0 /* 1=enable subset arithmetic */ 83 | #endif 84 | 85 | /* Context for operations, with associated constants */ 86 | enum rounding { 87 | DEC_ROUND_CEILING, /* round towards +infinity */ 88 | DEC_ROUND_UP, /* round away from 0 */ 89 | DEC_ROUND_HALF_UP, /* 0.5 rounds up */ 90 | DEC_ROUND_HALF_EVEN, /* 0.5 rounds to nearest even */ 91 | DEC_ROUND_HALF_DOWN, /* 0.5 rounds down */ 92 | DEC_ROUND_DOWN, /* round towards 0 (truncate) */ 93 | DEC_ROUND_FLOOR, /* round towards -infinity */ 94 | DEC_ROUND_05UP, /* round for reround */ 95 | DEC_ROUND_MAX /* enum must be less than this */ 96 | }; 97 | #define DEC_ROUND_DEFAULT DEC_ROUND_HALF_EVEN; 98 | 99 | typedef struct { 100 | int32_t digits; /* working precision */ 101 | int32_t emax; /* maximum positive exponent */ 102 | int32_t emin; /* minimum negative exponent */ 103 | enum rounding round; /* rounding mode */ 104 | uint32_t traps; /* trap-enabler flags */ 105 | uint32_t status; /* status flags */ 106 | uint8_t clamp; /* flag: apply IEEE exponent clamp */ 107 | #if DECSUBSET 108 | uint8_t extended; /* flag: special-values allowed */ 109 | #endif 110 | } decContext; 111 | 112 | /* Maxima and Minima for context settings */ 113 | #define DEC_MAX_DIGITS 999999999 114 | #define DEC_MIN_DIGITS 1 115 | #define DEC_MAX_EMAX 999999999 116 | #define DEC_MIN_EMAX 0 117 | #define DEC_MAX_EMIN 0 118 | #define DEC_MIN_EMIN -999999999 119 | #define DEC_MAX_MATH 999999 /* max emax, etc., for math funcs. */ 120 | 121 | /* Classifications for decimal numbers, aligned with 754 (note that */ 122 | /* 'normal' and 'subnormal' are meaningful only with a decContext */ 123 | /* or a fixed size format). */ 124 | enum decClass { 125 | DEC_CLASS_SNAN, 126 | DEC_CLASS_QNAN, 127 | DEC_CLASS_NEG_INF, 128 | DEC_CLASS_NEG_NORMAL, 129 | DEC_CLASS_NEG_SUBNORMAL, 130 | DEC_CLASS_NEG_ZERO, 131 | DEC_CLASS_POS_ZERO, 132 | DEC_CLASS_POS_SUBNORMAL, 133 | DEC_CLASS_POS_NORMAL, 134 | DEC_CLASS_POS_INF 135 | }; 136 | /* Strings for the decClasses */ 137 | #define DEC_ClassString_SN "sNaN" 138 | #define DEC_ClassString_QN "NaN" 139 | #define DEC_ClassString_NI "-Infinity" 140 | #define DEC_ClassString_NN "-Normal" 141 | #define DEC_ClassString_NS "-Subnormal" 142 | #define DEC_ClassString_NZ "-Zero" 143 | #define DEC_ClassString_PZ "+Zero" 144 | #define DEC_ClassString_PS "+Subnormal" 145 | #define DEC_ClassString_PN "+Normal" 146 | #define DEC_ClassString_PI "+Infinity" 147 | #define DEC_ClassString_UN "Invalid" 148 | 149 | /* Trap-enabler and Status flags (exceptional conditions), and */ 150 | /* their names. The top byte is reserved for internal use */ 151 | #if DECEXTFLAG 152 | /* Extended flags */ 153 | #define DEC_Conversion_syntax 0x00000001 154 | #define DEC_Division_by_zero 0x00000002 155 | #define DEC_Division_impossible 0x00000004 156 | #define DEC_Division_undefined 0x00000008 157 | #define DEC_Insufficient_storage 0x00000010 /* [when malloc fails] */ 158 | #define DEC_Inexact 0x00000020 159 | #define DEC_Invalid_context 0x00000040 160 | #define DEC_Invalid_operation 0x00000080 161 | #if DECSUBSET 162 | #define DEC_Lost_digits 0x00000100 163 | #endif 164 | #define DEC_Overflow 0x00000200 165 | #define DEC_Clamped 0x00000400 166 | #define DEC_Rounded 0x00000800 167 | #define DEC_Subnormal 0x00001000 168 | #define DEC_Underflow 0x00002000 169 | #else 170 | /* IEEE flags only */ 171 | #define DEC_Conversion_syntax 0x00000010 172 | #define DEC_Division_by_zero 0x00000002 173 | #define DEC_Division_impossible 0x00000010 174 | #define DEC_Division_undefined 0x00000010 175 | #define DEC_Insufficient_storage 0x00000010 /* [when malloc fails] */ 176 | #define DEC_Inexact 0x00000001 177 | #define DEC_Invalid_context 0x00000010 178 | #define DEC_Invalid_operation 0x00000010 179 | #if DECSUBSET 180 | #define DEC_Lost_digits 0x00000000 181 | #endif 182 | #define DEC_Overflow 0x00000008 183 | #define DEC_Clamped 0x00000000 184 | #define DEC_Rounded 0x00000000 185 | #define DEC_Subnormal 0x00000000 186 | #define DEC_Underflow 0x00000004 187 | #endif 188 | 189 | /* IEEE 754 groupings for the flags */ 190 | /* [DEC_Clamped, DEC_Lost_digits, DEC_Rounded, and DEC_Subnormal */ 191 | /* are not in IEEE 754] */ 192 | #define DEC_IEEE_754_Division_by_zero (DEC_Division_by_zero) 193 | #if DECSUBSET 194 | #define DEC_IEEE_754_Inexact (DEC_Inexact | DEC_Lost_digits) 195 | #else 196 | #define DEC_IEEE_754_Inexact (DEC_Inexact) 197 | #endif 198 | #define DEC_IEEE_754_Invalid_operation (DEC_Conversion_syntax | \ 199 | DEC_Division_impossible | \ 200 | DEC_Division_undefined | \ 201 | DEC_Insufficient_storage | \ 202 | DEC_Invalid_context | \ 203 | DEC_Invalid_operation) 204 | #define DEC_IEEE_754_Overflow (DEC_Overflow) 205 | #define DEC_IEEE_754_Underflow (DEC_Underflow) 206 | 207 | /* flags which are normally errors (result is qNaN, infinite, or 0) */ 208 | #define DEC_Errors (DEC_IEEE_754_Division_by_zero | \ 209 | DEC_IEEE_754_Invalid_operation | \ 210 | DEC_IEEE_754_Overflow | DEC_IEEE_754_Underflow) 211 | /* flags which cause a result to become qNaN */ 212 | #define DEC_NaNs DEC_IEEE_754_Invalid_operation 213 | 214 | /* flags which are normally for information only (finite results) */ 215 | #if DECSUBSET 216 | #define DEC_Information (DEC_Clamped | DEC_Rounded | DEC_Inexact \ 217 | | DEC_Lost_digits) 218 | #else 219 | #define DEC_Information (DEC_Clamped | DEC_Rounded | DEC_Inexact) 220 | #endif 221 | 222 | /* IEEE 854 names (for compatibility with older decNumber versions) */ 223 | #define DEC_IEEE_854_Division_by_zero DEC_IEEE_754_Division_by_zero 224 | #define DEC_IEEE_854_Inexact DEC_IEEE_754_Inexact 225 | #define DEC_IEEE_854_Invalid_operation DEC_IEEE_754_Invalid_operation 226 | #define DEC_IEEE_854_Overflow DEC_IEEE_754_Overflow 227 | #define DEC_IEEE_854_Underflow DEC_IEEE_754_Underflow 228 | 229 | /* Name strings for the exceptional conditions */ 230 | #define DEC_Condition_CS "Conversion syntax" 231 | #define DEC_Condition_DZ "Division by zero" 232 | #define DEC_Condition_DI "Division impossible" 233 | #define DEC_Condition_DU "Division undefined" 234 | #define DEC_Condition_IE "Inexact" 235 | #define DEC_Condition_IS "Insufficient storage" 236 | #define DEC_Condition_IC "Invalid context" 237 | #define DEC_Condition_IO "Invalid operation" 238 | #if DECSUBSET 239 | #define DEC_Condition_LD "Lost digits" 240 | #endif 241 | #define DEC_Condition_OV "Overflow" 242 | #define DEC_Condition_PA "Clamped" 243 | #define DEC_Condition_RO "Rounded" 244 | #define DEC_Condition_SU "Subnormal" 245 | #define DEC_Condition_UN "Underflow" 246 | #define DEC_Condition_ZE "No status" 247 | #define DEC_Condition_MU "Multiple status" 248 | #define DEC_Condition_Length 21 /* length of the longest string, */ 249 | /* including terminator */ 250 | 251 | /* Initialization descriptors, used by decContextDefault */ 252 | #define DEC_INIT_BASE 0 253 | #define DEC_INIT_DECIMAL32 32 254 | #define DEC_INIT_DECIMAL64 64 255 | #define DEC_INIT_DECIMAL128 128 256 | /* Synonyms */ 257 | #define DEC_INIT_DECSINGLE DEC_INIT_DECIMAL32 258 | #define DEC_INIT_DECDOUBLE DEC_INIT_DECIMAL64 259 | #define DEC_INIT_DECQUAD DEC_INIT_DECIMAL128 260 | 261 | #ifdef __cplusplus 262 | extern "C" { 263 | #endif 264 | 265 | /* decContext routines */ 266 | extern decContext * decContextClearStatus(decContext *, uint32_t); 267 | extern decContext * decContextDefault(decContext *, int32_t); 268 | extern enum rounding decContextGetRounding(decContext *); 269 | extern uint32_t decContextGetStatus(decContext *); 270 | extern decContext * decContextRestoreStatus(decContext *, uint32_t, uint32_t); 271 | extern uint32_t decContextSaveStatus(decContext *, uint32_t); 272 | extern decContext * decContextSetRounding(decContext *, enum rounding); 273 | extern decContext * decContextSetStatus(decContext *, uint32_t); 274 | extern decContext * decContextSetStatusFromString(decContext *, const char *); 275 | extern decContext * decContextSetStatusFromStringQuiet(decContext *, const char *); 276 | extern decContext * decContextSetStatusQuiet(decContext *, uint32_t); 277 | extern const char * decContextStatusToString(const decContext *); 278 | extern int32_t decContextTestEndian(uint8_t); 279 | extern uint32_t decContextTestSavedStatus(uint32_t, uint32_t); 280 | extern uint32_t decContextTestStatus(decContext *, uint32_t); 281 | extern decContext * decContextZeroStatus(decContext *); 282 | 283 | #ifdef __cplusplus 284 | } 285 | #endif 286 | 287 | #endif 288 | 289 | MNL_DSO_HIDE_END 290 | -------------------------------------------------------------------------------- /libdecnumber/decDouble.c: -------------------------------------------------------------------------------- 1 | // libdecnumber/decDouble.c 2 | 3 | /* Copyright (C) 2018, 2019, 2020 Alexey Protasov (AKA Alex or rusini) 4 | 5 | This file is part of MANOOL. 6 | 7 | MANOOL is free software: you can redistribute it and/or modify it under the terms of the version 3 of the GNU General Public License 8 | as published by the Free Software Foundation (and only version 3). 9 | 10 | MANOOL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License along with MANOOL. If not, see . */ 14 | 15 | 16 | // This file incorporates work covered by the following copyright and 17 | // permission notice: 18 | 19 | /* ------------------------------------------------------------------ */ 20 | /* decDouble.c -- decDouble operations module */ 21 | /* ------------------------------------------------------------------ */ 22 | /* Copyright (c) IBM Corporation, 2000, 2010. All rights reserved. */ 23 | /* */ 24 | /* This software is made available under the terms of the */ 25 | /* ICU License -- ICU 1.8.1 and later. */ 26 | /* */ 27 | /* The description and User's Guide ("The decNumber C Library") for */ 28 | /* this software is included in the package as decNumber.pdf. This */ 29 | /* document is also available in HTML, together with specifications, */ 30 | /* testcases, and Web links, on the General Decimal Arithmetic page. */ 31 | /* */ 32 | /* Please send comments, suggestions, and corrections to the author: */ 33 | /* mfc@uk.ibm.com */ 34 | /* Mike Cowlishaw, IBM Fellow */ 35 | /* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */ 36 | /* ------------------------------------------------------------------ */ 37 | /* This module comprises decDouble operations (including conversions) */ 38 | /* ------------------------------------------------------------------ */ 39 | 40 | #include "config.h" 41 | #include "mnl0.h" 42 | MNL_DSO_HIDE_BEGIN 43 | 44 | #include "decContext.h" // public includes 45 | #include "decDouble.h" // .. 46 | 47 | /* Constant mappings for shared code */ 48 | #define DECPMAX DECDOUBLE_Pmax 49 | #define DECEMIN DECDOUBLE_Emin 50 | #define DECEMAX DECDOUBLE_Emax 51 | #define DECEMAXD DECDOUBLE_EmaxD 52 | #define DECBYTES DECDOUBLE_Bytes 53 | #define DECSTRING DECDOUBLE_String 54 | #define DECECONL DECDOUBLE_EconL 55 | #define DECBIAS DECDOUBLE_Bias 56 | #define DECLETS DECDOUBLE_Declets 57 | #define DECQTINY (-DECDOUBLE_Bias) 58 | // parameters of next-wider format 59 | #define DECWBYTES DECQUAD_Bytes 60 | #define DECWPMAX DECQUAD_Pmax 61 | #define DECWECONL DECQUAD_EconL 62 | #define DECWBIAS DECQUAD_Bias 63 | 64 | /* Type and function mappings for shared code */ 65 | #define decFloat decDouble // Type name 66 | #define decFloatWider decQuad // Type name 67 | 68 | // Utilities and conversions (binary results, extractors, etc.) 69 | #define decFloatFromBCD decDoubleFromBCD 70 | #define decFloatFromInt32 decDoubleFromInt32 71 | #define decFloatFromPacked decDoubleFromPacked 72 | #define decFloatFromPackedChecked decDoubleFromPackedChecked 73 | #define decFloatFromString decDoubleFromString 74 | #define decFloatFromUInt32 decDoubleFromUInt32 75 | #define decFloatFromWider decDoubleFromWider 76 | #define decFloatGetCoefficient decDoubleGetCoefficient 77 | #define decFloatGetExponent decDoubleGetExponent 78 | #define decFloatSetCoefficient decDoubleSetCoefficient 79 | #define decFloatSetExponent decDoubleSetExponent 80 | #define decFloatShow decDoubleShow 81 | #define decFloatToBCD decDoubleToBCD 82 | #define decFloatToEngString decDoubleToEngString 83 | #define decFloatToInt32 decDoubleToInt32 84 | #define decFloatToInt32Exact decDoubleToInt32Exact 85 | #define decFloatToPacked decDoubleToPacked 86 | #define decFloatToString decDoubleToString 87 | #define decFloatToUInt32 decDoubleToUInt32 88 | #define decFloatToUInt32Exact decDoubleToUInt32Exact 89 | #define decFloatToWider decDoubleToWider 90 | #define decFloatZero decDoubleZero 91 | 92 | // Computational (result is a decFloat) 93 | #define decFloatAbs decDoubleAbs 94 | #define decFloatAdd decDoubleAdd 95 | #define decFloatAnd decDoubleAnd 96 | #define decFloatDivide decDoubleDivide 97 | #define decFloatDivideInteger decDoubleDivideInteger 98 | #define decFloatFMA decDoubleFMA 99 | #define decFloatInvert decDoubleInvert 100 | #define decFloatLogB decDoubleLogB 101 | #define decFloatMax decDoubleMax 102 | #define decFloatMaxMag decDoubleMaxMag 103 | #define decFloatMin decDoubleMin 104 | #define decFloatMinMag decDoubleMinMag 105 | #define decFloatMinus decDoubleMinus 106 | #define decFloatMultiply decDoubleMultiply 107 | #define decFloatNextMinus decDoubleNextMinus 108 | #define decFloatNextPlus decDoubleNextPlus 109 | #define decFloatNextToward decDoubleNextToward 110 | #define decFloatOr decDoubleOr 111 | #define decFloatPlus decDoublePlus 112 | #define decFloatQuantize decDoubleQuantize 113 | #define decFloatReduce decDoubleReduce 114 | #define decFloatRemainder decDoubleRemainder 115 | #define decFloatRemainderNear decDoubleRemainderNear 116 | #define decFloatRotate decDoubleRotate 117 | #define decFloatScaleB decDoubleScaleB 118 | #define decFloatShift decDoubleShift 119 | #define decFloatSubtract decDoubleSubtract 120 | #define decFloatToIntegralValue decDoubleToIntegralValue 121 | #define decFloatToIntegralExact decDoubleToIntegralExact 122 | #define decFloatXor decDoubleXor 123 | 124 | // Comparisons 125 | #define decFloatCompare decDoubleCompare 126 | #define decFloatCompareSignal decDoubleCompareSignal 127 | #define decFloatCompareTotal decDoubleCompareTotal 128 | #define decFloatCompareTotalMag decDoubleCompareTotalMag 129 | 130 | // Copies 131 | #define decFloatCanonical decDoubleCanonical 132 | #define decFloatCopy decDoubleCopy 133 | #define decFloatCopyAbs decDoubleCopyAbs 134 | #define decFloatCopyNegate decDoubleCopyNegate 135 | #define decFloatCopySign decDoubleCopySign 136 | 137 | // Non-computational 138 | #define decFloatClass decDoubleClass 139 | #define decFloatClassString decDoubleClassString 140 | #define decFloatDigits decDoubleDigits 141 | #define decFloatIsCanonical decDoubleIsCanonical 142 | #define decFloatIsFinite decDoubleIsFinite 143 | #define decFloatIsInfinite decDoubleIsInfinite 144 | #define decFloatIsInteger decDoubleIsInteger 145 | #define decFloatIsLogical decDoubleIsLogical 146 | #define decFloatIsNaN decDoubleIsNaN 147 | #define decFloatIsNegative decDoubleIsNegative 148 | #define decFloatIsNormal decDoubleIsNormal 149 | #define decFloatIsPositive decDoubleIsPositive 150 | #define decFloatIsSignaling decDoubleIsSignaling 151 | #define decFloatIsSignalling decDoubleIsSignalling 152 | #define decFloatIsSigned decDoubleIsSigned 153 | #define decFloatIsSubnormal decDoubleIsSubnormal 154 | #define decFloatIsZero decDoubleIsZero 155 | #define decFloatRadix decDoubleRadix 156 | #define decFloatSameQuantum decDoubleSameQuantum 157 | #define decFloatVersion decDoubleVersion 158 | 159 | #include "decNumberLocal.h" // local includes (need DECPMAX) 160 | #include "decCommon.c" // non-arithmetic decFloat routines 161 | #include "decBasic.c" // basic formats routines 162 | 163 | MNL_DSO_HIDE_END 164 | -------------------------------------------------------------------------------- /libdecnumber/decDouble.h: -------------------------------------------------------------------------------- 1 | // libdecnumber/decDouble.h 2 | 3 | /* Copyright (C) 2018, 2019, 2020 Alexey Protasov (AKA Alex or rusini) 4 | 5 | This file is part of MANOOL. 6 | 7 | MANOOL is free software: you can redistribute it and/or modify it under the terms of the version 3 of the GNU General Public License 8 | as published by the Free Software Foundation (and only version 3). 9 | 10 | MANOOL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License along with MANOOL. If not, see . */ 14 | 15 | 16 | // This file incorporates work covered by the following copyright and 17 | // permission notice: 18 | 19 | /* ------------------------------------------------------------------ */ 20 | /* decDouble.h -- Decimal 64-bit format module header */ 21 | /* ------------------------------------------------------------------ */ 22 | /* Copyright (c) IBM Corporation, 2000, 2010. All rights reserved. */ 23 | /* */ 24 | /* This software is made available under the terms of the */ 25 | /* ICU License -- ICU 1.8.1 and later. */ 26 | /* */ 27 | /* The description and User's Guide ("The decNumber C Library") for */ 28 | /* this software is included in the package as decNumber.pdf. This */ 29 | /* document is also available in HTML, together with specifications, */ 30 | /* testcases, and Web links, on the General Decimal Arithmetic page. */ 31 | /* */ 32 | /* Please send comments, suggestions, and corrections to the author: */ 33 | /* mfc@uk.ibm.com */ 34 | /* Mike Cowlishaw, IBM Fellow */ 35 | /* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */ 36 | /* ------------------------------------------------------------------ */ 37 | 38 | #include "mnl0.h" 39 | MNL_DSO_HIDE_BEGIN 40 | 41 | #if !defined(DECDOUBLE) 42 | #define DECDOUBLE 43 | 44 | #define DECDOUBLENAME "decimalDouble" /* Short name */ 45 | #define DECDOUBLETITLE "Decimal 64-bit datum" /* Verbose name */ 46 | #define DECDOUBLEAUTHOR "Mike Cowlishaw" /* Who to blame */ 47 | 48 | /* parameters for decDoubles */ 49 | #define DECDOUBLE_Bytes 8 /* length */ 50 | #define DECDOUBLE_Pmax 16 /* maximum precision (digits) */ 51 | #define DECDOUBLE_Emin -383 /* minimum adjusted exponent */ 52 | #define DECDOUBLE_Emax 384 /* maximum adjusted exponent */ 53 | #define DECDOUBLE_EmaxD 3 /* maximum exponent digits */ 54 | #define DECDOUBLE_Bias 398 /* bias for the exponent */ 55 | #define DECDOUBLE_String 25 /* maximum string length, +1 */ 56 | #define DECDOUBLE_EconL 8 /* exponent continuation length */ 57 | #define DECDOUBLE_Declets 5 /* count of declets */ 58 | /* highest biased exponent (Elimit-1) */ 59 | #define DECDOUBLE_Ehigh (DECDOUBLE_Emax + DECDOUBLE_Bias - (DECDOUBLE_Pmax-1)) 60 | 61 | /* Required includes */ 62 | #include "decContext.h" 63 | #include "decQuad.h" 64 | 65 | /* The decDouble decimal 64-bit type, accessible by all sizes */ 66 | typedef union { 67 | uint8_t bytes[DECDOUBLE_Bytes]; /* fields: 1, 5, 8, 50 bits */ 68 | uint16_t shorts[DECDOUBLE_Bytes/2]; 69 | uint32_t words[DECDOUBLE_Bytes/4]; 70 | #if DECUSE64 71 | uint64_t longs[DECDOUBLE_Bytes/8]; 72 | #endif 73 | } decDouble; 74 | 75 | /* ---------------------------------------------------------------- */ 76 | /* Routines -- implemented as decFloat routines in common files */ 77 | /* ---------------------------------------------------------------- */ 78 | 79 | #ifdef __cplusplus 80 | extern "C" { 81 | #endif 82 | 83 | /* Utilities and conversions, extractors, etc.) */ 84 | extern decDouble * decDoubleFromBCD(decDouble *, int32_t, const uint8_t *, int32_t); 85 | extern decDouble * decDoubleFromInt32(decDouble *, int32_t); 86 | extern decDouble * decDoubleFromPacked(decDouble *, int32_t, const uint8_t *); 87 | extern decDouble * decDoubleFromPackedChecked(decDouble *, int32_t, const uint8_t *); 88 | extern decDouble * decDoubleFromString(decDouble *, const char *, decContext *); 89 | extern decDouble * decDoubleFromUInt32(decDouble *, uint32_t); 90 | extern decDouble * decDoubleFromWider(decDouble *, const decQuad *, decContext *); 91 | extern int32_t decDoubleGetCoefficient(const decDouble *, uint8_t *); 92 | extern int32_t decDoubleGetExponent(const decDouble *); 93 | extern decDouble * decDoubleSetCoefficient(decDouble *, const uint8_t *, int32_t); 94 | extern decDouble * decDoubleSetExponent(decDouble *, decContext *, int32_t); 95 | extern void decDoubleShow(const decDouble *, const char *); 96 | extern int32_t decDoubleToBCD(const decDouble *, int32_t *, uint8_t *); 97 | extern char * decDoubleToEngString(const decDouble *, char *); 98 | extern int32_t decDoubleToInt32(const decDouble *, decContext *, enum rounding); 99 | extern int32_t decDoubleToInt32Exact(const decDouble *, decContext *, enum rounding); 100 | extern int32_t decDoubleToPacked(const decDouble *, int32_t *, uint8_t *); 101 | extern char * decDoubleToString(const decDouble *, char *); 102 | extern uint32_t decDoubleToUInt32(const decDouble *, decContext *, enum rounding); 103 | extern uint32_t decDoubleToUInt32Exact(const decDouble *, decContext *, enum rounding); 104 | extern decQuad * decDoubleToWider(const decDouble *, decQuad *); 105 | extern decDouble * decDoubleZero(decDouble *); 106 | 107 | /* Computational (result is a decDouble) */ 108 | extern decDouble * decDoubleAbs(decDouble *, const decDouble *, decContext *); 109 | extern decDouble * decDoubleAdd(decDouble *, const decDouble *, const decDouble *, decContext *); 110 | extern decDouble * decDoubleAnd(decDouble *, const decDouble *, const decDouble *, decContext *); 111 | extern decDouble * decDoubleDivide(decDouble *, const decDouble *, const decDouble *, decContext *); 112 | extern decDouble * decDoubleDivideInteger(decDouble *, const decDouble *, const decDouble *, decContext *); 113 | extern decDouble * decDoubleFMA(decDouble *, const decDouble *, const decDouble *, const decDouble *, decContext *); 114 | extern decDouble * decDoubleInvert(decDouble *, const decDouble *, decContext *); 115 | extern decDouble * decDoubleLogB(decDouble *, const decDouble *, decContext *); 116 | extern decDouble * decDoubleMax(decDouble *, const decDouble *, const decDouble *, decContext *); 117 | extern decDouble * decDoubleMaxMag(decDouble *, const decDouble *, const decDouble *, decContext *); 118 | extern decDouble * decDoubleMin(decDouble *, const decDouble *, const decDouble *, decContext *); 119 | extern decDouble * decDoubleMinMag(decDouble *, const decDouble *, const decDouble *, decContext *); 120 | extern decDouble * decDoubleMinus(decDouble *, const decDouble *, decContext *); 121 | extern decDouble * decDoubleMultiply(decDouble *, const decDouble *, const decDouble *, decContext *); 122 | extern decDouble * decDoubleNextMinus(decDouble *, const decDouble *, decContext *); 123 | extern decDouble * decDoubleNextPlus(decDouble *, const decDouble *, decContext *); 124 | extern decDouble * decDoubleNextToward(decDouble *, const decDouble *, const decDouble *, decContext *); 125 | extern decDouble * decDoubleOr(decDouble *, const decDouble *, const decDouble *, decContext *); 126 | extern decDouble * decDoublePlus(decDouble *, const decDouble *, decContext *); 127 | extern decDouble * decDoubleQuantize(decDouble *, const decDouble *, const decDouble *, decContext *); 128 | extern decDouble * decDoubleReduce(decDouble *, const decDouble *, decContext *); 129 | extern decDouble * decDoubleRemainder(decDouble *, const decDouble *, const decDouble *, decContext *); 130 | extern decDouble * decDoubleRemainderNear(decDouble *, const decDouble *, const decDouble *, decContext *); 131 | extern decDouble * decDoubleRotate(decDouble *, const decDouble *, const decDouble *, decContext *); 132 | extern decDouble * decDoubleScaleB(decDouble *, const decDouble *, const decDouble *, decContext *); 133 | extern decDouble * decDoubleShift(decDouble *, const decDouble *, const decDouble *, decContext *); 134 | extern decDouble * decDoubleSubtract(decDouble *, const decDouble *, const decDouble *, decContext *); 135 | extern decDouble * decDoubleToIntegralValue(decDouble *, const decDouble *, decContext *, enum rounding); 136 | extern decDouble * decDoubleToIntegralExact(decDouble *, const decDouble *, decContext *); 137 | extern decDouble * decDoubleXor(decDouble *, const decDouble *, const decDouble *, decContext *); 138 | 139 | /* Comparisons */ 140 | extern decDouble * decDoubleCompare(decDouble *, const decDouble *, const decDouble *, decContext *); 141 | extern decDouble * decDoubleCompareSignal(decDouble *, const decDouble *, const decDouble *, decContext *); 142 | extern decDouble * decDoubleCompareTotal(decDouble *, const decDouble *, const decDouble *); 143 | extern decDouble * decDoubleCompareTotalMag(decDouble *, const decDouble *, const decDouble *); 144 | 145 | /* Copies */ 146 | extern decDouble * decDoubleCanonical(decDouble *, const decDouble *); 147 | extern decDouble * decDoubleCopy(decDouble *, const decDouble *); 148 | extern decDouble * decDoubleCopyAbs(decDouble *, const decDouble *); 149 | extern decDouble * decDoubleCopyNegate(decDouble *, const decDouble *); 150 | extern decDouble * decDoubleCopySign(decDouble *, const decDouble *, const decDouble *); 151 | 152 | /* Non-computational */ 153 | extern enum decClass decDoubleClass(const decDouble *); 154 | extern const char * decDoubleClassString(const decDouble *); 155 | extern uint32_t decDoubleDigits(const decDouble *); 156 | extern uint32_t decDoubleIsCanonical(const decDouble *); 157 | extern uint32_t decDoubleIsFinite(const decDouble *); 158 | extern uint32_t decDoubleIsInfinite(const decDouble *); 159 | extern uint32_t decDoubleIsInteger(const decDouble *); 160 | extern uint32_t decDoubleIsLogical(const decDouble *); 161 | extern uint32_t decDoubleIsNaN(const decDouble *); 162 | extern uint32_t decDoubleIsNegative(const decDouble *); 163 | extern uint32_t decDoubleIsNormal(const decDouble *); 164 | extern uint32_t decDoubleIsPositive(const decDouble *); 165 | extern uint32_t decDoubleIsSignaling(const decDouble *); 166 | extern uint32_t decDoubleIsSignalling(const decDouble *); 167 | extern uint32_t decDoubleIsSigned(const decDouble *); 168 | extern uint32_t decDoubleIsSubnormal(const decDouble *); 169 | extern uint32_t decDoubleIsZero(const decDouble *); 170 | extern uint32_t decDoubleRadix(const decDouble *); 171 | extern uint32_t decDoubleSameQuantum(const decDouble *, const decDouble *); 172 | extern const char * decDoubleVersion(void); 173 | 174 | #ifdef __cplusplus 175 | } 176 | #endif 177 | 178 | /* decNumber conversions; these are implemented as macros so as not */ 179 | /* to force a dependency on decimal64 and decNumber in decDouble. */ 180 | /* decDoubleFromNumber returns a decimal64 * to avoid warnings. */ 181 | #if 0 182 | #define decDoubleToNumber(dq, dn) decimal64ToNumber((decimal64 *)(dq), dn) 183 | #define decDoubleFromNumber(dq, dn, set) decimal64FromNumber((decimal64 *)(dq), dn, set) 184 | #else 185 | #define decDoubleToNumber(dq, dn) (MNL_BARRIER(), decimal64ToNumber((decimal64 *)(dq), dn)) 186 | #define decDoubleFromNumber(dq, dn, set) (MNL_BARRIER(), decimal64FromNumber((decimal64 *)(dq), dn, set)) 187 | #endif 188 | 189 | #endif 190 | 191 | MNL_DSO_HIDE_END 192 | -------------------------------------------------------------------------------- /libdecnumber/decNumber.h: -------------------------------------------------------------------------------- 1 | // libdecnumber/decNumber.h 2 | 3 | /* Copyright (C) 2018, 2019, 2020 Alexey Protasov (AKA Alex or rusini) 4 | 5 | This file is part of MANOOL. 6 | 7 | MANOOL is free software: you can redistribute it and/or modify it under the terms of the version 3 of the GNU General Public License 8 | as published by the Free Software Foundation (and only version 3). 9 | 10 | MANOOL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License along with MANOOL. If not, see . */ 14 | 15 | 16 | // This file incorporates work covered by the following copyright and 17 | // permission notice: 18 | 19 | /* ------------------------------------------------------------------ */ 20 | /* Decimal Number arithmetic module header */ 21 | /* ------------------------------------------------------------------ */ 22 | /* Copyright (c) IBM Corporation, 2000, 2010. All rights reserved. */ 23 | /* */ 24 | /* This software is made available under the terms of the */ 25 | /* ICU License -- ICU 1.8.1 and later. */ 26 | /* */ 27 | /* The description and User's Guide ("The decNumber C Library") for */ 28 | /* this software is called decNumber.pdf. This document is */ 29 | /* available, together with arithmetic and format specifications, */ 30 | /* testcases, and Web links, on the General Decimal Arithmetic page. */ 31 | /* */ 32 | /* Please send comments, suggestions, and corrections to the author: */ 33 | /* mfc@uk.ibm.com */ 34 | /* Mike Cowlishaw, IBM Fellow */ 35 | /* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */ 36 | /* ------------------------------------------------------------------ */ 37 | 38 | #include "mnl0.h" 39 | MNL_DSO_HIDE_BEGIN 40 | 41 | #if !defined(DECNUMBER) 42 | #define DECNUMBER 43 | #define DECNAME "decNumber" /* Short name */ 44 | #define DECFULLNAME "Decimal Number Module" /* Verbose name */ 45 | #define DECAUTHOR "Mike Cowlishaw" /* Who to blame */ 46 | 47 | #if !defined(DECCONTEXT) 48 | #include "decContext.h" 49 | #endif 50 | 51 | /* Bit settings for decNumber.bits */ 52 | #define DECNEG 0x80 /* Sign; 1=negative, 0=positive or zero */ 53 | #define DECINF 0x40 /* 1=Infinity */ 54 | #define DECNAN 0x20 /* 1=NaN */ 55 | #define DECSNAN 0x10 /* 1=sNaN */ 56 | /* The remaining bits are reserved; they must be 0 */ 57 | #define DECSPECIAL (DECINF|DECNAN|DECSNAN) /* any special value */ 58 | 59 | /* Define the decNumber data structure. The size and shape of the */ 60 | /* units array in the structure is determined by the following */ 61 | /* constant. This must not be changed without recompiling the */ 62 | /* decNumber library modules. */ 63 | 64 | #define DECDPUN 3 /* DECimal Digits Per UNit [must be >0 */ 65 | /* and <10; 3 or powers of 2 are best]. */ 66 | 67 | /* DECNUMDIGITS is the default number of digits that can be held in */ 68 | /* the structure. If undefined, 1 is assumed and it is assumed */ 69 | /* that the structure will be immediately followed by extra space, */ 70 | /* as required. DECNUMDIGITS is always >0. */ 71 | #if !defined(DECNUMDIGITS) 72 | #define DECNUMDIGITS 1 73 | #endif 74 | 75 | /* The size (integer data type) of each unit is determined by the */ 76 | /* number of digits it will hold. */ 77 | #if DECDPUN<=2 78 | #define decNumberUnit uint8_t 79 | #elif DECDPUN<=4 80 | #define decNumberUnit uint16_t 81 | #else 82 | #define decNumberUnit uint32_t 83 | #endif 84 | /* The number of units needed is ceil(DECNUMDIGITS/DECDPUN) */ 85 | #define DECNUMUNITS ((DECNUMDIGITS+DECDPUN-1)/DECDPUN) 86 | 87 | /* The data structure... */ 88 | typedef struct { 89 | int32_t digits; /* Count of digits in the coefficient; >0 */ 90 | int32_t exponent; /* Unadjusted exponent, unbiased, in */ 91 | /* range: -1999999997 through 999999999 */ 92 | uint8_t bits; /* Indicator bits (see above) */ 93 | /* Coefficient, from least significant unit */ 94 | decNumberUnit lsu[DECNUMUNITS]; 95 | } decNumber; 96 | 97 | /* Notes: */ 98 | /* 1. If digits is > DECDPUN then there will one or more */ 99 | /* decNumberUnits immediately following the first element of lsu.*/ 100 | /* These contain the remaining (more significant) digits of the */ 101 | /* number, and may be in the lsu array, or may be guaranteed by */ 102 | /* some other mechanism (such as being contained in another */ 103 | /* structure, or being overlaid on dynamically allocated */ 104 | /* storage). */ 105 | /* */ 106 | /* Each integer of the coefficient (except potentially the last) */ 107 | /* contains DECDPUN digits (e.g., a value in the range 0 through */ 108 | /* 99999999 if DECDPUN is 8, or 0 through 999 if DECDPUN is 3). */ 109 | /* */ 110 | /* 2. A decNumber converted to a string may need up to digits+14 */ 111 | /* characters. The worst cases (non-exponential and exponential */ 112 | /* formats) are -0.00000{9...}# and -9.{9...}E+999999999# */ 113 | /* (where # is '\0') */ 114 | 115 | 116 | /* ---------------------------------------------------------------- */ 117 | /* decNumber public functions and macros */ 118 | /* ---------------------------------------------------------------- */ 119 | 120 | #ifdef __cplusplus 121 | extern "C" { 122 | #endif 123 | 124 | /* Conversions */ 125 | decNumber * decNumberFromInt32(decNumber *, int32_t); 126 | decNumber * decNumberFromUInt32(decNumber *, uint32_t); 127 | decNumber * decNumberFromString(decNumber *, const char *, decContext *); 128 | char * decNumberToString(const decNumber *, char *); 129 | char * decNumberToEngString(const decNumber *, char *); 130 | uint32_t decNumberToUInt32(const decNumber *, decContext *); 131 | int32_t decNumberToInt32(const decNumber *, decContext *); 132 | uint8_t * decNumberGetBCD(const decNumber *, uint8_t *); 133 | decNumber * decNumberSetBCD(decNumber *, const uint8_t *, uint32_t); 134 | 135 | /* Operators and elementary functions */ 136 | decNumber * decNumberAbs(decNumber *, const decNumber *, decContext *); 137 | decNumber * decNumberAdd(decNumber *, const decNumber *, const decNumber *, decContext *); 138 | decNumber * decNumberAnd(decNumber *, const decNumber *, const decNumber *, decContext *); 139 | decNumber * decNumberCompare(decNumber *, const decNumber *, const decNumber *, decContext *); 140 | decNumber * decNumberCompareSignal(decNumber *, const decNumber *, const decNumber *, decContext *); 141 | decNumber * decNumberCompareTotal(decNumber *, const decNumber *, const decNumber *, decContext *); 142 | decNumber * decNumberCompareTotalMag(decNumber *, const decNumber *, const decNumber *, decContext *); 143 | decNumber * decNumberDivide(decNumber *, const decNumber *, const decNumber *, decContext *); 144 | decNumber * decNumberDivideInteger(decNumber *, const decNumber *, const decNumber *, decContext *); 145 | decNumber * decNumberExp(decNumber *, const decNumber *, decContext *); 146 | decNumber * decNumberFMA(decNumber *, const decNumber *, const decNumber *, const decNumber *, decContext *); 147 | decNumber * decNumberInvert(decNumber *, const decNumber *, decContext *); 148 | decNumber * decNumberLn(decNumber *, const decNumber *, decContext *); 149 | decNumber * decNumberLogB(decNumber *, const decNumber *, decContext *); 150 | decNumber * decNumberLog10(decNumber *, const decNumber *, decContext *); 151 | decNumber * decNumberMax(decNumber *, const decNumber *, const decNumber *, decContext *); 152 | decNumber * decNumberMaxMag(decNumber *, const decNumber *, const decNumber *, decContext *); 153 | decNumber * decNumberMin(decNumber *, const decNumber *, const decNumber *, decContext *); 154 | decNumber * decNumberMinMag(decNumber *, const decNumber *, const decNumber *, decContext *); 155 | decNumber * decNumberMinus(decNumber *, const decNumber *, decContext *); 156 | decNumber * decNumberMultiply(decNumber *, const decNumber *, const decNumber *, decContext *); 157 | decNumber * decNumberNormalize(decNumber *, const decNumber *, decContext *); 158 | decNumber * decNumberOr(decNumber *, const decNumber *, const decNumber *, decContext *); 159 | decNumber * decNumberPlus(decNumber *, const decNumber *, decContext *); 160 | decNumber * decNumberPower(decNumber *, const decNumber *, const decNumber *, decContext *); 161 | decNumber * decNumberQuantize(decNumber *, const decNumber *, const decNumber *, decContext *); 162 | decNumber * decNumberReduce(decNumber *, const decNumber *, decContext *); 163 | decNumber * decNumberRemainder(decNumber *, const decNumber *, const decNumber *, decContext *); 164 | decNumber * decNumberRemainderNear(decNumber *, const decNumber *, const decNumber *, decContext *); 165 | decNumber * decNumberRescale(decNumber *, const decNumber *, const decNumber *, decContext *); 166 | decNumber * decNumberRotate(decNumber *, const decNumber *, const decNumber *, decContext *); 167 | decNumber * decNumberSameQuantum(decNumber *, const decNumber *, const decNumber *); 168 | decNumber * decNumberScaleB(decNumber *, const decNumber *, const decNumber *, decContext *); 169 | decNumber * decNumberShift(decNumber *, const decNumber *, const decNumber *, decContext *); 170 | decNumber * decNumberSquareRoot(decNumber *, const decNumber *, decContext *); 171 | decNumber * decNumberSubtract(decNumber *, const decNumber *, const decNumber *, decContext *); 172 | decNumber * decNumberToIntegralExact(decNumber *, const decNumber *, decContext *); 173 | decNumber * decNumberToIntegralValue(decNumber *, const decNumber *, decContext *); 174 | decNumber * decNumberXor(decNumber *, const decNumber *, const decNumber *, decContext *); 175 | 176 | /* Utilities */ 177 | enum decClass decNumberClass(const decNumber *, decContext *); 178 | const char * decNumberClassToString(enum decClass); 179 | decNumber * decNumberCopy(decNumber *, const decNumber *); 180 | decNumber * decNumberCopyAbs(decNumber *, const decNumber *); 181 | decNumber * decNumberCopyNegate(decNumber *, const decNumber *); 182 | decNumber * decNumberCopySign(decNumber *, const decNumber *, const decNumber *); 183 | decNumber * decNumberNextMinus(decNumber *, const decNumber *, decContext *); 184 | decNumber * decNumberNextPlus(decNumber *, const decNumber *, decContext *); 185 | decNumber * decNumberNextToward(decNumber *, const decNumber *, const decNumber *, decContext *); 186 | decNumber * decNumberTrim(decNumber *); 187 | const char * decNumberVersion(void); 188 | decNumber * decNumberZero(decNumber *); 189 | 190 | /* Functions for testing decNumbers (normality depends on context) */ 191 | int32_t decNumberIsNormal(const decNumber *, decContext *); 192 | int32_t decNumberIsSubnormal(const decNumber *, decContext *); 193 | 194 | #ifdef __cplusplus 195 | } 196 | #endif 197 | 198 | /* Macros for testing decNumber *dn */ 199 | #define decNumberIsCanonical(dn) (1) /* All decNumbers are saintly */ 200 | #define decNumberIsFinite(dn) (((dn)->bits&DECSPECIAL)==0) 201 | #define decNumberIsInfinite(dn) (((dn)->bits&DECINF)!=0) 202 | #define decNumberIsNaN(dn) (((dn)->bits&(DECNAN|DECSNAN))!=0) 203 | #define decNumberIsNegative(dn) (((dn)->bits&DECNEG)!=0) 204 | #define decNumberIsQNaN(dn) (((dn)->bits&(DECNAN))!=0) 205 | #define decNumberIsSNaN(dn) (((dn)->bits&(DECSNAN))!=0) 206 | #define decNumberIsSpecial(dn) (((dn)->bits&DECSPECIAL)!=0) 207 | #define decNumberIsZero(dn) (*(dn)->lsu==0 \ 208 | && (dn)->digits==1 \ 209 | && (((dn)->bits&DECSPECIAL)==0)) 210 | #define decNumberRadix(dn) (10) 211 | 212 | #endif 213 | 214 | MNL_DSO_HIDE_END 215 | -------------------------------------------------------------------------------- /libdecnumber/decQuad.c: -------------------------------------------------------------------------------- 1 | // libdecnumber/decQuad.c 2 | 3 | /* Copyright (C) 2018, 2019, 2020 Alexey Protasov (AKA Alex or rusini) 4 | 5 | This file is part of MANOOL. 6 | 7 | MANOOL is free software: you can redistribute it and/or modify it under the terms of the version 3 of the GNU General Public License 8 | as published by the Free Software Foundation (and only version 3). 9 | 10 | MANOOL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License along with MANOOL. If not, see . */ 14 | 15 | 16 | // This file incorporates work covered by the following copyright and 17 | // permission notice: 18 | 19 | /* ------------------------------------------------------------------ */ 20 | /* decQuad.c -- decQuad operations module */ 21 | /* ------------------------------------------------------------------ */ 22 | /* Copyright (c) IBM Corporation, 2000, 2010. All rights reserved. */ 23 | /* */ 24 | /* This software is made available under the terms of the */ 25 | /* ICU License -- ICU 1.8.1 and later. */ 26 | /* */ 27 | /* The description and User's Guide ("The decNumber C Library") for */ 28 | /* this software is included in the package as decNumber.pdf. This */ 29 | /* document is also available in HTML, together with specifications, */ 30 | /* testcases, and Web links, on the General Decimal Arithmetic page. */ 31 | /* */ 32 | /* Please send comments, suggestions, and corrections to the author: */ 33 | /* mfc@uk.ibm.com */ 34 | /* Mike Cowlishaw, IBM Fellow */ 35 | /* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */ 36 | /* ------------------------------------------------------------------ */ 37 | /* This module comprises decQuad operations (including conversions) */ 38 | /* ------------------------------------------------------------------ */ 39 | 40 | #include "config.h" 41 | #include "mnl0.h" 42 | MNL_DSO_HIDE_BEGIN 43 | 44 | /* Constant mappings for shared code */ 45 | #define DECPMAX DECQUAD_Pmax 46 | #define DECEMIN DECQUAD_Emin 47 | #define DECEMAX DECQUAD_Emax 48 | #define DECEMAXD DECQUAD_EmaxD 49 | #define DECBYTES DECQUAD_Bytes 50 | #define DECSTRING DECQUAD_String 51 | #define DECECONL DECQUAD_EconL 52 | #define DECBIAS DECQUAD_Bias 53 | #define DECLETS DECQUAD_Declets 54 | #define DECQTINY (-DECQUAD_Bias) 55 | 56 | /* Type and function mappings for shared code */ 57 | #define decFloat decQuad // Type name 58 | 59 | // Utilities and conversions (binary results, extractors, etc.) 60 | #define decFloatFromBCD decQuadFromBCD 61 | #define decFloatFromInt32 decQuadFromInt32 62 | #define decFloatFromPacked decQuadFromPacked 63 | #define decFloatFromPackedChecked decQuadFromPackedChecked 64 | #define decFloatFromString decQuadFromString 65 | #define decFloatFromUInt32 decQuadFromUInt32 66 | #define decFloatFromWider decQuadFromWider 67 | #define decFloatGetCoefficient decQuadGetCoefficient 68 | #define decFloatGetExponent decQuadGetExponent 69 | #define decFloatSetCoefficient decQuadSetCoefficient 70 | #define decFloatSetExponent decQuadSetExponent 71 | #define decFloatShow decQuadShow 72 | #define decFloatToBCD decQuadToBCD 73 | #define decFloatToEngString decQuadToEngString 74 | #define decFloatToInt32 decQuadToInt32 75 | #define decFloatToInt32Exact decQuadToInt32Exact 76 | #define decFloatToPacked decQuadToPacked 77 | #define decFloatToString decQuadToString 78 | #define decFloatToUInt32 decQuadToUInt32 79 | #define decFloatToUInt32Exact decQuadToUInt32Exact 80 | #define decFloatToWider decQuadToWider 81 | #define decFloatZero decQuadZero 82 | 83 | // Computational (result is a decFloat) 84 | #define decFloatAbs decQuadAbs 85 | #define decFloatAdd decQuadAdd 86 | #define decFloatAnd decQuadAnd 87 | #define decFloatDivide decQuadDivide 88 | #define decFloatDivideInteger decQuadDivideInteger 89 | #define decFloatFMA decQuadFMA 90 | #define decFloatInvert decQuadInvert 91 | #define decFloatLogB decQuadLogB 92 | #define decFloatMax decQuadMax 93 | #define decFloatMaxMag decQuadMaxMag 94 | #define decFloatMin decQuadMin 95 | #define decFloatMinMag decQuadMinMag 96 | #define decFloatMinus decQuadMinus 97 | #define decFloatMultiply decQuadMultiply 98 | #define decFloatNextMinus decQuadNextMinus 99 | #define decFloatNextPlus decQuadNextPlus 100 | #define decFloatNextToward decQuadNextToward 101 | #define decFloatOr decQuadOr 102 | #define decFloatPlus decQuadPlus 103 | #define decFloatQuantize decQuadQuantize 104 | #define decFloatReduce decQuadReduce 105 | #define decFloatRemainder decQuadRemainder 106 | #define decFloatRemainderNear decQuadRemainderNear 107 | #define decFloatRotate decQuadRotate 108 | #define decFloatScaleB decQuadScaleB 109 | #define decFloatShift decQuadShift 110 | #define decFloatSubtract decQuadSubtract 111 | #define decFloatToIntegralValue decQuadToIntegralValue 112 | #define decFloatToIntegralExact decQuadToIntegralExact 113 | #define decFloatXor decQuadXor 114 | 115 | // Comparisons 116 | #define decFloatCompare decQuadCompare 117 | #define decFloatCompareSignal decQuadCompareSignal 118 | #define decFloatCompareTotal decQuadCompareTotal 119 | #define decFloatCompareTotalMag decQuadCompareTotalMag 120 | 121 | // Copies 122 | #define decFloatCanonical decQuadCanonical 123 | #define decFloatCopy decQuadCopy 124 | #define decFloatCopyAbs decQuadCopyAbs 125 | #define decFloatCopyNegate decQuadCopyNegate 126 | #define decFloatCopySign decQuadCopySign 127 | 128 | // Non-computational 129 | #define decFloatClass decQuadClass 130 | #define decFloatClassString decQuadClassString 131 | #define decFloatDigits decQuadDigits 132 | #define decFloatIsCanonical decQuadIsCanonical 133 | #define decFloatIsFinite decQuadIsFinite 134 | #define decFloatIsInfinite decQuadIsInfinite 135 | #define decFloatIsInteger decQuadIsInteger 136 | #define decFloatIsLogical decQuadIsLogical 137 | #define decFloatIsNaN decQuadIsNaN 138 | #define decFloatIsNegative decQuadIsNegative 139 | #define decFloatIsNormal decQuadIsNormal 140 | #define decFloatIsPositive decQuadIsPositive 141 | #define decFloatIsSignaling decQuadIsSignaling 142 | #define decFloatIsSignalling decQuadIsSignalling 143 | #define decFloatIsSigned decQuadIsSigned 144 | #define decFloatIsSubnormal decQuadIsSubnormal 145 | #define decFloatIsZero decQuadIsZero 146 | #define decFloatRadix decQuadRadix 147 | #define decFloatSameQuantum decQuadSameQuantum 148 | #define decFloatVersion decQuadVersion 149 | 150 | /* And now the code itself */ 151 | #include "decContext.h" // public includes 152 | #include "decQuad.h" // .. 153 | #include "decNumberLocal.h" // local includes (need DECPMAX) 154 | #include "decCommon.c" // non-arithmetic decFloat routines 155 | #include "decBasic.c" // basic formats routines 156 | 157 | MNL_DSO_HIDE_END 158 | -------------------------------------------------------------------------------- /libdecnumber/decQuad.h: -------------------------------------------------------------------------------- 1 | // libdecnumber/decQuad.h 2 | 3 | /* Copyright (C) 2018, 2019, 2020 Alexey Protasov (AKA Alex or rusini) 4 | 5 | This file is part of MANOOL. 6 | 7 | MANOOL is free software: you can redistribute it and/or modify it under the terms of the version 3 of the GNU General Public License 8 | as published by the Free Software Foundation (and only version 3). 9 | 10 | MANOOL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License along with MANOOL. If not, see . */ 14 | 15 | 16 | // This file incorporates work covered by the following copyright and 17 | // permission notice: 18 | 19 | /* ------------------------------------------------------------------ */ 20 | /* decQuad.h -- Decimal 128-bit format module header */ 21 | /* ------------------------------------------------------------------ */ 22 | /* Copyright (c) IBM Corporation, 2000, 2010. All rights reserved. */ 23 | /* */ 24 | /* This software is made available under the terms of the */ 25 | /* ICU License -- ICU 1.8.1 and later. */ 26 | /* */ 27 | /* The description and User's Guide ("The decNumber C Library") for */ 28 | /* this software is included in the package as decNumber.pdf. This */ 29 | /* document is also available in HTML, together with specifications, */ 30 | /* testcases, and Web links, on the General Decimal Arithmetic page. */ 31 | /* */ 32 | /* Please send comments, suggestions, and corrections to the author: */ 33 | /* mfc@uk.ibm.com */ 34 | /* Mike Cowlishaw, IBM Fellow */ 35 | /* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */ 36 | /* ------------------------------------------------------------------ */ 37 | /* This include file is always included by decSingle and decDouble, */ 38 | /* and therefore also holds useful constants used by all three. */ 39 | 40 | #include "mnl0.h" 41 | MNL_DSO_HIDE_BEGIN 42 | 43 | #if !defined(DECQUAD) 44 | #define DECQUAD 45 | 46 | #define DECQUADNAME "decimalQuad" /* Short name */ 47 | #define DECQUADTITLE "Decimal 128-bit datum" /* Verbose name */ 48 | #define DECQUADAUTHOR "Mike Cowlishaw" /* Who to blame */ 49 | 50 | /* parameters for decQuads */ 51 | #define DECQUAD_Bytes 16 /* length */ 52 | #define DECQUAD_Pmax 34 /* maximum precision (digits) */ 53 | #define DECQUAD_Emin -6143 /* minimum adjusted exponent */ 54 | #define DECQUAD_Emax 6144 /* maximum adjusted exponent */ 55 | #define DECQUAD_EmaxD 4 /* maximum exponent digits */ 56 | #define DECQUAD_Bias 6176 /* bias for the exponent */ 57 | #define DECQUAD_String 43 /* maximum string length, +1 */ 58 | #define DECQUAD_EconL 12 /* exponent continuation length */ 59 | #define DECQUAD_Declets 11 /* count of declets */ 60 | /* highest biased exponent (Elimit-1) */ 61 | #define DECQUAD_Ehigh (DECQUAD_Emax + DECQUAD_Bias - (DECQUAD_Pmax-1)) 62 | 63 | /* Required include */ 64 | #include "decContext.h" 65 | 66 | /* The decQuad decimal 128-bit type, accessible by all sizes */ 67 | typedef union { 68 | uint8_t bytes[DECQUAD_Bytes]; /* fields: 1, 5, 12, 110 bits */ 69 | uint16_t shorts[DECQUAD_Bytes/2]; 70 | uint32_t words[DECQUAD_Bytes/4]; 71 | #if DECUSE64 72 | uint64_t longs[DECQUAD_Bytes/8]; 73 | #endif 74 | } decQuad; 75 | 76 | /* ---------------------------------------------------------------- */ 77 | /* Shared constants */ 78 | /* ---------------------------------------------------------------- */ 79 | 80 | /* sign and special values [top 32-bits; last two bits are don't-care 81 | for Infinity on input, last bit don't-care for NaNs] */ 82 | #define DECFLOAT_Sign 0x80000000 /* 1 00000 00 Sign */ 83 | #define DECFLOAT_NaN 0x7c000000 /* 0 11111 00 NaN generic */ 84 | #define DECFLOAT_qNaN 0x7c000000 /* 0 11111 00 qNaN */ 85 | #define DECFLOAT_sNaN 0x7e000000 /* 0 11111 10 sNaN */ 86 | #define DECFLOAT_Inf 0x78000000 /* 0 11110 00 Infinity */ 87 | #define DECFLOAT_MinSp 0x78000000 /* minimum special value */ 88 | /* [specials are all >=MinSp] */ 89 | /* Sign nibble constants */ 90 | #if !defined(DECPPLUSALT) 91 | #define DECPPLUSALT 0x0A /* alternate plus nibble */ 92 | #define DECPMINUSALT 0x0B /* alternate minus nibble */ 93 | #define DECPPLUS 0x0C /* preferred plus nibble */ 94 | #define DECPMINUS 0x0D /* preferred minus nibble */ 95 | #define DECPPLUSALT2 0x0E /* alternate plus nibble */ 96 | #define DECPUNSIGNED 0x0F /* alternate plus nibble (unsigned) */ 97 | #endif 98 | 99 | /* ---------------------------------------------------------------- */ 100 | /* Routines -- implemented as decFloat routines in common files */ 101 | /* ---------------------------------------------------------------- */ 102 | 103 | #ifdef __cplusplus 104 | extern "C" { 105 | #endif 106 | 107 | /* Utilities and conversions, extractors, etc.) */ 108 | extern decQuad * decQuadFromBCD(decQuad *, int32_t, const uint8_t *, int32_t); 109 | extern decQuad * decQuadFromInt32(decQuad *, int32_t); 110 | extern decQuad * decQuadFromPacked(decQuad *, int32_t, const uint8_t *); 111 | extern decQuad * decQuadFromPackedChecked(decQuad *, int32_t, const uint8_t *); 112 | extern decQuad * decQuadFromString(decQuad *, const char *, decContext *); 113 | extern decQuad * decQuadFromUInt32(decQuad *, uint32_t); 114 | extern int32_t decQuadGetCoefficient(const decQuad *, uint8_t *); 115 | extern int32_t decQuadGetExponent(const decQuad *); 116 | extern decQuad * decQuadSetCoefficient(decQuad *, const uint8_t *, int32_t); 117 | extern decQuad * decQuadSetExponent(decQuad *, decContext *, int32_t); 118 | extern void decQuadShow(const decQuad *, const char *); 119 | extern int32_t decQuadToBCD(const decQuad *, int32_t *, uint8_t *); 120 | extern char * decQuadToEngString(const decQuad *, char *); 121 | extern int32_t decQuadToInt32(const decQuad *, decContext *, enum rounding); 122 | extern int32_t decQuadToInt32Exact(const decQuad *, decContext *, enum rounding); 123 | extern int32_t decQuadToPacked(const decQuad *, int32_t *, uint8_t *); 124 | extern char * decQuadToString(const decQuad *, char *); 125 | extern uint32_t decQuadToUInt32(const decQuad *, decContext *, enum rounding); 126 | extern uint32_t decQuadToUInt32Exact(const decQuad *, decContext *, enum rounding); 127 | extern decQuad * decQuadZero(decQuad *); 128 | 129 | /* Computational (result is a decQuad) */ 130 | extern decQuad * decQuadAbs(decQuad *, const decQuad *, decContext *); 131 | extern decQuad * decQuadAdd(decQuad *, const decQuad *, const decQuad *, decContext *); 132 | extern decQuad * decQuadAnd(decQuad *, const decQuad *, const decQuad *, decContext *); 133 | extern decQuad * decQuadDivide(decQuad *, const decQuad *, const decQuad *, decContext *); 134 | extern decQuad * decQuadDivideInteger(decQuad *, const decQuad *, const decQuad *, decContext *); 135 | extern decQuad * decQuadFMA(decQuad *, const decQuad *, const decQuad *, const decQuad *, decContext *); 136 | extern decQuad * decQuadInvert(decQuad *, const decQuad *, decContext *); 137 | extern decQuad * decQuadLogB(decQuad *, const decQuad *, decContext *); 138 | extern decQuad * decQuadMax(decQuad *, const decQuad *, const decQuad *, decContext *); 139 | extern decQuad * decQuadMaxMag(decQuad *, const decQuad *, const decQuad *, decContext *); 140 | extern decQuad * decQuadMin(decQuad *, const decQuad *, const decQuad *, decContext *); 141 | extern decQuad * decQuadMinMag(decQuad *, const decQuad *, const decQuad *, decContext *); 142 | extern decQuad * decQuadMinus(decQuad *, const decQuad *, decContext *); 143 | extern decQuad * decQuadMultiply(decQuad *, const decQuad *, const decQuad *, decContext *); 144 | extern decQuad * decQuadNextMinus(decQuad *, const decQuad *, decContext *); 145 | extern decQuad * decQuadNextPlus(decQuad *, const decQuad *, decContext *); 146 | extern decQuad * decQuadNextToward(decQuad *, const decQuad *, const decQuad *, decContext *); 147 | extern decQuad * decQuadOr(decQuad *, const decQuad *, const decQuad *, decContext *); 148 | extern decQuad * decQuadPlus(decQuad *, const decQuad *, decContext *); 149 | extern decQuad * decQuadQuantize(decQuad *, const decQuad *, const decQuad *, decContext *); 150 | extern decQuad * decQuadReduce(decQuad *, const decQuad *, decContext *); 151 | extern decQuad * decQuadRemainder(decQuad *, const decQuad *, const decQuad *, decContext *); 152 | extern decQuad * decQuadRemainderNear(decQuad *, const decQuad *, const decQuad *, decContext *); 153 | extern decQuad * decQuadRotate(decQuad *, const decQuad *, const decQuad *, decContext *); 154 | extern decQuad * decQuadScaleB(decQuad *, const decQuad *, const decQuad *, decContext *); 155 | extern decQuad * decQuadShift(decQuad *, const decQuad *, const decQuad *, decContext *); 156 | extern decQuad * decQuadSubtract(decQuad *, const decQuad *, const decQuad *, decContext *); 157 | extern decQuad * decQuadToIntegralValue(decQuad *, const decQuad *, decContext *, enum rounding); 158 | extern decQuad * decQuadToIntegralExact(decQuad *, const decQuad *, decContext *); 159 | extern decQuad * decQuadXor(decQuad *, const decQuad *, const decQuad *, decContext *); 160 | 161 | /* Comparisons */ 162 | extern decQuad * decQuadCompare(decQuad *, const decQuad *, const decQuad *, decContext *); 163 | extern decQuad * decQuadCompareSignal(decQuad *, const decQuad *, const decQuad *, decContext *); 164 | extern decQuad * decQuadCompareTotal(decQuad *, const decQuad *, const decQuad *); 165 | extern decQuad * decQuadCompareTotalMag(decQuad *, const decQuad *, const decQuad *); 166 | 167 | /* Copies */ 168 | extern decQuad * decQuadCanonical(decQuad *, const decQuad *); 169 | extern decQuad * decQuadCopy(decQuad *, const decQuad *); 170 | extern decQuad * decQuadCopyAbs(decQuad *, const decQuad *); 171 | extern decQuad * decQuadCopyNegate(decQuad *, const decQuad *); 172 | extern decQuad * decQuadCopySign(decQuad *, const decQuad *, const decQuad *); 173 | 174 | /* Non-computational */ 175 | extern enum decClass decQuadClass(const decQuad *); 176 | extern const char * decQuadClassString(const decQuad *); 177 | extern uint32_t decQuadDigits(const decQuad *); 178 | extern uint32_t decQuadIsCanonical(const decQuad *); 179 | extern uint32_t decQuadIsFinite(const decQuad *); 180 | extern uint32_t decQuadIsInteger(const decQuad *); 181 | extern uint32_t decQuadIsLogical(const decQuad *); 182 | extern uint32_t decQuadIsInfinite(const decQuad *); 183 | extern uint32_t decQuadIsNaN(const decQuad *); 184 | extern uint32_t decQuadIsNegative(const decQuad *); 185 | extern uint32_t decQuadIsNormal(const decQuad *); 186 | extern uint32_t decQuadIsPositive(const decQuad *); 187 | extern uint32_t decQuadIsSignaling(const decQuad *); 188 | extern uint32_t decQuadIsSignalling(const decQuad *); 189 | extern uint32_t decQuadIsSigned(const decQuad *); 190 | extern uint32_t decQuadIsSubnormal(const decQuad *); 191 | extern uint32_t decQuadIsZero(const decQuad *); 192 | extern uint32_t decQuadRadix(const decQuad *); 193 | extern uint32_t decQuadSameQuantum(const decQuad *, const decQuad *); 194 | extern const char * decQuadVersion(void); 195 | 196 | #ifdef __cplusplus 197 | } 198 | #endif 199 | 200 | /* decNumber conversions; these are implemented as macros so as not */ 201 | /* to force a dependency on decimal128 and decNumber in decQuad. */ 202 | /* decQuadFromNumber returns a decimal128 * to avoid warnings. */ 203 | #if 0 204 | #define decQuadToNumber(dq, dn) decimal128ToNumber((decimal128 *)(dq), dn) 205 | #define decQuadFromNumber(dq, dn, set) decimal128FromNumber((decimal128 *)(dq), dn, set) 206 | #else 207 | #define decQuadToNumber(dq, dn) (MNL_BARRIER(), decimal128ToNumber((decimal128 *)(dq), dn)) 208 | #define decQuadFromNumber(dq, dn, set) (MNL_BARRIER(), decimal128FromNumber((decimal128 *)(dq), dn, set)) 209 | #endif 210 | 211 | #endif 212 | 213 | MNL_DSO_HIDE_END 214 | -------------------------------------------------------------------------------- /libdecnumber/decimal128.h: -------------------------------------------------------------------------------- 1 | // libdecnumber/decimal128.h 2 | 3 | /* Copyright (C) 2018, 2019, 2020 Alexey Protasov (AKA Alex or rusini) 4 | 5 | This file is part of MANOOL. 6 | 7 | MANOOL is free software: you can redistribute it and/or modify it under the terms of the version 3 of the GNU General Public License 8 | as published by the Free Software Foundation (and only version 3). 9 | 10 | MANOOL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License along with MANOOL. If not, see . */ 14 | 15 | 16 | // This file incorporates work covered by the following copyright and 17 | // permission notice: 18 | 19 | /* ------------------------------------------------------------------ */ 20 | /* Decimal 128-bit format module header */ 21 | /* ------------------------------------------------------------------ */ 22 | /* Copyright (c) IBM Corporation, 2000, 2005. All rights reserved. */ 23 | /* */ 24 | /* This software is made available under the terms of the */ 25 | /* ICU License -- ICU 1.8.1 and later. */ 26 | /* */ 27 | /* The description and User's Guide ("The decNumber C Library") for */ 28 | /* this software is called decNumber.pdf. This document is */ 29 | /* available, together with arithmetic and format specifications, */ 30 | /* testcases, and Web links, on the General Decimal Arithmetic page. */ 31 | /* */ 32 | /* Please send comments, suggestions, and corrections to the author: */ 33 | /* mfc@uk.ibm.com */ 34 | /* Mike Cowlishaw, IBM Fellow */ 35 | /* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */ 36 | /* ------------------------------------------------------------------ */ 37 | 38 | #include "mnl0.h" 39 | MNL_DSO_HIDE_BEGIN 40 | 41 | #if !defined(DECIMAL128) 42 | #define DECIMAL128 43 | #define DEC128NAME "decimal128" /* Short name */ 44 | #define DEC128FULLNAME "Decimal 128-bit Number" /* Verbose name */ 45 | #define DEC128AUTHOR "Mike Cowlishaw" /* Who to blame */ 46 | 47 | /* parameters for decimal128s */ 48 | #define DECIMAL128_Bytes 16 /* length */ 49 | #define DECIMAL128_Pmax 34 /* maximum precision (digits) */ 50 | #define DECIMAL128_Emax 6144 /* maximum adjusted exponent */ 51 | #define DECIMAL128_Emin -6143 /* minimum adjusted exponent */ 52 | #define DECIMAL128_Bias 6176 /* bias for the exponent */ 53 | #define DECIMAL128_String 43 /* maximum string length, +1 */ 54 | #define DECIMAL128_EconL 12 /* exp. continuation length */ 55 | /* highest biased exponent (Elimit-1) */ 56 | #define DECIMAL128_Ehigh (DECIMAL128_Emax+DECIMAL128_Bias-DECIMAL128_Pmax+1) 57 | 58 | /* check enough digits, if pre-defined */ 59 | #if defined(DECNUMDIGITS) 60 | #if (DECNUMDIGITS=34 for safe use 62 | #endif 63 | #endif 64 | 65 | #ifndef DECNUMDIGITS 66 | #define DECNUMDIGITS DECIMAL128_Pmax /* size if not already defined*/ 67 | #endif 68 | #ifndef DECNUMBER 69 | #include "decNumber.h" /* context and number library */ 70 | #endif 71 | 72 | /* Decimal 128-bit type, accessible by bytes */ 73 | typedef struct { 74 | uint8_t bytes[DECIMAL128_Bytes]; /* decimal128: 1, 5, 12, 110 bits*/ 75 | } decimal128; 76 | 77 | /* special values [top byte excluding sign bit; last two bits are */ 78 | /* don't-care for Infinity on input, last bit don't-care for NaN] */ 79 | #if !defined(DECIMAL_NaN) 80 | #define DECIMAL_NaN 0x7c /* 0 11111 00 NaN */ 81 | #define DECIMAL_sNaN 0x7e /* 0 11111 10 sNaN */ 82 | #define DECIMAL_Inf 0x78 /* 0 11110 00 Infinity */ 83 | #endif 84 | 85 | /* ---------------------------------------------------------------- */ 86 | /* Routines */ 87 | /* ---------------------------------------------------------------- */ 88 | 89 | #ifdef __cplusplus 90 | extern "C" { 91 | #endif 92 | 93 | /* String conversions */ 94 | decimal128 * decimal128FromString(decimal128 *, const char *, decContext *); 95 | char * decimal128ToString(const decimal128 *, char *); 96 | char * decimal128ToEngString(const decimal128 *, char *); 97 | 98 | /* decNumber conversions */ 99 | decimal128 * decimal128FromNumber(decimal128 *, const decNumber *, 100 | decContext *); 101 | decNumber * decimal128ToNumber(const decimal128 *, decNumber *); 102 | 103 | /* Format-dependent utilities */ 104 | uint32_t decimal128IsCanonical(const decimal128 *); 105 | decimal128 * decimal128Canonical(decimal128 *, const decimal128 *); 106 | 107 | #ifdef __cplusplus 108 | } 109 | #endif 110 | 111 | #endif 112 | 113 | MNL_DSO_HIDE_END 114 | -------------------------------------------------------------------------------- /libdecnumber/decimal64.h: -------------------------------------------------------------------------------- 1 | // libdecnumber/decimal64.h 2 | 3 | /* Copyright (C) 2018, 2019, 2020 Alexey Protasov (AKA Alex or rusini) 4 | 5 | This file is part of MANOOL. 6 | 7 | MANOOL is free software: you can redistribute it and/or modify it under the terms of the version 3 of the GNU General Public License 8 | as published by the Free Software Foundation (and only version 3). 9 | 10 | MANOOL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License along with MANOOL. If not, see . */ 14 | 15 | 16 | // This file incorporates work covered by the following copyright and 17 | // permission notice: 18 | 19 | /* ------------------------------------------------------------------ */ 20 | /* Decimal 64-bit format module header */ 21 | /* ------------------------------------------------------------------ */ 22 | /* Copyright (c) IBM Corporation, 2000, 2005. All rights reserved. */ 23 | /* */ 24 | /* This software is made available under the terms of the */ 25 | /* ICU License -- ICU 1.8.1 and later. */ 26 | /* */ 27 | /* The description and User's Guide ("The decNumber C Library") for */ 28 | /* this software is called decNumber.pdf. This document is */ 29 | /* available, together with arithmetic and format specifications, */ 30 | /* testcases, and Web links, on the General Decimal Arithmetic page. */ 31 | /* */ 32 | /* Please send comments, suggestions, and corrections to the author: */ 33 | /* mfc@uk.ibm.com */ 34 | /* Mike Cowlishaw, IBM Fellow */ 35 | /* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */ 36 | /* ------------------------------------------------------------------ */ 37 | 38 | #include "mnl0.h" 39 | MNL_DSO_HIDE_BEGIN 40 | 41 | #if !defined(DECIMAL64) 42 | #define DECIMAL64 43 | #define DEC64NAME "decimal64" /* Short name */ 44 | #define DEC64FULLNAME "Decimal 64-bit Number" /* Verbose name */ 45 | #define DEC64AUTHOR "Mike Cowlishaw" /* Who to blame */ 46 | 47 | 48 | /* parameters for decimal64s */ 49 | #define DECIMAL64_Bytes 8 /* length */ 50 | #define DECIMAL64_Pmax 16 /* maximum precision (digits) */ 51 | #define DECIMAL64_Emax 384 /* maximum adjusted exponent */ 52 | #define DECIMAL64_Emin -383 /* minimum adjusted exponent */ 53 | #define DECIMAL64_Bias 398 /* bias for the exponent */ 54 | #define DECIMAL64_String 24 /* maximum string length, +1 */ 55 | #define DECIMAL64_EconL 8 /* exp. continuation length */ 56 | /* highest biased exponent (Elimit-1) */ 57 | #define DECIMAL64_Ehigh (DECIMAL64_Emax+DECIMAL64_Bias-DECIMAL64_Pmax+1) 58 | 59 | /* check enough digits, if pre-defined */ 60 | #if defined(DECNUMDIGITS) 61 | #if (DECNUMDIGITS=16 for safe use 63 | #endif 64 | #endif 65 | 66 | 67 | #ifndef DECNUMDIGITS 68 | #define DECNUMDIGITS DECIMAL64_Pmax /* size if not already defined*/ 69 | #endif 70 | #ifndef DECNUMBER 71 | #include "decNumber.h" /* context and number library */ 72 | #endif 73 | 74 | /* Decimal 64-bit type, accessible by bytes */ 75 | typedef struct { 76 | uint8_t bytes[DECIMAL64_Bytes]; /* decimal64: 1, 5, 8, 50 bits*/ 77 | } decimal64; 78 | 79 | /* special values [top byte excluding sign bit; last two bits are */ 80 | /* don't-care for Infinity on input, last bit don't-care for NaN] */ 81 | #if !defined(DECIMAL_NaN) 82 | #define DECIMAL_NaN 0x7c /* 0 11111 00 NaN */ 83 | #define DECIMAL_sNaN 0x7e /* 0 11111 10 sNaN */ 84 | #define DECIMAL_Inf 0x78 /* 0 11110 00 Infinity */ 85 | #endif 86 | 87 | /* ---------------------------------------------------------------- */ 88 | /* Routines */ 89 | /* ---------------------------------------------------------------- */ 90 | 91 | #ifdef __cplusplus 92 | extern "C" { 93 | #endif 94 | 95 | /* String conversions */ 96 | decimal64 * decimal64FromString(decimal64 *, const char *, decContext *); 97 | char * decimal64ToString(const decimal64 *, char *); 98 | char * decimal64ToEngString(const decimal64 *, char *); 99 | 100 | /* decNumber conversions */ 101 | decimal64 * decimal64FromNumber(decimal64 *, const decNumber *, 102 | decContext *); 103 | decNumber * decimal64ToNumber(const decimal64 *, decNumber *); 104 | 105 | /* Format-dependent utilities */ 106 | uint32_t decimal64IsCanonical(const decimal64 *); 107 | decimal64 * decimal64Canonical(decimal64 *, const decimal64 *); 108 | 109 | #ifdef __cplusplus 110 | } 111 | #endif 112 | 113 | #endif 114 | 115 | MNL_DSO_HIDE_END 116 | -------------------------------------------------------------------------------- /libdecnumber/mnl0.h: -------------------------------------------------------------------------------- 1 | // libdecnumber/mnl0.h 2 | # define MNL_C_SOURCE // TODO: this applies to public *.h?! 3 | # include "../mnl-aux-mnl0.hh" 4 | -------------------------------------------------------------------------------- /manool.hh: -------------------------------------------------------------------------------- 1 | // manool.hh -- MANOOL plug-in API (depends on: core, base; dependency of: base) 2 | 3 | /* Copyright (C) 2018, 2019, 2020 Alexey Protasov (AKA Alex or rusini) 4 | 5 | This file is part of MANOOL. 6 | 7 | MANOOL is free software: you can redistribute it and/or modify it under the terms of the version 3 of the GNU General Public License 8 | as published by the Free Software Foundation (and only version 3). 9 | 10 | MANOOL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License along with MANOOL. If not, see . */ 14 | 15 | 16 | # ifndef MNL_INCLUDED_MANOOL 17 | # define MNL_INCLUDED_MANOOL 18 | 19 | # include 20 | 21 | # include "mnl-misc-memmgm.hh" 22 | 23 | # include "mnl-aux-core.tcc" 24 | 25 | // Macros ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 26 | # define MNL_RVALUE() \ 27 | MNL_INLINE static ::mnl::code compile(::mnl::code &&self, const ::mnl::form &form, const ::mnl::loc &loc) \ 28 | { return ::mnl::aux::compile_apply(::std::move(self), form, loc); } \ 29 | MNL_INLINE static void exec_in(::mnl::val &&) { MNL_UNREACHABLE(); } \ 30 | MNL_INLINE static ::mnl::val exec_out() { MNL_UNREACHABLE(); } \ 31 | MNL_INLINE static bool is_rvalue() { return true; } \ 32 | MNL_INLINE static bool is_lvalue() { return false; } \ 33 | friend ::mnl::code; 34 | # define MNL_LVALUE(COND) \ 35 | MNL_INLINE static ::mnl::code compile(::mnl::code &&self, const ::mnl::form &form, const ::mnl::loc &loc) \ 36 | { return ::mnl::aux::compile_apply(::std::move(self), form, loc); } \ 37 | MNL_INLINE static bool is_rvalue() { return true; } \ 38 | MNL_INLINE bool is_lvalue() const { return (COND); } \ 39 | friend ::mnl::code; 40 | # define MNL_NONVALUE() \ 41 | MNL_INLINE static ::mnl::val execute(bool = false) { MNL_UNREACHABLE(); } \ 42 | MNL_INLINE static void exec_in(::mnl::val &&) { MNL_UNREACHABLE(); } \ 43 | MNL_INLINE static ::mnl::val exec_out() { MNL_UNREACHABLE(); } \ 44 | MNL_INLINE static bool is_rvalue() { return false; } \ 45 | MNL_INLINE static bool is_lvalue() { return false; } \ 46 | friend ::mnl::code; 47 | // end 48 | # define MNL_CATCH_UNEXPECTED \ 49 | catch (decltype(::mnl::sig_state) &sig) { ::mnl::aux::panic(sig); } \ 50 | catch (::mnl::stack_overflow &) { ::mnl::aux::panic({MNL_SYM("StackOverflow"), {}}); } \ 51 | catch (::mnl::heap_exhausted &) { ::mnl::aux::panic({MNL_SYM("HeapExhausted"), {}}); } \ 52 | catch (::std::bad_alloc &) { ::mnl::aux::panic({MNL_SYM("LimitExceeded"), {}}); } \ 53 | catch (::std::system_error &) { ::mnl::aux::panic({MNL_SYM("SystemError"), {}}); } \ 54 | // end 55 | 56 | namespace MNL_AUX_UUID { 57 | 58 | namespace aux { namespace pub { 59 | // Temporary Variable Accounting //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 60 | 61 | // Compile-time accounting 62 | extern MNL_IF_WITH_MT(thread_local) int tmp_cnt; // count for current frame layout 63 | extern MNL_IF_WITH_MT(thread_local) set tmp_ids; // all temporaries 64 | // Run-time accounting 65 | extern MNL_IF_WITH_MT(thread_local) vector tmp_stk; // stack 66 | extern MNL_IF_WITH_MT(thread_local) decltype(tmp_stk)::size_type tmp_frm; // frame pointer 67 | 68 | // Essential Stuff ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 69 | code make_lit(const val &); 70 | 71 | // Convenience Stuff //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 72 | 73 | code compile_rval(const form &, const loc & = MNL_IF_GCC5(loc)MNL_IF_GCC6(loc){}), compile_lval(const form &, const loc & = MNL_IF_GCC5(loc)MNL_IF_GCC6(loc){}); 74 | sym eval_sym(const form &, const loc & = MNL_IF_GCC5(loc)MNL_IF_GCC6(loc){}); 75 | code compile_rval(form::vci_range, const loc & = MNL_IF_GCC5(loc)MNL_IF_GCC6(loc){}); 76 | 77 | class expr_export { MNL_NONVALUE() 78 | public: 79 | expr_export() = default; 80 | expr_export(initializer_list> bind): bind(bind) {} 81 | expr_export(const vector> &bind): bind(bind) {} 82 | MNL_INLINE expr_export(vector> &&bind) noexcept: bind(move(bind)) {} 83 | private: 84 | vector> bind; 85 | MNL_INLINE inline code compile(code &&, const form &, const loc &) const; 86 | }; 87 | extern template class code::box; 88 | 89 | template MNL_INLINE inline code make_proc_test() { 90 | struct proc { MNL_INLINE static val invoke(val &&self, const sym &op, int argc, val argv[], val *) { 91 | if (MNL_UNLIKELY(op != MNL_SYM("Apply"))) return self.default_invoke(op, argc, argv); 92 | if (MNL_UNLIKELY(argc != 1)) MNL_ERR(MNL_SYM("InvalidInvocation")); 93 | return test(argv[0]); 94 | }}; 95 | return make_lit(proc{}); 96 | } 97 | }} // namespace aux::pub 98 | 99 | namespace aux { // Helper Stuff //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 100 | code compile_apply(code &&, const form &, const loc &); 101 | MNL_NORETURN void panic(const decltype(sig_state) &); 102 | } // namespace aux 103 | 104 | } // namespace MNL_AUX_UUID 105 | 106 | # endif // # ifndef MNL_INCLUDED_MANOOL 107 | -------------------------------------------------------------------------------- /misc-decimal.cc: -------------------------------------------------------------------------------- 1 | // misc-decimal.cc -- thin wrapper around libdecnumber for IEEE 754 formats 2 | 3 | /* Copyright (C) 2018, 2019, 2020 Alexey Protasov (AKA Alex or rusini) 4 | 5 | This file is part of MANOOL. 6 | 7 | MANOOL is free software: you can redistribute it and/or modify it under the terms of the version 3 of the GNU General Public License 8 | as published by the Free Software Foundation (and only version 3). 9 | 10 | MANOOL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License along with MANOOL. If not, see . */ 14 | 15 | 16 | # include "mnl-misc-decimal.hh" 17 | 18 | # define DECNUMDIGITS 34 // struct decNumber definitions differ in TUs - technically UB but in practice not an issue 19 | # include "libdecnumber/decDouble.h" 20 | # include "libdecnumber/decimal64.h" 21 | # include "libdecnumber/decimal128.h" 22 | 23 | namespace MNL_AUX_UUID { using namespace aux; 24 | 25 | namespace aux { 26 | typedef dec<64, true> df64b; typedef dec<128, true> df128b; 27 | typedef dec<64, false> df64c; typedef dec<128, false> df128c; 28 | static MNL_IF_WITH_MT(thread_local) decContext 29 | ctx_df64b{16, +384, -383, DEC_ROUND_HALF_EVEN, 0, 0, 1}, ctx_df128b{34, +6144, -6143, DEC_ROUND_HALF_EVEN, 0, 0, 1}, 30 | ctx_df64c{16, +384, -383, DEC_ROUND_HALF_UP, 0, 0, 1}, ctx_df128c{34, +6144, -6143, DEC_ROUND_HALF_UP, 0, 0, 1}; 31 | } // namespace aux 32 | 33 | # define MNL_M(TYPE, PREC) \ 34 | template<> TYPE TYPE::make(const char rhs[]) noexcept { TYPE res; dec##PREC##FromString(reinterpret_cast(&res), rhs, &ctx_##TYPE); return res; } \ 35 | template<> TYPE TYPE::make(int rhs) noexcept { TYPE res; dec##PREC##FromInt32 (reinterpret_cast(&res), rhs); return res; } \ 36 | template<> TYPE TYPE::make(unsigned rhs) noexcept { TYPE res; dec##PREC##FromUInt32(reinterpret_cast(&res), rhs); return res; } \ 37 | template<> char *TYPE::to_str(str_buf res) const noexcept { return dec##PREC##ToString (reinterpret_cast(this), res); } \ 38 | template<> char *TYPE::to_eng_str(str_buf res) const noexcept { return dec##PREC##ToEngString(reinterpret_cast(this), res); } \ 39 | bool pub::isfinite(TYPE rhs) noexcept { return dec##PREC##IsFinite (reinterpret_cast(&rhs)); } \ 40 | bool pub::isinf (TYPE rhs) noexcept { return dec##PREC##IsInfinite(reinterpret_cast(&rhs)); } \ 41 | bool pub::isnan (TYPE rhs) noexcept { return dec##PREC##IsNaN (reinterpret_cast(&rhs)); } \ 42 | bool pub::signbit (TYPE rhs) noexcept { return dec##PREC##IsSigned (reinterpret_cast(&rhs)); } \ 43 | \ 44 | TYPE pub::operator+(TYPE lhs, TYPE rhs) noexcept { TYPE res; dec##PREC##Add(reinterpret_cast(&res), \ 45 | reinterpret_cast(&lhs), reinterpret_cast(&rhs), &ctx_##TYPE); return res; \ 46 | } \ 47 | TYPE pub::operator-(TYPE lhs, TYPE rhs) noexcept { TYPE res; dec##PREC##Subtract(reinterpret_cast(&res), \ 48 | reinterpret_cast(&lhs), reinterpret_cast(&rhs), &ctx_##TYPE); return res; \ 49 | } \ 50 | TYPE pub::operator*(TYPE lhs, TYPE rhs) noexcept { TYPE res; dec##PREC##Multiply(reinterpret_cast(&res), \ 51 | reinterpret_cast(&lhs), reinterpret_cast(&rhs), &ctx_##TYPE); return res; \ 52 | } \ 53 | TYPE pub::operator/(TYPE lhs, TYPE rhs) noexcept { TYPE res; dec##PREC##Divide(reinterpret_cast(&res), \ 54 | reinterpret_cast(&lhs), reinterpret_cast(&rhs), &ctx_##TYPE); return res; \ 55 | } \ 56 | TYPE pub::operator+(TYPE rhs) noexcept { TYPE res; dec##PREC##Plus(reinterpret_cast(&res), \ 57 | reinterpret_cast(&rhs), &ctx_##TYPE); return res; \ 58 | } \ 59 | TYPE pub::operator-(TYPE rhs) noexcept { TYPE res; dec##PREC##Minus(reinterpret_cast(&res), \ 60 | reinterpret_cast(&rhs), &ctx_##TYPE); return res; \ 61 | } \ 62 | TYPE pub::abs(TYPE rhs) noexcept { TYPE res; dec##PREC##Abs(reinterpret_cast(&res), \ 63 | reinterpret_cast(&rhs), &ctx_##TYPE); return res; \ 64 | } \ 65 | TYPE pub::fma(TYPE a1, TYPE a2, TYPE a3) noexcept { TYPE res; dec##PREC##FMA(reinterpret_cast(&res), \ 66 | reinterpret_cast(&a1), reinterpret_cast(&a2), reinterpret_cast(&a3), &ctx_##TYPE); return res; \ 67 | } \ 68 | bool pub::operator==(TYPE lhs, TYPE rhs) noexcept { dec##PREC res; dec##PREC##Compare(&res, \ 69 | reinterpret_cast(&lhs), reinterpret_cast(&rhs), &ctx_##TYPE); return dec##PREC##IsZero(&res); \ 70 | } \ 71 | bool pub::operator< (TYPE lhs, TYPE rhs) noexcept { dec##PREC res; dec##PREC##Compare(&res, \ 72 | reinterpret_cast(&lhs), reinterpret_cast(&rhs), &ctx_##TYPE); return dec##PREC##IsNegative(&res); \ 73 | } \ 74 | int pub::order(TYPE lhs, TYPE rhs) noexcept { dec##PREC res; dec##PREC##CompareTotal(&res, \ 75 | reinterpret_cast(&lhs), reinterpret_cast(&rhs)); return dec##PREC##ToInt32(&res, &ctx_##TYPE, DEC_ROUND_DOWN); \ 76 | } \ 77 | TYPE pub::exp(TYPE rhs) noexcept { \ 78 | decNumber num; dec##PREC##ToNumber(&reinterpret_cast(rhs), &num); decNumberExp(&num, &num, &ctx_##TYPE); \ 79 | TYPE res; dec##PREC##FromNumber(&reinterpret_cast(res), &num, &ctx_##TYPE); return res; \ 80 | } \ 81 | TYPE pub::log(TYPE rhs) noexcept { \ 82 | decNumber num; dec##PREC##ToNumber(&reinterpret_cast(rhs), &num); decNumberLn(&num, &num, &ctx_##TYPE); \ 83 | TYPE res; dec##PREC##FromNumber(&reinterpret_cast(res), &num, &ctx_##TYPE); return res; \ 84 | } \ 85 | TYPE pub::log10(TYPE rhs) noexcept { \ 86 | decNumber num; dec##PREC##ToNumber(&reinterpret_cast(rhs), &num); decNumberLog10(&num, &num, &ctx_##TYPE); \ 87 | TYPE res; dec##PREC##FromNumber(&reinterpret_cast(res), &num, &ctx_##TYPE); return res; \ 88 | } \ 89 | TYPE pub::sqrt(TYPE rhs) noexcept { \ 90 | decNumber num; dec##PREC##ToNumber(&reinterpret_cast(rhs), &num); decNumberSquareRoot(&num, &num, &ctx_##TYPE); \ 91 | TYPE res; dec##PREC##FromNumber(&reinterpret_cast(res), &num, &ctx_##TYPE); return res; \ 92 | } \ 93 | TYPE pub::pow(TYPE lhs, TYPE rhs) noexcept { \ 94 | decNumber num, _num; \ 95 | dec##PREC##ToNumber(&reinterpret_cast(lhs), &num); \ 96 | dec##PREC##ToNumber(&reinterpret_cast(rhs), &_num); \ 97 | decNumberPower(&num, &num, &_num, &ctx_##TYPE); \ 98 | TYPE res; dec##PREC##FromNumber(&reinterpret_cast(res), &num, &ctx_##TYPE); return res; \ 99 | } \ 100 | TYPE pub::trunc(TYPE rhs) noexcept { TYPE res; dec##PREC##ToIntegralValue(reinterpret_cast(&res), \ 101 | reinterpret_cast(&rhs), &ctx_##TYPE, DEC_ROUND_DOWN); return res; \ 102 | } \ 103 | TYPE pub::round(TYPE rhs) noexcept { TYPE res; dec##PREC##ToIntegralValue(reinterpret_cast(&res), \ 104 | reinterpret_cast(&rhs), &ctx_##TYPE, DEC_ROUND_HALF_UP); return res; \ 105 | } \ 106 | TYPE pub::floor(TYPE rhs) noexcept { TYPE res; dec##PREC##ToIntegralValue(reinterpret_cast(&res), \ 107 | reinterpret_cast(&rhs), &ctx_##TYPE, DEC_ROUND_FLOOR); return res; \ 108 | } \ 109 | TYPE pub::ceil(TYPE rhs) noexcept { TYPE res; dec##PREC##ToIntegralValue(reinterpret_cast(&res), \ 110 | reinterpret_cast(&rhs), &ctx_##TYPE, DEC_ROUND_CEILING); return res; \ 111 | } \ 112 | TYPE pub::quantize(TYPE lhs, TYPE rhs) noexcept { TYPE res; dec##PREC##Quantize( \ 113 | reinterpret_cast(&res), reinterpret_cast(&lhs), \ 114 | reinterpret_cast(&rhs), &ctx_##TYPE); return res; \ 115 | } \ 116 | // end # define MNL_M(TYPE, PREC) 117 | MNL_M(df64b, Double) MNL_M(df128b, Quad) 118 | MNL_M(df64c, Double) MNL_M(df128c, Quad) 119 | # undef MNL_M 120 | 121 | } // namespace MNL_AUX_UUID 122 | -------------------------------------------------------------------------------- /misc-memmgm.cc: -------------------------------------------------------------------------------- 1 | // misc-memmgm.cc -- general memory management 2 | 3 | /* Copyright (C) 2018, 2019, 2020 Alexey Protasov (AKA Alex or rusini) 4 | 5 | This file is part of MANOOL. 6 | 7 | MANOOL is free software: you can redistribute it and/or modify it under the terms of the version 3 of the GNU General Public License 8 | as published by the Free Software Foundation (and only version 3). 9 | 10 | MANOOL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License along with MANOOL. If not, see . */ 14 | 15 | 16 | # include "config.tcc" 17 | # include "mnl-misc-memmgm.hh" 18 | 19 | # include // ::malloc, ::free 20 | # if __linux__ 21 | # include // ::malloc_usable_size 22 | # elif __FreeBSD__ 23 | # include // ::malloc_usable_size 24 | # else 25 | # error "Either __linux__ or __FreeBSD__ is required" 26 | # endif 27 | # include 28 | # include // size_t, _Exit, EXIT_FAILURE 29 | # include // stderr, fprintf, fflush, perror 30 | 31 | namespace MNL_AUX_UUID { using namespace aux; 32 | namespace aux { 33 | using std::size_t; using std::_Exit; // 34 | using std::fprintf; using std::fflush; using std::perror; // 35 | } 36 | 37 | MNL_IF_WITH_MT(thread_local) long long aux::stk_lim; 38 | namespace aux { namespace { 39 | MNL_IF_WITH_MT(thread_local) long long stk_res; 40 | 41 | /*atomic*/ size_t heap_use; 42 | long long heap_lim = 1ll << 47; 43 | MNL_IF_WITH_MT(thread_local) long long heap_res; 44 | }} // namespace aux:: 45 | 46 | void pub::stk_limit (long long size) noexcept { 47 | unsigned long _; stk_lim = reinterpret_cast(&_) - size + stk_res; 48 | } 49 | void pub::heap_limit(long long size) noexcept { 50 | heap_lim = (long long)heap_use + size; 51 | } 52 | long long pub::stk_reserve (long long size) noexcept { 53 | auto saved_size = stk_res; (stk_lim -= stk_res) += size, stk_res = size; return saved_size; 54 | } 55 | long long pub::heap_reserve(long long size) noexcept { 56 | auto saved_size = heap_res; heap_res = size; return saved_size; 57 | } 58 | void aux::err_stk_overflow() { 59 | if (stk_res) stk_lim -= stk_res, stk_res = 0, throw stack_overflow{}; 60 | fprintf(stderr, "MANOOL: FATAL ERROR: %s\n", "Stack overflow (and no reservation is in effect)"), fflush(stderr), _Exit(EXIT_FAILURE); 61 | } 62 | 63 | namespace aux { namespace { 64 | MNL_INLINE inline void *_new(size_t size) { 65 | if (MNL_UNLIKELY(!size)) size = 1; 66 | auto ptr = ::malloc(size); // Note: the VM pages are still not committed here 67 | if (MNL_UNLIKELY(!ptr)) { 68 | if (size <= 1ll << 47 && (long long) MNL_IF_WITH_MT(__atomic_load_n(&heap_use, __ATOMIC_RELAXED)) 69 | MNL_IF_WITHOUT_MT(heap_use) + (long long)size + (long long)sizeof(size_t) <= heap_lim - heap_res) 70 | perror("MANOOL: FATAL ERROR: Cannot malloc"), fflush(stderr), _Exit(EXIT_FAILURE); 71 | if (heap_res) heap_res = 0, throw heap_exhausted{}; 72 | fprintf(stderr, "MANOOL: FATAL ERROR: %s\n", "Heap exhausted (and no reservation is in effect)"), fflush(stderr), _Exit(EXIT_FAILURE); 73 | } 74 | # if MNL_WITH_MULTITHREADING 75 | size = ::malloc_usable_size(ptr) + sizeof(size_t); 76 | auto _heap_use = __atomic_load_n(&heap_use, __ATOMIC_RELAXED); 77 | do if (MNL_UNLIKELY((long long)(_heap_use + size) > heap_lim - heap_res)) { 78 | ::free(ptr); 79 | if (heap_res) heap_res = 0, throw heap_exhausted{}; 80 | fprintf(stderr, "MANOOL: FATAL ERROR: %s\n", "Heap exhausted (and no reservation is in effect)"), fflush(stderr), _Exit(EXIT_FAILURE); 81 | } while (MNL_UNLIKELY(!__atomic_compare_exchange_n(&heap_use, &_heap_use, _heap_use + size, {}, __ATOMIC_RELAXED, __ATOMIC_RELAXED))); 82 | # else 83 | if (MNL_UNLIKELY((long long)(heap_use + (size = ::malloc_usable_size(ptr) + sizeof(size_t))) > heap_lim - heap_res)) { 84 | ::free(ptr); 85 | if (heap_res) heap_res = 0, throw heap_exhausted{}; 86 | fprintf(stderr, "MANOOL: FATAL ERROR: %s\n", "Heap exhausted (and no reservation is in effect)"), fflush(stderr), _Exit(EXIT_FAILURE); 87 | } 88 | heap_use += size; 89 | # endif // # if MNL_WITH_MULTITHREADING 90 | return ptr; 91 | } 92 | MNL_INLINE inline void *_new(size_t size, const std::nothrow_t &) noexcept { 93 | if (MNL_UNLIKELY(!size)) size = 1; 94 | auto ptr = ::malloc(size); // Note: the VM pages are still not committed here 95 | if (MNL_UNLIKELY(!ptr)) { 96 | if (size <= 1ll << 47 && (long long) MNL_IF_WITH_MT(__atomic_load_n(&heap_use, __ATOMIC_RELAXED)) 97 | MNL_IF_WITHOUT_MT(heap_use) + (long long)size + (long long)sizeof(size_t) <= heap_lim - heap_res) 98 | perror("MANOOL: FATAL ERROR: Cannot malloc"), fflush(stderr), _Exit(EXIT_FAILURE); 99 | if (heap_res) return heap_res = 0, nullptr; 100 | fprintf(stderr, "MANOOL: FATAL ERROR: %s\n", "Heap exhausted (and no reservation is in effect)"), fflush(stderr), _Exit(EXIT_FAILURE); 101 | } 102 | # if MNL_WITH_MULTITHREADING 103 | size = ::malloc_usable_size(ptr) + sizeof(size_t); 104 | auto _heap_use = __atomic_load_n(&heap_use, __ATOMIC_RELAXED); 105 | do if (MNL_UNLIKELY((long long)(_heap_use + size) > heap_lim - heap_res)) { 106 | ::free(ptr); 107 | if (heap_res) return heap_res = 0, nullptr; 108 | fprintf(stderr, "MANOOL: FATAL ERROR: %s\n", "Heap exhausted (and no reservation is in effect)"), fflush(stderr), _Exit(EXIT_FAILURE); 109 | } while (MNL_UNLIKELY(!__atomic_compare_exchange_n(&heap_use, &_heap_use, _heap_use + size, {}, __ATOMIC_RELAXED, __ATOMIC_RELAXED))); 110 | # else 111 | if (MNL_UNLIKELY((long long)(heap_use + (size = ::malloc_usable_size(ptr) + sizeof(size_t))) > heap_lim - heap_res)) { 112 | ::free(ptr); 113 | if (heap_res) return heap_res = 0, nullptr; 114 | fprintf(stderr, "MANOOL: FATAL ERROR: %s\n", "Heap exhausted (and no reservation is in effect)"), fflush(stderr), _Exit(EXIT_FAILURE); 115 | } 116 | heap_use += size; 117 | # endif // # if MNL_WITH_MULTITHREADING 118 | return ptr; 119 | } 120 | MNL_INLINE inline void _delete(void *ptr) noexcept { 121 | if (MNL_UNLIKELY(!ptr)) return; 122 | auto size = ::malloc_usable_size(ptr) + sizeof(size_t); 123 | ::free(ptr), MNL_IF_WITH_MT(__atomic_sub_fetch(&heap_use, size, __ATOMIC_RELAXED))MNL_IF_WITHOUT_MT(heap_use -= size); 124 | } 125 | }} // namespace aux:: 126 | 127 | const char *stack_overflow::what() const noexcept { return "mnl::stack_overflow"; } 128 | const char *heap_exhausted::what() const noexcept { return "mnl::heap_exhausted"; } 129 | 130 | } // namespace MNL_AUX_UUID 131 | 132 | 133 | void *operator new(std::size_t size) { return mnl::_new(size); } 134 | void *operator new(std::size_t size, const std::nothrow_t &) noexcept { return mnl::_new(size, std::nothrow); } 135 | void operator delete(void *ptr) noexcept { mnl::_delete(ptr); } 136 | void operator delete(void *ptr, const std::nothrow_t &) noexcept { mnl::_delete(ptr); } 137 | 138 | void *operator new[](std::size_t size) { return mnl::_new(size); } 139 | void *operator new[](std::size_t size, const std::nothrow_t &) noexcept { return mnl::_new(size, std::nothrow); } 140 | void operator delete[](void *ptr) noexcept { mnl::_delete(ptr); } 141 | void operator delete[](void *ptr, const std::nothrow_t &) noexcept { mnl::_delete(ptr); } 142 | -------------------------------------------------------------------------------- /mnl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | # mnl 3 | test -e build/mnlexec && MNL_PATH=${MNL_PATH-build/lib} exec build/mnlexec "$@" 4 | printf 'Try first: make\n' >&2; exit 127 5 | -------------------------------------------------------------------------------- /mnl-aux-mnl0.hh: -------------------------------------------------------------------------------- 1 | // mnl-aux-mnl0.hh -- minimal infrastructure (mnl:: Namespaces + Host Compiler Idiosyncrasies) for otherwise self-sufficient modules 2 | 3 | /* Copyright (C) 2018, 2019, 2020 Alexey Protasov (AKA Alex or rusini) 4 | 5 | This file is part of MANOOL. 6 | 7 | MANOOL is free software: you can redistribute it and/or modify it under the terms of the version 3 of the GNU General Public License 8 | as published by the Free Software Foundation (and only version 3). 9 | 10 | MANOOL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License along with MANOOL. If not, see . */ 14 | 15 | 16 | # ifndef MNL_INCLUDED_MNL0 17 | # define MNL_INCLUDED_MNL0 18 | 19 | // Toolchain Checks //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 20 | # ifndef MNL_C_SOURCE 21 | # if __cplusplus < 201103/*C++11*/ || !__STDC_HOSTED__ || !__GNUC__/*g++/clang++/icpc...*/ || !__STRICT_ANSI__/*-std=c++NN*/ 22 | # error "Unsupported C++ compiler or compiler mode" 23 | # endif 24 | # else 25 | # if __STDC_VERSION__ < 199901/*C99*/ || !__STDC_HOSTED__ || !__GNUC__/*gcc/clang/icc...*/ || !__STRICT_ANSI__/*-std=cNN*/ 26 | # error "Unsupported C compiler or compiler mode" 27 | # endif 28 | # endif 29 | # if !(__i386__ && __SSE2_MATH__ || __x86_64__ || __AARCH64EL__ || __ARMEL__ && __VFP_FP__) || __SIZEOF_LONG__ != __SIZEOF_POINTER__ 30 | //# error "Unsupported or not tested target ISA or ABI" 31 | # endif 32 | # if __cplusplus // even more paranoid ABI check 33 | static_assert(sizeof(long) == sizeof(void *), "sizeof(long) == sizeof(void *)"); 34 | # endif 35 | 36 | // C++ Namespaces ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 37 | # if __cplusplus 38 | # if MNL_WITH_UUID_NS || defined MNL_AUX_UUID 39 | # ifndef MNL_AUX_UUID 40 | # define MNL_AUX_UUID uuid_CF067875_8A9C_4A0D_A889_35989E0140EF 41 | # endif 42 | namespace MNL_AUX_UUID { namespace aux { namespace pub {} using namespace pub; } using namespace aux::pub; } namespace mnl = MNL_AUX_UUID; 43 | # else 44 | # define MNL_AUX_UUID mnl 45 | namespace MNL_AUX_UUID { namespace aux { namespace pub {} using namespace pub; } using namespace aux::pub; } 46 | # endif 47 | # endif 48 | 49 | // Compiler Idiosyncrasies ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 50 | # define MNL_PACK __attribute__((__packed__)) 51 | # define MNL_ALIGN(ALIGN) __attribute__((__aligned__(ALIGN))) 52 | # define MNL_PRIORITY(PRI) __attribute__((__init_priority__(PRI))) 53 | # // the "proper" way to advise about violations of Strict Aliasing Rules: 54 | # define MNL_BARRIER() __extension__({ __asm volatile ("" : : : "memory"); }) // used by libdecnumber patch 55 | # 56 | # if MNL_USE_EXPECT 57 | # define MNL_LIKELY(...) (!__builtin_expect(!(__VA_ARGS__), 0)) 58 | # define MNL_UNLIKELY(...) (!__builtin_expect(!(__VA_ARGS__), 1)) 59 | # else 60 | # define MNL_LIKELY(...) (__VA_ARGS__) 61 | # define MNL_UNLIKELY(...) (__VA_ARGS__) 62 | # endif 63 | # if MNL_USE_INLINE 64 | # define MNL_INLINE __attribute__((__always_inline__)) 65 | # define MNL_NOINLINE __attribute__((__noinline__)) 66 | # else 67 | # define MNL_INLINE 68 | # define MNL_NOINLINE 69 | # endif 70 | # 71 | # define MNL_NORETURN __attribute__((__noreturn__, __noinline__, __cold__)) 72 | # define MNL_UNREACHABLE() __builtin_unreachable() 73 | 74 | # define MNL_DSO_HIDE __attribute__(__visibility__("hidden")) // may be used to speed up calling sequence a bit 75 | # define MNL_DSO_HIDE_BEGIN _Pragma("GCC visibility push(hidden)") // used by libdecnumber patch 76 | # define MNL_DSO_HIDE_END _Pragma("GCC visibility pop") // ditto 77 | # define MNL_DSO_UNHIDE_BEGIN _Pragma("GCC visibility push(default)") // ditto 78 | # define MNL_DSO_UNHIDE_END _Pragma("GCC visibility pop") // ditto 79 | 80 | # if MNL_USE_PURE 81 | # define MNL_PURE __attribute__((__const__)) 82 | # define MNL_NOCLOBBER __attribute__((__pure__)) 83 | # elif MNL_USE_NOCLOBBER 84 | # define MNL_PURE __attribute__((__pure__)) 85 | # define MNL_NOCLOBBER __attribute__((__pure__)) 86 | # else 87 | # define MNL_PURE 88 | # define MNL_NOCLOBBER 89 | # endif 90 | 91 | // Conditionals //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 92 | # if MNL_WITH_MULTITHREADING 93 | # define MNL_IF_WITH_MT(...) __VA_ARGS__ 94 | # define MNL_IF_WITHOUT_MT(...) 95 | # else 96 | # define MNL_IF_WITH_MT(...) 97 | # define MNL_IF_WITHOUT_MT(...) __VA_ARGS__ 98 | # endif 99 | # if MNL_WITH_IDENT_OPT 100 | # define MNL_IF_WITH_IDENT_OPT(...) __VA_ARGS__ 101 | # else 102 | # define MNL_IF_WITH_IDENT_OPT(...) 103 | # endif 104 | 105 | // To provide small workarounds for C++ compiler bugs 106 | # if !__clang__ && !__INTEL_COMPILER && __GNUC__ == 4 107 | # define MNL_IF_GCC4(...) __VA_ARGS__ 108 | # define MNL_IF_NOT_GCC4(...) 109 | # else 110 | # define MNL_IF_GCC4(...) 111 | # define MNL_IF_NOT_GCC4(...) __VA_ARGS__ 112 | # endif 113 | # if !__clang__ && !__INTEL_COMPILER && __GNUC__ == 5 114 | # define MNL_IF_GCC5(...) __VA_ARGS__ 115 | # define MNL_IF_NOT_GCC5(...) 116 | # else 117 | # define MNL_IF_GCC5(...) 118 | # define MNL_IF_NOT_GCC5(...) __VA_ARGS__ 119 | # endif 120 | # if !__clang__ && !__INTEL_COMPILER && __GNUC__ == 6 121 | # define MNL_IF_GCC6(...) __VA_ARGS__ 122 | # define MNL_IF_NOT_GCC6(...) 123 | # else 124 | # define MNL_IF_GCC6(...) 125 | # define MNL_IF_NOT_GCC6(...) __VA_ARGS__ 126 | # endif 127 | # if !__clang__ && !__INTEL_COMPILER && __GNUC__ == 7 128 | # define MNL_IF_GCC7(...) __VA_ARGS__ 129 | # define MNL_IF_NOT_GCC7(...) 130 | # else 131 | # define MNL_IF_GCC7(...) 132 | # define MNL_IF_NOT_GCC7(...) __VA_ARGS__ 133 | # endif 134 | # if !__clang__ && !__INTEL_COMPILER && __GNUC__ == 8 135 | # define MNL_IF_GCC8(...) __VA_ARGS__ 136 | # define MNL_IF_NOT_GCC8(...) 137 | # else 138 | # define MNL_IF_GCC8(...) 139 | # define MNL_IF_NOT_GCC8(...) __VA_ARGS__ 140 | # endif 141 | # if !__clang__ && !__INTEL_COMPILER && __GNUC__ == 9 142 | # define MNL_IF_GCC9(...) __VA_ARGS__ 143 | # define MNL_IF_NOT_GCC9(...) 144 | # else 145 | # define MNL_IF_GCC9(...) 146 | # define MNL_IF_NOT_GCC9(...) __VA_ARGS__ 147 | # endif 148 | # if __clang__ 149 | # define MNL_IF_CLANG(...) __VA_ARGS__ 150 | # define MNL_IF_NOT_CLANG(...) 151 | # else 152 | # define MNL_IF_CLANG(...) 153 | # define MNL_IF_NOT_CLANG(...) __VA_ARGS__ 154 | # endif 155 | # if __INTEL_COMPILER 156 | # define MNL_IF_ICC(...) __VA_ARGS__ 157 | # define MNL_IF_NOT_ICC(...) 158 | # else 159 | # define MNL_IF_ICC(...) 160 | # define MNL_IF_NOT_ICC(...) __VA_ARGS__ 161 | # endif 162 | 163 | # if __cplusplus && MNL_USE_DEBUG 164 | # include 165 | namespace MNL_AUX_UUID { namespace aux { using std::cerr; } } 166 | # endif 167 | 168 | # endif // # ifndef MNL_INCLUDED_MNL0 169 | -------------------------------------------------------------------------------- /mnl-lib-base.hh: -------------------------------------------------------------------------------- 1 | // mnl-lib-base.hh -- C++ API to base facilities 2 | 3 | /* Copyright (C) 2018, 2019, 2020 Alexey Protasov (AKA Alex or rusini) 4 | 5 | This file is part of MANOOL. 6 | 7 | MANOOL is free software: you can redistribute it and/or modify it under the terms of the version 3 of the GNU General Public License 8 | as published by the Free Software Foundation (and only version 3). 9 | 10 | MANOOL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License along with MANOOL. If not, see . */ 14 | 15 | 16 | # ifndef MNL_INCLUDED_BASE 17 | # define MNL_INCLUDED_BASE 18 | 19 | # include 20 | # include "manool.hh" 21 | # include "mnl-misc-dict.hh" 22 | 23 | namespace MNL_AUX_UUID { 24 | 25 | namespace aux { namespace pub { 26 | MNL_INLINE inline long long order(val lhs, val rhs) { return safe_cast(MNL_SYM("Order")(args<2>{move(lhs), move(rhs)})); } // Ordering for dict 27 | 28 | // MANOOL Pointers ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 29 | class w_pointer /*weak pointer*/ { 30 | public: 31 | val *value; 32 | MNL_IF_WITH_MT(mutable std::mutex mutex; std::mutex &val_mutex;) 33 | MNL_INLINE w_pointer(w_pointer &&rhs) noexcept: value(rhs.value) MNL_IF_WITH_MT(,val_mutex(rhs.val_mutex)) {} 34 | MNL_INLINE w_pointer(val *value MNL_IF_WITH_MT(,std::mutex &val_mutex)) noexcept: value(value) MNL_IF_WITH_MT(,val_mutex(val_mutex)) {} 35 | private: 36 | MNL_INLINE inline val invoke(val &&, const sym &, int, val [], val *) const; 37 | friend box; 38 | }; 39 | typedef class s_pointer /*strong pointer*/ { 40 | public: 41 | val value, weak; val cleanup; 42 | MNL_IF_WITH_MT(mutable std::mutex mutex;) 43 | s_pointer() = default; 44 | MNL_INLINE s_pointer(s_pointer &&rhs) noexcept: value(move(rhs.value)), cleanup(move(rhs.cleanup)) {} 45 | ~s_pointer(); 46 | MNL_INLINE s_pointer(val &&value) noexcept: value(move(value)) {} 47 | MNL_INLINE s_pointer(val &&value, val &&cleanup) noexcept: value(move(value)), cleanup(move(cleanup)) {} 48 | private: 49 | MNL_INLINE inline val invoke(val &&, const sym &, int, val [], val *); 50 | friend box; 51 | } pointer; 52 | }} // namespace aux::pub 53 | template<> val box> :: invoke(val &&, const sym &, int, val [], val *); // Map 54 | template<> val box> :: invoke(val &&, const sym &, int, val [], val *); // Set 55 | template<> val box> :: invoke(val &&, const sym &, int, val [], val *); // Sequence 56 | extern template class box; 57 | extern template class box; 58 | 59 | } // namespace MNL_AUX_UUID 60 | 61 | # endif // # ifndef MNL_INCLUDED_BASE 62 | -------------------------------------------------------------------------------- /mnl-lib-ieee754-cmpx.hh: -------------------------------------------------------------------------------- 1 | // mnl-lib-ieee754-cmpx.hh 2 | # ifndef MNL_INCLUDED_IEEE754_CMPX 3 | # define MNL_INCLUDED_IEEE754_CMPX 4 | # include 5 | # include "manool.hh" 6 | template<> auto mnl::box> :: invoke(val &&, const sym &, int, val [], val *)->val; // Z64[] 7 | template<> auto mnl::box> :: invoke(val &&, const sym &, int, val [], val *)->val; // Z32[] 8 | # endif // # ifndef MNL_INCLUDED_IEEE754_CMPX 9 | -------------------------------------------------------------------------------- /mnl-lib-ieee754-dec.hh: -------------------------------------------------------------------------------- 1 | // mnl-lib-ieee754-dec.hh 2 | # ifndef MNL_INCLUDED_IEEE754_DEC 3 | # define MNL_INCLUDED_IEEE754_DEC 4 | # include "mnl-misc-decimal.hh" 5 | # include "manool.hh" 6 | template<> auto mnl::box> :: invoke(val &&, const sym &, int, val [], val *)->val; // D64[] 7 | template<> auto mnl::box> :: invoke(val &&, const sym &, int, val [], val *)->val; // D128[] 8 | template<> auto mnl::box> :: invoke(val &&, const sym &, int, val [], val *)->val; // C64[] 9 | template<> auto mnl::box> :: invoke(val &&, const sym &, int, val [], val *)->val; // C128[] 10 | # endif // # ifndef MNL_INCLUDED_IEEE754_DEC 11 | -------------------------------------------------------------------------------- /mnl-misc-decimal.hh: -------------------------------------------------------------------------------- 1 | // mnl-misc-decimal.hh -- thin wrapper around libdecnumber for IEEE 754 formats 2 | 3 | /* Copyright (C) 2018, 2019, 2020 Alexey Protasov (AKA Alex or rusini) 4 | 5 | This file is part of MANOOL. 6 | 7 | MANOOL is free software: you can redistribute it and/or modify it under the terms of the version 3 of the GNU General Public License 8 | as published by the Free Software Foundation (and only version 3). 9 | 10 | MANOOL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License along with MANOOL. If not, see . */ 14 | 15 | 16 | # ifndef MNL_INCLUDED_DECIMAL 17 | # define MNL_INCLUDED_DECIMAL 18 | 19 | # include // aligned_storage 20 | # include // rel_ops 21 | # include 22 | # include "mnl-aux-mnl0.hh" 23 | 24 | namespace MNL_AUX_UUID { 25 | namespace aux { 26 | using std::string; 27 | } 28 | 29 | namespace aux { namespace pub { 30 | template class dec/*imal FP*/ { 31 | static_assert(Width == 64 || Width == 128, "Width == 64 || Width == 128"); 32 | public: // Construction and simple assignment 33 | dec() = default; 34 | dec &operator=(const dec &) = default; 35 | MNL_INLINE dec(const char rhs[]) noexcept: dec(make(rhs)) {} 36 | MNL_INLINE dec(const string &rhs) noexcept: dec(rhs.c_str()) {} 37 | MNL_INLINE dec(int rhs) noexcept: dec(MNL_LIKELY(rhs) ? make(rhs) : dec{}) {} 38 | MNL_INLINE dec(unsigned rhs) noexcept: dec(MNL_LIKELY(rhs) ? make(rhs) : dec{}) {} 39 | MNL_INLINE dec &operator=(const char rhs[]) noexcept { return *this = rhs; } 40 | MNL_INLINE dec &operator=(const string &rhs) noexcept { return *this = rhs; } 41 | MNL_INLINE dec &operator=(int rhs) noexcept { return *this = rhs; } 42 | MNL_INLINE dec &operator=(unsigned rhs) noexcept { return *this = rhs; } 43 | MNL_INLINE explicit dec(dec rhs) noexcept: _(rhs._) {} 44 | public: // Extraction 45 | typedef char str_buf[Width == 64 ? 25 : Width == 128 ? 43 : 0]; 46 | char *to_str(str_buf) const noexcept, *to_eng_str(str_buf) const noexcept; 47 | MNL_INLINE string to_str() const { str_buf buf; return to_str(buf), buf; } 48 | MNL_INLINE string to_eng_str() const { str_buf buf; return to_eng_str(buf), buf; } 49 | MNL_INLINE operator string() const { return to_str(); } 50 | public: // Compound assignment 51 | MNL_INLINE dec &operator+=(dec rhs) noexcept { return *this = *this + rhs; } 52 | MNL_INLINE dec &operator-=(dec rhs) noexcept { return *this = *this - rhs; } 53 | MNL_INLINE dec &operator*=(dec rhs) noexcept { return *this = *this * rhs; } 54 | MNL_INLINE dec &operator/=(dec rhs) noexcept { return *this = *this / rhs; } 55 | private: // Internals 56 | typename std::aligned_storage::type _; 57 | static dec make(const char []) noexcept, make(int) noexcept, make(unsigned) noexcept; 58 | }; 59 | # define MNL_M(TYPE) \ 60 | template<> MNL_NOCLOBBER TYPE TYPE::make(const char []) noexcept; \ 61 | template<> MNL_PURE TYPE TYPE::make(int) noexcept; \ 62 | template<> MNL_PURE TYPE TYPE::make(unsigned) noexcept; \ 63 | template<> char *TYPE::to_str(char []) const noexcept; \ 64 | template<> char *TYPE::to_eng_str(char []) const noexcept; \ 65 | MNL_PURE bool isfinite(TYPE) noexcept, isinf(TYPE) noexcept, isnan(TYPE) noexcept, signbit(TYPE) noexcept; \ 66 | MNL_PURE TYPE operator+(TYPE, TYPE) noexcept, operator-(TYPE, TYPE) noexcept, operator*(TYPE, TYPE) noexcept, operator/(TYPE, TYPE) noexcept; \ 67 | MNL_PURE TYPE operator+(TYPE rhs) noexcept, operator-(TYPE) noexcept, abs(TYPE) noexcept, fma(TYPE, TYPE, TYPE) noexcept; \ 68 | MNL_PURE bool operator==(TYPE, TYPE) noexcept, operator<(TYPE, TYPE) noexcept; \ 69 | MNL_PURE int order(TYPE, TYPE) noexcept; \ 70 | MNL_INLINE inline bool operator!=(TYPE lhs, TYPE rhs) noexcept { return std::rel_ops::operator!=(lhs, rhs); } \ 71 | MNL_INLINE inline bool operator> (TYPE lhs, TYPE rhs) noexcept { return std::rel_ops::operator> (lhs, rhs); } \ 72 | MNL_INLINE inline bool operator<=(TYPE lhs, TYPE rhs) noexcept { return std::rel_ops::operator<=(lhs, rhs); } \ 73 | MNL_INLINE inline bool operator>=(TYPE lhs, TYPE rhs) noexcept { return std::rel_ops::operator>=(lhs, rhs); } \ 74 | MNL_PURE TYPE exp(TYPE) noexcept, log(TYPE) noexcept, log10(TYPE) noexcept, sqr(TYPE) noexcept, sqrt(TYPE) noexcept, pow(TYPE, TYPE) noexcept; \ 75 | MNL_PURE TYPE trunc(TYPE) noexcept, round(TYPE) noexcept, floor(TYPE) noexcept, ceil(TYPE) noexcept, quantize(TYPE, TYPE) noexcept; \ 76 | // end # define MNL_M(TYPE) 77 | # define MNL_T(...) __VA_ARGS__ 78 | MNL_M(MNL_T(dec<64, true>)) MNL_M(MNL_T(dec<128, true>)) 79 | MNL_M(MNL_T(dec<64, false>)) MNL_M(MNL_T(dec<128, false>)) 80 | # undef MNL_T 81 | # undef MNL_M 82 | }} // namespace aux::pub 83 | 84 | } // namespace MNL_AUX_UUID 85 | 86 | # endif // # ifndef MNL_INCLUDED_DECIMAL 87 | -------------------------------------------------------------------------------- /mnl-misc-memmgm.hh: -------------------------------------------------------------------------------- 1 | // mnl-misc-memmgm.hh -- general memory management 2 | 3 | /* Copyright (C) 2018, 2019, 2020 Alexey Protasov (AKA Alex or rusini) 4 | 5 | This file is part of MANOOL. 6 | 7 | MANOOL is free software: you can redistribute it and/or modify it under the terms of the version 3 of the GNU General Public License 8 | as published by the Free Software Foundation (and only version 3). 9 | 10 | MANOOL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License along with MANOOL. If not, see . */ 14 | 15 | 16 | # ifndef MNL_INCLUDED_MEMMGM 17 | # define MNL_INCLUDED_MEMMGM 18 | 19 | # include "mnl-aux-mnl0.hh" 20 | 21 | # include // exception 22 | # include // bad_alloc 23 | 24 | namespace MNL_AUX_UUID { 25 | 26 | namespace aux { 27 | extern MNL_IF_WITH_MT(thread_local) long long stk_lim; 28 | MNL_NORETURN void err_stk_overflow(); 29 | } // namespace aux 30 | 31 | namespace aux { namespace pub { 32 | void stk_limit(long long) noexcept, heap_limit(long long) noexcept /*NOT MT-safe!*/; // precond: size >= 0, size < 1ll << 47 33 | long long stk_reserve(long long) noexcept, heap_reserve(long long) noexcept; // ditto 34 | MNL_INLINE inline void stk_check() { unsigned long _; if (MNL_UNLIKELY(reinterpret_cast(&_) < stk_lim)) err_stk_overflow(); } 35 | class stack_overflow: public std::exception { const char *what() const noexcept override; }; 36 | class heap_exhausted: public std::bad_alloc { const char *what() const noexcept override; }; 37 | }} // namespace aux::pub 38 | 39 | } // namespace MNL_AUX_UUID 40 | 41 | #endif // # ifndef MNL_INCLUDED_MEMMGM 42 | -------------------------------------------------------------------------------- /test.mnl: -------------------------------------------------------------------------------- 1 | -- test.mnl 2 | 3 | { {extern "manool.org.18/std/0.6/all"} in 4 | : let { AllocOpt = False } in 5 | : let { N = 40; M = 80 } in 6 | : let { G = 2 } in 7 | 8 | : let 9 | { Display = 10 | { proc { B } as 11 | : for { I = Range[N]$ } do 12 | : do Out.WriteLine[] after 13 | : for { J = Range[M]$ } do 14 | Out.Write[{if B[I; J] <> 0 then "*" else " "}] 15 | } 16 | } 17 | in 18 | 19 | : var { B = {array N of: array M of 0} } in 20 | -- initialization 21 | B[19; 41] = 1 22 | B[20; 40] = 1 23 | B[21; 40] = 1 24 | B[22; 40] = 1 25 | B[22; 41] = 1 26 | B[22; 42] = 1 27 | B[22; 43] = 1 28 | B[19; 44] = 1 29 | -- end of initialization 30 | /*Out.WriteLine["Before:"]; Display[B]*/ 31 | 32 | { var { NextB = B } in 33 | : repeat G do 34 | : do {if ~AllocOpt then (B = NextB)' else {assign B = NextB; NextB = B}'}% after 35 | : for { I = Range[N]$ } do 36 | : var { Up = {if I <> 0 then I - 1 else (N - 1)$}; Down = {if I <> (N - 1)$ then I + 1 else 0} } in 37 | : for { J = Range[M]$ } do 38 | : var { Left = {if J <> 0 then J - 1 else (M - 1)$}; Right = {if J <> (M - 1)$ then J + 1 else 0} } in 39 | : var 40 | { Count = 41 | B[Up ; Left ] + 42 | B[Up ; J ] + 43 | B[Up ; Right] + 44 | B[I ; Right] + 45 | B[Down; Right] + 46 | B[Down; J ] + 47 | B[Down; Left ] + 48 | B[I ; Left ] 49 | } 50 | in 51 | NextB[I; J] = 52 | { if Count == 2 then B[I; J] else 53 | : if Count == 3 then 1 else 54 | 0 55 | } 56 | } 57 | /*Out.WriteLine["After " G " generations:"]; Display[B]*/ 58 | { var { ExpectedB = {array N of: array M of 0} } in 59 | ExpectedB[20; 39] = 1 60 | ExpectedB[20; 40] = 1 61 | ExpectedB[20; 41] = 1 62 | ExpectedB[21; 39] = 1 63 | ExpectedB[21; 42] = 1 64 | ExpectedB[22; 39] = 1 65 | ExpectedB[22; 43] = 1 66 | ExpectedB[23; 40] = 1 67 | ExpectedB[23; 42] = 1 68 | Out.WriteLine[{if B == ExpectedB then "Success" else "Fail"}] 69 | } 70 | } 71 | --------------------------------------------------------------------------------