Universal Number Arithmetic

Overview

Universal: a header-only C++ template library for universal number arithmetic

Codacy Badge Awesome Cpp FOSSA Status Codeship Status for stillwater-sc/universal Coverage Status

The goal of the Universal Numbers Library is to offer applications alternatives to IEEE floating-point that are more efficient and mathematically robust.

The motivation to find improvements to IEEE floating-point had been brewing in the HPC community since the late 90's as most algorithms became memory bound and computational scientists were looking for alternatives that provided more granularity in precision and dynamic range. Even though the inefficiency of IEEE floating-point had been measured and agreed upon in the HPC community, it was the commercial demands of Deep Learning that provided the incentive to replaced IEEE-754 with alternatives, such as half-floats, and bfloats. These alternatives are tailored to the application and yield speed-ups of two to three orders of magnitude, making rapid innovation in AI possible.

The Universal library is a ready-to-use header-only library that provides plug-in replacement for native types, and provides a low-friction environment to start exploring alternatives to IEEE floating-point in your own algorithms.

The basic use pattern is as simple as:

#include <universal/number/posit/posit>

template<typename Real>
Real MyKernel(const Real& a, const Real& b) {
    return a * b;  // replace this with your kernel computation
}

constexpr double pi = 3.14159265358979323846;

int main() {
    using Real = sw::universal::posit<32,2>;  

    Real a = sqrt(2);
    Real b = pi;
    std::cout << "Result: " << MyKernel(a, b) << std::endl;
  
}

The library contains integers, decimals, fixed-points, rationals, linear floats, tapered floats, logarithmic, interval and adaptive-precision integers and floats. There are example number system skeletons to get you started quickly if you desire to add your own, which is highly encouraged.

Communication channels

  • GitHub Issue: bug reports, feature requests, etc.
  • Forum: discussion of alternatives to IEEE-754 for computational science.
  • Slack: online chats, discussions, and collaboration with other users, researchers and developers.

Citation

Please cite our work if you use Universal.

@article{Omtzigt2020,
    author    = {E. Theodore L. Omtzigt and Peter Gottschling and Mark Seligman and William Zorn},
    title     = {{Universal Numbers Library}: design and implementation of a high-performance reproducible number systems library},
    journal   = {arXiv:2012.11011},
    year      = {2020},
}

Quick start

If you just want to experiment with the number system tools and test suites, and don't want to bother cloning and building the source code, there is a Docker container to get started:

> docker pull stillwater/universal
> docker run -it --rm stillwater/universal bash
stillwater@b3e6708fd732:~/universal/build$ ls
CMakeCache.txt       Makefile      cmake-uninstall.cmake  playground  universal-config-version.cmake
CMakeFiles           applications  cmake_install.cmake    tests       universal-config.cmake
CTestTestfile.cmake  c_api         education              tools       universal-targets.cmake

From the build directory, it is convenient to run any of the regression test suites:

stillwater@b3e6708fd732:~/universal/build$ tests/posit/specialized/fast_posit_8_0
Fast specialization posit<8,0> configuration tests
 posit<  8,0> useed scale     1     minpos scale         -6     maxpos scale          6
Logic operator tests
 posit<8,0>     ==         (native)   PASS
 posit<8,0>     !=         (native)   PASS
 posit<8,0>     <          (native)   PASS
 posit<8,0>     <=         (native)   PASS
 posit<8,0>     >          (native)   PASS
 posit<8,0>     >=         (native)   PASS
Assignment/conversion tests
 posit<8,0> integer assign (native)   PASS
 posit<8,0> float assign   (native)   PASS
Arithmetic tests
 posit<8,0> add            (native)   PASS
 posit<8,0> +=             (native)   PASS
 posit<8,0> subtract       (native)   PASS
 posit<8,0> -=             (native)   PASS
 posit<8,0> multiply       (native)   PASS
 posit<8,0> *=             (native)   PASS
 posit<8,0> divide         (native)   PASS
 posit<8,0> /=             (native)   PASS
 posit<8,0> negate         (native)   PASS
 posit<8,0> reciprocate    (native)   PASS
Elementary function tests
 posit<8,0> sqrt           (native)   PASS
 posit<8,0> exp                       PASS
 posit<8,0> exp2                      PASS
 posit<8,0> log                       PASS
 posit<8,0> log2                      PASS
 posit<8,0> log10                     PASS
 posit<8,0> sin                       PASS
 posit<8,0> cos                       PASS
 posit<8,0> tan                       PASS
 posit<8,0> atan                      PASS
 posit<8,0> asin                      PASS
 posit<8,0> acos                      PASS
 posit<8,0> sinh                      PASS
 posit<8,0> cosh                      PASS
 posit<8,0> tanh                      PASS
 posit<8,0> atanh                     PASS
 posit<8,0> acosh                     PASS
 posit<8,0> asinh                     PASS
ValidatePower has been truncated
 posit<8,0> pow                       PASS

In /usr/local/bin there are a set of command line utilities to inspect floating point encodings.

stillwater@b3e6708fd732:~/universal/build$ ls /usr/local/bin
compd  compf  compfp  compieee  compld  complns  compp  compsi  compui  float2posit  propenv  propp

stillwater@b3e6708fd732:~/universal$ compieee 1.2345678901234567890123
compiler              : 7.5.0
float precision       : 23 bits
double precision      : 52 bits
long double precision : 63 bits

Representable?        : maybe

Decimal representations
input value:  1.2345678901234567890123
      float:                1.23456788
     double:        1.2345678901234567
long double:    1.23456789012345678899

Hex representations
input value:  1.2345678901234567890123
      float:                1.23456788    hex: 0.7f.1e0652
     double:        1.2345678901234567    hex: 0.3ff.3c0ca428c59fb
long double:    1.23456789012345678899    hex: 0.3fff.1e06521462cfdb8d

Binary representations:
      float:                1.23456788    bin: 0.01111111.00111100000011001010010
     double:        1.2345678901234567    bin: 0.01111111111.00111100000011001010010000101000110001011001                        11111011
long double:    1.23456789012345678899    bin: 0.011111111111111.0011110000001100101001000010100011000101                        10011111101101110001101

Native triple representations (sign, scale, fraction):
      float:                1.23456788    triple: (+,0,00111100000011001010010)
     double:        1.2345678901234567    triple: (+,0,00111100000011001010010000101000110001011001111110                        11)
long double:    1.23456789012345678899    triple: (+,0,00111100000011001010010000101000110001011001111110                        1101110001101)

Scientific triple representation (sign, scale, fraction):
input value:  1.2345678901234567890123
      float:                1.23456788    triple: (+,0,00111100000011001010010)
     double:        1.2345678901234567    triple: (+,0,00111100000011001010010000101000110001011001111110                        11)
long double:    1.23456789012345678899    triple: (+,0,00111100000011001010010000101000110001011001111110                        1101110001101)
      exact: TBD

Or posit encodings:

stillwater@b3e6708fd732:~/universal/build$ compp 1.2345678901234567890123
posit< 8,0> = s0 r10 e f01000 qNE v1.25
posit< 8,1> = s0 r10 e0 f0100 qNE v1.25
posit< 8,2> = s0 r10 e00 f010 qNE v1.25
posit< 8,3> = s0 r10 e000 f01 qNE v1.25
posit<16,1> = s0 r10 e0 f001111000001 qNE v1.234619140625
posit<16,2> = s0 r10 e00 f00111100000 qNE v1.234375
posit<16,3> = s0 r10 e000 f0011110000 qNE v1.234375
posit<32,1> = s0 r10 e0 f0011110000001100101001000011 qNE v1.2345678918063641
posit<32,2> = s0 r10 e00 f001111000000110010100100001 qNE v1.2345678880810738
posit<32,3> = s0 r10 e000 f00111100000011001010010001 qNE v1.2345678955316544
posit<48,1> = s0 r10 e0 f00111100000011001010010000101000110001011010 qNE v1.2345678901234578
posit<48,2> = s0 r10 e00 f0011110000001100101001000010100011000101101 qNE v1.2345678901234578
posit<48,3> = s0 r10 e000 f001111000000110010100100001010001100010110 qNE v1.2345678901233441
posit<64,1> = s0 r10 e0 f001111000000110010100100001010001100010110011111101100000000 qNE v1.2345678901234567
posit<64,2> = s0 r10 e00 f00111100000011001010010000101000110001011001111110110000000 qNE v1.2345678901234567
posit<64,3> = s0 r10 e000 f0011110000001100101001000010100011000101100111111011000000 qNE v1.2345678901234567
posit<64,4> = s0 r10 e0000 f001111000000110010100100001010001100010110011111101100000 qNE v1.2345678901234567

The following two educational examples are pretty informative when you are just starting out learning about posits: edu_scales and edu_tables.

stillwater@b3e6708fd732:~/universal/build$ education/posit/edu_scales
Experiments with the scale of posit numbers
Posit specificiation examples and their ranges:
Scales are represented as the binary scale of the number: i.e. 2^scale

Small, specialized posit configurations
nbits = 3
 posit<  3,0> useed scale     1     minpos scale         -1     maxpos scale          1
 posit<  3,1> useed scale     2     minpos scale         -2     maxpos scale          2
 posit<  3,2> useed scale     4     minpos scale         -4     maxpos scale          4
 posit<  3,3> useed scale     8     minpos scale         -8     maxpos scale          8
 posit<  3,4> useed scale    16     minpos scale        -16     maxpos scale         16
nbits = 4
 posit<  4,0> useed scale     1     minpos scale         -2     maxpos scale          2
 posit<  4,1> useed scale     2     minpos scale         -4     maxpos scale          4
 posit<  4,2> useed scale     4     minpos scale         -8     maxpos scale          8
 posit<  4,3> useed scale     8     minpos scale        -16     maxpos scale         16
 posit<  4,4> useed scale    16     minpos scale        -32     maxpos scale         32
nbits = 5
 posit<  5,0> useed scale     1     minpos scale         -3     maxpos scale          3
 posit<  5,1> useed scale     2     minpos scale         -6     maxpos scale          6
 posit<  5,2> useed scale     4     minpos scale        -12     maxpos scale         12
 posit<  5,3> useed scale     8     minpos scale        -24     maxpos scale         24
 posit<  5,4> useed scale    16     minpos scale        -48     maxpos scale         48
...

The command edu_tables generates tables of full posit encodings and their constituent parts:

stillwater@b3e6708fd732:~/universal/build$ education/posit/edu_tables | more
Generate posit configurations
Generate Posit Lookup table for a POSIT<2,0> in TXT format
   #           Binary         Decoded       k    sign   scale          regime        exponent        fraction
     value    posit_format
   0:               00              00      -1       0       0               0               ~               ~
          0           2.0x0p
   1:               01              01       0       0       0               1               ~               ~
          1           2.0x1p
   2:               10              10       1       1       0               0               ~               ~
        nar           2.0x2p
   3:               11              11       0       1       0               1               ~               ~
         -1           2.0x3p
Generate Posit Lookup table for a POSIT<3,0> in TXT format
   #           Binary         Decoded       k    sign   scale          regime        exponent        fraction
     value    posit_format
   0:              000             000      -2       0      -1              00               ~               ~
          0           3.0x0p
   1:              001             001      -1       0      -1              01               ~               ~
        0.5           3.0x1p
   2:              010             010       0       0       0              10               ~               ~
          1           3.0x2p
   3:              011             011       1       0       1              11               ~               ~
          2           3.0x3p
   4:              100             100       2       1      -1              00               ~               ~
        nar           3.0x4p
   5:              101             111       1       1       1              11               ~               ~
         -2           3.0x5p
   6:              110             110       0       1       0              10               ~               ~
         -1           3.0x6p
   7:              111             101      -1       1      -1              01               ~               ~
       -0.5           3.0x7p
...

How to build

If you do want to work with the code, the universal numbers software library is built using cmake version v3.18. Install the latest cmake. There are interactive installers for MacOS and Windows. For Linux, a portable approach downloads the shell archive and installs it at /usr/local:

> wget https://github.com/Kitware/CMake/releases/download/v3.18.2/cmake-3.18.2-Linux-x86_64.sh 
> sudo sh cmake-3.18.2-Linux-x86_64.sh --prefix=/usr/local --exclude-subdir

For Ubuntu, snap will install the latest cmake, and would be the preferred method:

> sudo snap install cmake --classic

The Universal library is a pure C++ template library without any further dependencies, even for the regression test suites, to enable hassle-free installation and use.

Simply clone the github repo, and you are ready to build the different components of the Universal library. The library contains tools to work with integers, decimals, fixed-points, floats, posits, valids, and logarithmic number systems. It contains educational programs that showcase simple use cases to familiarize yourself with different number systems, and application examples to highlight the use of different number systems to gain performance or numerical accuracy. Finally, each number system offers its own verification suite.

The easiest way to become familiar with all the options in the build process is to fire up the CMake GUI (or ccmake if you are on a headless server). The cmake output will summarize which options have been set. The output will looks something like this:

$ git clone https://github.com/stillwater-sc/universal
$ cd universal
$ mkdir build
$ cd build
$ cmake ..
-- The C compiler identification is GNU 7.5.0
-- The CXX compiler identification is GNU 7.5.0
-- The ASM compiler identification is GNU
-- Found assembler: /usr/bin/cc
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- No default build type specified: setting CMAKE_BUILD_TYPE=Release
-- C++17 support has been enabled by default
-- Performing Test COMPILER_HAS_SSE3_FLAG
-- Performing Test COMPILER_HAS_SSE3_FLAG - Success
-- Performing Test COMPILER_HAS_AVX_FLAG
-- Performing Test COMPILER_HAS_AVX_FLAG - Success
-- Performing Test COMPILER_HAS_AVX2_FLAG
-- Performing Test COMPILER_HAS_AVX2_FLAG - Success
-- universal -> universal
-- include_install_dir         = include
-- include_install_dir_full    = include/universal
-- config_install_dir          = share/universal
-- include_install_dir_postfix = universal
-- PROJECT_SOURCE_DIR          = /home/stillwater/dev/clones/universal
-- PROJECT_VERSION             = 2.1.41
-- CMAKE_CURRENT_SOURCE_DIR    = /home/stillwater/dev/clones/universal
-- CMAKE_CURRENT_BINARY_DIR    = /home/stillwater/dev/clones/universal/build
--
-- ******************* Universal Arithmetic Library Configuration Summary *******************
-- General:
--   Version                      :   2.1.41
--   System                       :   Linux
--   C compiler                   :   /usr/bin/cc
--   Release C flags              :   -O3 -DNDEBUG -Wall -Wpedantic -Wno-narrowing -Wno-deprecated
--   Debug C flags                :   -g -Wall -Wpedantic -Wno-narrowing -Wno-deprecated
--   C++ compiler                 :   /usr/bin/c++
--   Release CXX flags            :   -O3 -DNDEBUG -std=c++14  -Wall -Wpedantic -Wno-narrowing -Wno-deprecated -std=c++14  -Wall -Wpedantic -Wno-narrowing -Wno-deprecated
--   Debug CXX flags              :   -g -std=c++14  -Wall -Wpedantic -Wno-narrowing -Wno-deprecated -std=c++14  -Wall -Wpedantic -Wno-narrowing -Wno-deprecated
--   Build type                   :   Release
--
--   BUILD_CI_CHECK               :   OFF
--
--   BUILD_STORAGE_CLASSES        :   OFF
--   BUILD_NATIVE_TYPES           :   OFF
--   BUILD_INTEGERS               :   OFF
--   BUILD_DECIMALS               :   OFF
--   BUILD_FIXPNTS                :   OFF
--   BUILD_LNS                    :   OFF
--   BUILD_UNUM_TYPE_1            :   OFF
--   BUILD_UNUM_TYPE_2            :   OFF
--   BUILD_POSITS                 :   OFF
--   BUILD_VALIDS                 :   OFF
--   BUILD_REALS                  :   OFF
--
--   BUILD_C_API_PURE_LIB         :   OFF
--   BUILD_C_API_SHIM_LIB         :   OFF
--   BUILD_C_API_LIB_PIC          :   OFF
--
--   BUILD_CMD_LINE_TOOLS         :   ON
--   BUILD_EDUCATION              :   ON
--   BUILD_APPLICATIONS           :   ON
--   BUILD_NUMERICAL              :   OFF
--   BUILD_FUNCTIONS              :   OFF
--   BUILD_PLAYGROUND             :   ON
--
--   BUILD_CONVERSION_TESTS       :   OFF
--
--   BUILD_PERFORMANCE_TESTS      :   OFF
--
--   BUILD_IEEE_FLOAT_QUIRES      :   OFF
--
--   BUILD_DOCS                   :   OFF
--
-- Dependencies:
--   SSE3                         :   NO
--   AVX                          :   NO
--   AVX2                         :   NO
--   Pthread                      :   NO
--   TBB                          :   NO
--   OMP                          :   NO
--
-- Utilities:
--   Serializer                   :   NO
--
-- Install:
--   Install path                 :   /usr/local
--
-- Configuring done
-- Generating done
-- Build files have been written to: /home/stillwater/dev/clones/universal/build

The build options are enabled/disabled as follows:

> cmake -DBUILD_EDUCATION=OFF -DBUILD_POSITS=ON ..

After building, issue the command make test to run the complete test suite of all the enabled components, as a regression capability when you are modifying the source code. This will take several minutes but will touch all the corners of the code.

> git clone https://github.com/stillwater-sc/universal
> cd universal
> mkdir build
> cd build
> cmake ..
> make -j $(nproc)
> make test

For Windows and Visual Studio, there are CMakePredefinedTargets that accomplish the same tasks:

    - ALL_BUILD will compile all the projects
    - INSTALL   will install the Universal library
    - RUN_TESTS will run all tests

visual-studio-project

Installation and usage

After cloning the library, building and testing it in your environment, you can install it via:

> cd universal/build
> cmake .. -DCMAKE_INSTALL_PREFIX:PATH=/your/installation/path
> cmake --build . --config Release --target install -- -j $(nproc)

or manually via the Makefile target in the build directory:

> make -j ${nproc) install

The default install directory is /usr/local under Linux. There is also an uninstall

> make uninstall

If you want to use the number systems provided by Universal in your own project, you can use the following CMakeLists.txt structure:

project("my-numerical-experiment")

find_package(UNIVERSAL CONFIG REQUIRED)

add_executable(${PROJECT_NAME} src/mymain.cpp)
target_link_libraries(${PROJECT_NAME} UNIVERSAL::UNIVERSAL)

Controlling the build to include different components

The default build configuration will build the command line tools, a playground, educational and application examples. If you want to build the full regression suite across all the number systems, use the following cmake command:

cmake -DBUILD_CI_CHECK=ON ..

For performance, the build configuration can enable specific x86 instruction sets (SSE/AVX/AVX2). For example, if your processor supports the AVX2 instruction set, you can build the test suites and educational examples with the AVX2 flag turned on. This typically yields a 20% performance boost.

cmake -DBUILD_CI_CHECK=on -DUSE_AVX2=ON ..

The library builds a set of useful command utilities to inspect native IEEE float/double/long double numbers as well as the custom number systems provided by Universal. Assuming you have build and installed the library, the commands are

    compieee       -- show the components (sign, scale, fraction) of the full set of IEEE floating point values
    compsi         -- show the components (sign, scale, fraction) of a signed integer value
    compui         -- show the components (sign, scale, fraction) of an unsigned integer value
    compf          -- show the components (sign, scale, fraction) of a float value
    compd          -- show the components (sign, scale, fraction) of a double value
    compld         -- show the components (sign, scale, fraction) of a long double value
    compfp         -- show the components (sign, scale, fraction) of a fixed-point value
    compp          -- show the components (sign, scale, fraction) of a posit value
    complns        -- show the components (sign, scale, fraction) of a logarithmic number system value

    convert        -- show the conversion process of a Real value to a posit

    propenv        -- show the properties of the execution (==compiler) environment that built the library
    propp          -- show numerical properties of a posit environment including the associated quire

For example:

$ compieee 1.234567890123456789012
compiler              : 7.5.0
float precision       : 23 bits
double precision      : 52 bits
long double precision : 63 bits

Decimal representations
input value:             1.23456789012
      float:                1.23456788
     double:        1.2345678901199999
long double:    1.23456789011999999999

Hex representations
input value:             1.23456789012
      float:                1.23456788    hex: 0.7f.1e0652
     double:        1.2345678901199999    hex: 0.3ff.3c0ca428c1d2b
long double:    1.23456789011999999999    hex: 0.3fff.1e06521460e95b9a

Binary representations:
      float:                1.23456788    bin: 0.01111111.00111100000011001010010
     double:        1.2345678901199999    bin: 0.01111111111.0011110000001100101001000010100011000001110100101011
long double:    1.23456789011999999999    bin: 0.011111111111111.001111000000110010100100001010001100000111010010101101110011010

Native triple representations (sign, scale, fraction):
      float:                1.23456788    triple: (+,0,00111100000011001010010)
     double:        1.2345678901199999    triple: (+,0,0011110000001100101001000010100011000001110100101011)
long double:    1.23456789011999999999    triple: (+,0,001111000000110010100100001010001100000111010010101101110011010)

Universal triple representation (sign, scale, fraction):
input value:             1.23456789012
      float:                1.23456788    triple: (+,0,00111100000011001010010)
     double:        1.2345678901199999    triple: (+,0,0011110000001100101001000010100011000001110100101011)
long double:    1.23456789011999999999    triple: (+,0,001111000000110010100100001010001100000111010010101101110011010)
      exact: TBD

This compieee command is very handy to quickly determine how your development environment represents (truncates) a specific value.

The specific commands compf, compd, and compld focus on float, double, and long double representations respectively.

There is also a command compp to help you visualize and compare the posit component fields for a given value, for example:

$ compp 1.234567890123456789012
posit< 8,0> = s0 r10 e f01000 qNE v1.25
posit< 8,1> = s0 r10 e0 f0100 qNE v1.25
posit< 8,2> = s0 r10 e00 f010 qNE v1.25
posit< 8,3> = s0 r10 e000 f01 qNE v1.25
posit<16,1> = s0 r10 e0 f001111000001 qNE v1.234619140625
posit<16,2> = s0 r10 e00 f00111100000 qNE v1.234375
posit<16,3> = s0 r10 e000 f0011110000 qNE v1.234375
posit<32,1> = s0 r10 e0 f0011110000001100101001000011 qNE v1.2345678918063641
posit<32,2> = s0 r10 e00 f001111000000110010100100001 qNE v1.2345678880810738
posit<32,3> = s0 r10 e000 f00111100000011001010010001 qNE v1.2345678955316544
posit<48,1> = s0 r10 e0 f00111100000011001010010000101000110001011010 qNE v1.2345678901234578
posit<48,2> = s0 r10 e00 f0011110000001100101001000010100011000101101 qNE v1.2345678901234578
posit<48,3> = s0 r10 e000 f001111000000110010100100001010001100010110 qNE v1.2345678901233441
posit<64,1> = s0 r10 e0 f001111000000110010100100001010001100010110011111101100000000 qNE v1.2345678901234567
posit<64,2> = s0 r10 e00 f00111100000011001010010000101000110001011001111110110000000 qNE v1.2345678901234567
posit<64,3> = s0 r10 e000 f0011110000001100101001000010100011000101100111111011000000 qNE v1.2345678901234567

The fields are prefixed by their first characters, for example, "posit<16,2> = s0 r10 e00 f00111100000 qNE v1.234375"

  • sign field = s0, indicating a positive number
  • regime field = r10, indicates the first positive regime, named regime 0
  • exponent field = e00, indicates two bits of exponent, both 0
  • fraction field = f00111100000, a full set of fraction bits

The field values are followed by a quadrant descriptor and a value representation in decimal:

  • qNE = North-East Quadrant, representing a number in the range "[1, maxpos]"
  • v1.234375 = the value representation of the posit projection

The positive regime for a posit shows a very specific structure, as can be seen in the image blow: regime structure

Motivation

Modern AI applications have demonstrated the inefficiencies of the IEEE floating point format. Both Google and Microsoft have jettisonned IEEE floating point for their AI cloud services to gain two orders of magnitude better performance. Similarly, AI applications for mobile and embedded applications are shifting away from IEEE floating point. But, AI applications are hardly the only applications that expose the limitations of floating point. Cloud scale, IoT, embedded, control, and HPC applications are also limited by the inefficiencies of the IEEE floating point format. A simple change to a new number system can improve scale and cost of these appliations by orders of magnitude.

When performance and/or power efficiency are differentiating attributes for the use case, the complexity of IEEE floats simply can't compete with number systems that are tailored to the needs of the application.

Advantages of posits: better, faster, cheaper, and more power efficient

The core limitations of IEEE floating point are caused by two key problems of the format:

  • inefficient representation of the reals
  • irreproducibility in the context of concurrency

The complete list of issues that are holding back IEEE floating point formats:

  1. Wasted Bit Patterns - 32-bit IEEE floating point has around eight million ways to represent NaN (Not-A-Number), while 64-bit floating point has two quadrillion, that is approximately 2.251x10^15 to be more exact. A NaN is an exception value to represent undefined or invalid results, such as the result of a division by zero.
  2. Mathematically Incorrect - The format specifies two zeroes, a negative and positive zero, which have different behaviors. - Loss of associative and distributive law due to rounding after each operation. This loss of associative and distributive arithmetic behavior creates irreproducible result of concurrent programs that use IEEE floating point. This is particularly problematic for embedded and control applications.
  3. Overflows to ± inf and underflows to 0 - Overflowing to ± inf increases the relative error by an infinite factor, while underflowing to 0 loses sign information.
  4. Unused dynamic range - The dynamic range of double precision floats is a whopping 2^2047, whereas most numerical software is architected to operate around 1.0.
  5. Complicated Circuitry - Denormalized floating point numbers have a hidden bit of 0 instead of 1. This creates a host of special handling requirements that complicate compliant hardware implementations.
  6. No Gradual Overflow and Fixed Accuracy - If accuracy is defined as the number of significand bits, IEEE floating point have fixed accuracy for all numbers except denormalized numbers because the number of signficand digits is fixed. Denormalized numbers are characterized by a decreased number of significand digits when the value approaches zero as a result of having a zero hidden bit. Denormalized numbers fill the underflow gap (i.e. the gap between zero and the least non-zero values). The counterpart for gradual underflow is gradual overflow which does not exist in IEEE floating points.

In contrast, the posit number system is designed to be efficient, symmetric, and mathematically correct in any concurrency environment.

  1. Economical - No bit patterns are redundant. There is one representation for infinity denoted as ± inf and zero. All other bit patterns are valid distinct non-zero real numbers. ± inf serves as a replacement for NaN.
  2. Mathematical Elegant - There is only one representation for zero, and the encoding is symmetric around 1.0. Associative and distributive laws are supported through deferred rounding via the quire, enabling reproducible linear algebra algorithms in any concurrency environment.
  3. Tapered Accuracy - Tapered accuracy is when values with small exponent have more digits of accuracy and values with large exponents have fewer digits of accuracy. This concept was first introduced by Morris (1971) in his paper ”Tapered Floating Point: A New Floating-Point Representation”.
  4. Parameterized precision and dynamic range - posits are defined by a size, nbits, and the number of exponent bits, es. This enables system designers the freedom to pick the right precision and dynamic range required for the application. For example, for AI applications we may pick 5 or 6 bit posits without any exponent bits to improve performance. For embedded DSP applications, such as 5G base stations, we may select a 16 bit posit with 1 exponent bit to improve performance per Watt.
  5. Simpler Circuitry - There are only two special cases, Not a Real and Zero. No denormalized numbers, overflow, or underflow.

Goals of the library

The Universal library started as a bit-level arithmetic reference implementation of the evolving unum Type III (posit and valid) standard. However, the demands for supporting number systems, such as adaptive-precision integers to solve large factorials, adaptive-precision floats to act as Oracles, or comparing linear and tapered floats provided the opportunity to create a complete platform for numerical analysis and computational mathematics. With this Universal platform we enable a new direction for optimization of algorithms to take advantage of mixed-precision to maximize performance and/or minimize energy demands. Energy efficiency is going to be the key differentiator for embedded intelligence applications.

As a reference library, Universal offers an xtensive test infrastructure to validate number system arithmetic operations, and there is a host of utilities to inspect the internal encodings and operations of the different number systems.

The design space for custom arithmetic is vast, and any contribution to expand the capability of the Universal library is encouraged.

Contributing to universal

We are happy to accept pull requests via GitHub. The only requirement is that the entire regression test suite passes.

Stargazers over time

Verification Suite

Normally, the verification suite is run as part of the make test command in the build directory. However, it is possible to run specific components of the test suite, for example, to validate algorithmic changes to more complex arithmetic functions, such as square root, exponent, logarithm, and trigonometric functions.

Here is an example:

>:~/dev/universal/build$ make posit_32bit_posit
Scanning dependencies of target posit_32bit_posit
[100%] Building CXX object tests/posit/CMakeFiles/posit_32bit_posit.dir/32bit_posit.cpp.o
[100%] Linking CXX executable posit_32bit_posit
[100%] Built target posit_32bit_posit
>:~/dev/universal/build$ tests/posit/posit_32bit_posit
Standard posit<32,2> configuration tests
 posit< 32,2> useed scale     4     minpos scale       -120     maxpos scale        120

Arithmetic tests 200000 randoms each
 posit<32,2> addition       PASS
 posit<32,2> subtraction    PASS
 posit<32,2> multiplication PASS
 posit<32,2> division       PASS

Structure of the tree

The universal library contains a set of functional groups to deal with different number systems. In the examples shown above, we have seen the ".../universal/include/universal/posit" group and its test suite, ".../universal/tests/posit".

Here is a complete list:

  • universal/number/integer - arbitrary configuration fixed-size integer
  • universal/number/fixpnt - arbitrary configuration fixed-size fixed-point number system
  • universal/number/areal - arbitrary configuration fixed-size linear floating-point
  • universal/number/posit - arbitrary configuration fixed-size posit number system
  • universal/number/valid - arbitrary configuration fixed-size valid number system
  • universal/number/quire - arbitrary configuration fixed-size super accumulator number system (add/sub/abs/sqrt)
  • universal/number/unum - flexible configuration unum Type 1 number system
  • universal/number/unum2 - flexible configuration unum Type 2 number system
  • universal/number/lns - logarithmic number system
  • universal/number/float - contains the implementation of the IEEE floating point augmentations for reproducible computation
  • universal/number/decimal - adaptive-precision decimal
  • universal/number/rational - adaptive-precision rational number system
  • universal/number/adaptiveint - adaptive-precision binary integer
  • universal/number/adaptivefloat - adaptive-precision linear floating-point
  • universal/number/adaptiveposit - adaptive-precision tapered floating-point

And each of these functionality groups have an associated test suite located in ".../universal/tests/..."

Background information

Universal numbers, unums for short, are for expressing real numbers, and ranges of real numbers. There are two modes of operation, selectable by the programmer, posit mode, and valid mode.

In posit mode, a unum behaves much like a floating-point number of fixed size, rounding to the nearest expressible value if the result of a calculation is not expressible exactly. A posit offers more accuracy and a larger dynamic range than floats with the same number of bits.

In valid mode, a unum represents a range of real numbers and can be used to rigorously bound answers much like interval arithmetic does.

Posit configurations have a very specific relationship to one another. When expanding a posit, the new value falls 'between' the old values of the smaller posit. The new value is the arithmetic mean of the two numbers if the expanding bit is a fraction bit, and it is the geometric mean of the two numbers if the expanding bit is a regime or exponent bit. This page shows a visualization of the expansion of posit<2,0> to posit<7,1>:

Public Domain and community resources

The unum format is a public domain specification, and there are a collection of web resources that manage information and discussions around the use of unums.

Posit Hub

Unum-computing Google Group

Projects that leverage posits

Matrix Template Library

The Matrix Template Library incorporates modern C++ programming techniques to provide an easy and intuitive interface to users while enabling optimal performance. The natural mathematical notation in MTL4 empowers all engineers and scientists to implement their algorithms and models in minimal time. All technical aspects are encapsulated in the library. Think of it as MATLAB for applications.

G+SMO

G+Smo (Geometry + Simulation Modules, pronounced "gismo") is a new open-source C++ library that brings together mathematical tools for geometric design and numerical simulation. It is developed mainly by researchers and PhD students. It implements the relatively new paradigm of isogeometric analysis, which suggests the use of a unified framework in the design and analysis pipeline. G+Smo is an object-oriented, cross-platform, template C++ library and follows the generic programming principle, with a focus on both efficiency and ease of use. The library is partitioned into smaller entities, called modules. Examples of available modules include the dimension-independent NURBS module, the data fitting and solid segmentation module, the PDE discretization module and the adaptive spline module, based on hierarchical splines of arbitrary dimension and polynomial degree.

FEniCS

FEniCS is a popular open-source (LGPLv3) computing platform for solving partial differential equations (PDEs). FEniCS enables users to quickly translate scientific models into efficient finite element code. With the high-level Python and C++ interfaces to FEniCS, it is easy to get started, but FEniCS offers also powerful capabilities for more experienced programmers. FEniCS runs on a multitude of platforms ranging from laptops to high-performance clusters.

ODEINT-v2

Odeint is a modern C++ library for numerically solving Ordinary Differential Equations. It is developed in a generic way using Template Metaprogramming which leads to extraordinary high flexibility at top performance. The numerical algorithms are implemented independently of the underlying arithmetics. This results in an incredible applicability of the library, especially in non-standard environments. For example, odeint supports matrix types, arbitrary precision arithmetics and even can be easily run on CUDA GPUs.

Several AI and Deep Learning libraries are being reengineered to enable the use of posits for both training and inference. They will be announced as they are released.

License

FOSSA Status

Comments
  • posit<64,3> warnings on 32bit platform

    posit<64,3> warnings on 32bit platform

    Hello Devs.

    First of all, thanks for taking on this very important piece of work.

    I'm using your 3.0 project on 32bit windows. I get some warnings that I'm uncomfortable with, given the operations involved.

    Here they are (for the type posit<64,3>):

    posit.hpp(159): warning C4244: 'argument': conversion from 'int64_t' to 'size_t', possible loss of data posit.hpp(176): warning C4244: 'argument': conversion from 'unsigned __int64' to 'size_t', possible loss of data

    so on my platform size_t is 32 bit. I can understand that there might be a need to cast to size_t sometimes, but can't help thinking that e.g. defining any member variable (e.g. es) as size_t is unfortunate. Should std::uint32_t not be sufficient for es?

    The first warning is in this code:

    _exp[size_t(es - 1ull - i)]
    

    so the problem here is the suffix ull. Writing ul should fix it. Maybe the size_t cast is not really needed.

    The second warning appears in this code:

    _frac[fbits - 1ull - (msb - i)]
    

    here changing 1ull is not enough as msb is also 64bit.

    opened by thorsten-ottosen 21
  • Quire += operator seems to fail

    Quire += operator seems to fail

    I'm working with posit<16,1> at the moment. Modeling quire usage after the code in examples/blas/blas.hpp line 62, I have the following:

    for(int row=0; row<n; ++row) {
         quireX sum = sw::unum::quire_mul(beta, ycoefs[row]); //sum is initially 0
         for(LocalOrdinalType i=Arowoffsets[row]; i<Arowoffsets[row+1]; ++i) {
              positX tempPosit; 
              sum += sw::unum::quire_mul(Acoefs[i], xcoefs[Acols[i]]);
              if (row > 263 && row < 269) {
                   tempPosit.convert(sum.to_value());
                   if (tempPosit < testCompare) {
                            std::cout <<"WRONG! Sum after += is less than -1.0: " << tempPosit <<", after taking sum (" << sumHolderPosit << ") += quire_mul("<<Acoefs[i] << ", " <<xcoefs[Acols[i]] << ")" << std::endl;
                            std::cout <<"We essentially took " << sumHolderPosit << " += " << tempQuireMultholder << " and somehow ended up with " << tempPosit << std::endl;
                            std::cout << "Incorrect sum as a quire: " << sum << std::endl;
                            std::cout << "Delta Quire: " << tempQuireMult << ", (as posit) = " << tempQuireMultholder << std::endl;
                            std::cout << "Row: " << row << ", Acoefs[i]: " << Acoefs[i] << ", Acols[i]: " << Acols[i] << ", xcoefs[" << Acols[i] << "]: " << xcoefs[Acols[i]] << std::endl;
                   }
              }
    
    

    The sum should never go below the value -1.0 - and if I run an alternate version of this code that does not use the quire feature, it doesn't. With the quire enabled, I get the following output - the WRONG! tag near the bottom is where the error occurs - I figured I'd include additional output prior to the error of the sum successfully reducing in size.

    Row is 266. Acoefs[5334] = -0.016571, xcoefs[Acols[5334]] = 0.000999451
    Sum before += quire_mul  1: 000000000000000000000000000000_000000000000000000000000000000000000000000000000000000000.00000000000001100000110001100000010000000000000000000000
    Sum before += quire_mul (as posit)9.25064e-05
    product of quire_mul = -1.66893e-05
    Row is 266. Acoefs[5335] = -0.00828552, xcoefs[Acols[5335]] = 0.000999451
    Sum before += quire_mul  1: 000000000000000000000000000000_000000000000000000000000000000000000000000000000000000000.00000000000001001111011010000011010000000000000000000000
    Sum before += quire_mul (as posit)7.53403e-05
    product of quire_mul = -8.10623e-06
    Row is 266. Acoefs[5336] = -0.0165405, xcoefs[Acols[5336]] = 0.000999451
    Sum before += quire_mul  1: 000000000000000000000000000000_000000000000000000000000000000000000000000000000000000000.00000000000001000110101110010100110000000000000000000000
    Sum before += quire_mul (as posit)6.77109e-05
    product of quire_mul = -1.66893e-05
    Row is 266. Acoefs[5337] = 7.62939e-06, xcoefs[Acols[5337]] = 0.000999451
    Sum before += quire_mul  1: 000000000000000000000000000000_000000000000000000000000000000000000000000000000000000000.00000000000000110101011000111010110000000000000000000000
    Sum before += quire_mul (as posit)5.05447e-05
    product of quire_mul = 1.49012e-08
    Row is 266. Acoefs[5338] = -0.0165405, xcoefs[Acols[5338]] = 0.000999451
    Sum before += quire_mul  1: 000000000000000000000000000000_000000000000000000000000000000000000000000000000000000000.00000000000000110101011001011011100000000000000000000000
    Sum before += quire_mul (as posit)5.05447e-05
    product of quire_mul = -1.66893e-05
    Row is 266. Acoefs[5339] = -0.00828552, xcoefs[Acols[5339]] = 0.000999451
    Sum before += quire_mul  1: 000000000000000000000000000000_000000000000000000000000000000000000000000000000000000000.00000000000000100100000100000001100000000000000000000000
    Sum before += quire_mul (as posit)3.43323e-05
    product of quire_mul = -8.10623e-06
    Row is 266. Acoefs[5340] = -0.016571, xcoefs[Acols[5340]] = 0.000999451
    Sum before += quire_mul  1: 000000000000000000000000000000_000000000000000000000000000000000000000000000000000000000.00000000000000011011011000010011000000000000000000000000
    Sum before += quire_mul (as posit)2.6226e-05
    product of quire_mul = -1.66893e-05
    -------------------------------------------------------------------------------------------------------------------
    WRONG! Sum after += is less than -1.0: -2.68435e+08, after taking sum (2.6226e-05) += quire_mul(-0.016571, 0.000999451)
    We essentially took 2.6226e-05 += -1.66893e-05 and somehow ended up with -2.68435e+08 (= -maxpos)
    Incorrect sum as a quire: -1: 111111111111111111111111111111_111111111111111111111111111111111111111111111111111111111.11111111111111110101111111001010000000000000000000000000
    Delta Quire: -1: 000000000000000000000000000000_000000000000000000000000000000000000000000000000000000000.00000000000000010001010111011101000000000000000000000000, (as posit) = -1.66893e-05
    Row: 266, Acoefs[i]: -0.016571, Acols[i]: 398, xcoefs[398]: 0.000999451
    Row is 266. Acoefs[5341] = -0.00828552, xcoefs[Acols[5341]] = 0.000999451
    -------------------------------------------------------------------------------------------------------------------
    

    If you noticed, the value -2.68435e+08 is negative maxpos for a <16,1> posit. So what I'm wondering is, why does my quire suddenly explode from very small positive values to massive negative values?

    My positX and quireX are declared as

    namespace posit_shape {
        const uint es = UNUM_ES_SIZE; //1
        const uint nbits = UNUM_NBIT_SIZE; //16
    }
    namespace quire_shape {
        const uint es = UNUM_ES_SIZE;
        const uint nbits = UNUM_NBIT_SIZE;
        const uint capacity = UNUM_QUIRE_CAPACITY; //10 - as per stillwater example
    }
    typedef sw::unum::posit<posit_shape::nbits, posit_shape::es> positX;
    typedef sw::unum::quire<quire_shape::nbits, quire_shape::es> quireX;
    

    All evidence points to a bug in quire's +=, any feedback welcome.

    bug fixed 
    opened by eirhardt 18
  • Build errors when integrated with downstream TVM

    Build errors when integrated with downstream TVM

    Hi @Ravenwater !

    I am working on the Bring Your Own DataTypes PR (https://github.com/apache/incubator-tvm/pull/5812), and unfortunately we are having trouble building because of warnings from this project.

    I can open a new PR if you are okay with it

    See: (https://ci.tvm.ai/blue/organizations/jenkins/tvm/detail/PR-5812/16/pipeline) or below:

    /workspace/3rdparty/universal/posit/value.hpp: In function 'uint8_t Posit8es2Sqrt(uint8_t)':
    
    /workspace/3rdparty/universal/posit/value.hpp:219:7: error: '_exponent' may be used uninitialized in this function [-Werror=maybe-uninitialized]
    
           _scale = _exponent - 1;
    
           ^
    
    /workspace/3rdparty/universal/posit/value.hpp:217:11: note: '_exponent' was declared here
    
           int _exponent;
    
               ^
    
    /workspace/3rdparty/universal/posit/value.hpp: In function 'uint16_t Posit16es2Sqrt(uint16_t)':
    
    /workspace/3rdparty/universal/posit/value.hpp:219:7: error: '_exponent' may be used uninitialized in this function [-Werror=maybe-uninitialized]
    
           _scale = _exponent - 1;
    
           ^
    
    /workspace/3rdparty/universal/posit/value.hpp:217:11: note: '_exponent' was declared here
    
           int _exponent;
    
               ^
    
    /workspace/3rdparty/universal/posit/value.hpp: In function 'uint32_t Posit32es2Sqrt(uint32_t)':
    
    /workspace/3rdparty/universal/posit/value.hpp:219:7: error: '_exponent' may be used uninitialized in this function [-Werror=maybe-uninitialized]
    
           _scale = _exponent - 1;
    
           ^
    
    /workspace/3rdparty/universal/posit/value.hpp:217:11: note: '_exponent' was declared here
    
           int _exponent;
    
    opened by hypercubestart 13
  • Need help with builds on a collection of compilers (Intel, CLang, Apple, ARM, etc.)

    Need help with builds on a collection of compilers (Intel, CLang, Apple, ARM, etc.)

    We don't have Apple gear to build on, so I am looking for folks that can keep a Mac build clean. We don't have Intel compiler gear, so I am looking for folks that can keep an Intel build clean. We do have ARM gear, so in this case, looking for collaborators to try to set up a cross compilation flow.

    help wanted fixed 
    opened by Ravenwater 11
  • mac compilation problem

    mac compilation problem

    trying build on mac / clang etc. complains about popcntl, ctzl and __N can you hint where those should normally come from? tried searching but failed to find so far

    opened by akorzh 8
  • added a .cpp to do runge - kutta using posits.

    added a .cpp to do runge - kutta using posits.

    I was trying to use pi/4 as the interval size / step size to show the difference in precision but I was having trouble with that. Take a look and let me know what you think :)

    opened by jtodd440 7
  • Eliminating libstdc++ from c_api

    Eliminating libstdc++ from c_api

    Kind of an annoyance for C projects is the fact that C++ code is full of references to things which in fact end up requiring their own support libraries. Exceptions, for example, require a support library, and the C api is going to be very cool for mixed C/C++ projects but a project where the maintainer wants to keep it in C is going to have a hard sell to adopt the codebase when it requires linking libstdc++, which by then they might as well just switch to C++ for their own code...

    It is possible to write C++ code which doesn't use any of this, but you just need to be acutely aware of which features you're taking advantage of...

    Here is the linker error from compiling a trivial program which calls posit_integer_assign128 when libstdc++ is not present, it shows the list of C++ symbols which the linker wants and why:

    notgay:build user$ gcc-7 -o xxx ../xxx.c -L.//c_api/posit/ -std=c99 -Wall -Wextra -pedantic -lposit_c_api
    ../xxx.c: In function 'main':
    ../xxx.c:6:16: warning: unused variable 'four' [-Wunused-variable]
         posit128_t four = posit_integer_assign128(4);
                    ^~~~
    Undefined symbols for architecture x86_64:
      "std::runtime_error::what() const", referenced from:
          vtable for shift_too_large in libposit_c_api.a(posit_c_api.cpp.o)
          vtable for posit_internal_exception in libposit_c_api.a(posit_c_api.cpp.o)
          vtable for integer_divide_by_zero in libposit_c_api.a(posit_c_api.cpp.o)
          vtable for bitblock_arithmetic_exception in libposit_c_api.a(posit_c_api.cpp.o)
      "std::__1::__basic_string_common<true>::__throw_length_error() const", referenced from:
          std::__1::basic_stringbuf<char, std::__1::char_traits<char>, std::__1::allocator<char> >::str() const in libposit_c_api.a(posit_c_api.cpp.o)
      "std::__1::locale::use_facet(std::__1::locale::id&) const", referenced from:
          std::__1::basic_ostream<char, std::__1::char_traits<char> >& std::__1::__put_character_sequence<char, std::__1::char_traits<char> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, char const*, unsigned long) in libposit_c_api.a(posit_c_api.cpp.o)
      "std::__1::ios_base::getloc() const", referenced from:
          std::__1::basic_ostream<char, std::__1::char_traits<char> >& std::__1::__put_character_sequence<char, std::__1::char_traits<char> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, char const*, unsigned long) in libposit_c_api.a(posit_c_api.cpp.o)
      "std::logic_error::logic_error(char const*)", referenced from:
          std::__1::bitset<8ul>::set(unsigned long, bool) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::regime<8ul, 0ul>::assign_regime_pattern(int) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::regime<16ul, 1ul>::assign_regime_pattern(int) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::regime<32ul, 2ul>::assign_regime_pattern(int) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::bitblock<8ul>& sw::unum::convert_to_bb<8ul, 0ul, 23ul>(bool, int, sw::unum::bitblock<23ul> const&, sw::unum::bitblock<8ul>&) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::bitblock<16ul>& sw::unum::convert_to_bb<16ul, 1ul, 23ul>(bool, int, sw::unum::bitblock<23ul> const&, sw::unum::bitblock<16ul>&) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::bitblock<32ul>& sw::unum::convert_to_bb<32ul, 2ul, 52ul>(bool, int, sw::unum::bitblock<52ul> const&, sw::unum::bitblock<32ul>&) in libposit_c_api.a(posit_c_api.cpp.o)
          ...
      "std::out_of_range::~out_of_range()", referenced from:
          std::__1::bitset<8ul>::set(unsigned long, bool) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::regime<8ul, 0ul>::assign_regime_pattern(int) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::regime<16ul, 1ul>::assign_regime_pattern(int) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::regime<32ul, 2ul>::assign_regime_pattern(int) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::bitblock<8ul>& sw::unum::convert_to_bb<8ul, 0ul, 23ul>(bool, int, sw::unum::bitblock<23ul> const&, sw::unum::bitblock<8ul>&) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::bitblock<16ul>& sw::unum::convert_to_bb<16ul, 1ul, 23ul>(bool, int, sw::unum::bitblock<23ul> const&, sw::unum::bitblock<16ul>&) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::bitblock<32ul>& sw::unum::convert_to_bb<32ul, 2ul, 52ul>(bool, int, sw::unum::bitblock<52ul> const&, sw::unum::bitblock<32ul>&) in libposit_c_api.a(posit_c_api.cpp.o)
          ...
      "std::runtime_error::runtime_error(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)", referenced from:
          posit_internal_exception::posit_internal_exception(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) in libposit_c_api.a(posit_c_api.cpp.o)
          bitblock_arithmetic_exception::bitblock_arithmetic_exception(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) in libposit_c_api.a(posit_c_api.cpp.o)
      "std::runtime_error::~runtime_error()", referenced from:
          shift_too_large::~shift_too_large() in libposit_c_api.a(posit_c_api.cpp.o)
          shift_too_large::~shift_too_large() in libposit_c_api.a(posit_c_api.cpp.o)
          posit_internal_exception::~posit_internal_exception() in libposit_c_api.a(posit_c_api.cpp.o)
          posit_internal_exception::~posit_internal_exception() in libposit_c_api.a(posit_c_api.cpp.o)
          integer_divide_by_zero::~integer_divide_by_zero() in libposit_c_api.a(posit_c_api.cpp.o)
          integer_divide_by_zero::~integer_divide_by_zero() in libposit_c_api.a(posit_c_api.cpp.o)
          bitblock_arithmetic_exception::~bitblock_arithmetic_exception() in libposit_c_api.a(posit_c_api.cpp.o)
          ...
      "std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::__init(char const*, unsigned long)", referenced from:
          sw::unum::to_string(sw::unum::posit<8ul, 0ul> const&, long) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::to_string(sw::unum::posit<16ul, 1ul> const&, long) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::to_string(sw::unum::posit<32ul, 2ul> const&, long) in libposit_c_api.a(posit_c_api.cpp.o)
          std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > sw::unum::posit_format<8ul, 0ul>(sw::unum::posit<8ul, 0ul> const&) in libposit_c_api.a(posit_c_api.cpp.o)
          std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > sw::unum::posit_format<16ul, 1ul>(sw::unum::posit<16ul, 1ul> const&) in libposit_c_api.a(posit_c_api.cpp.o)
          std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > sw::unum::posit_format<64ul, 3ul>(sw::unum::posit<64ul, 3ul> const&) in libposit_c_api.a(posit_c_api.cpp.o)
          std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > sw::unum::posit_format<128ul, 4ul>(sw::unum::posit<128ul, 4ul> const&) in libposit_c_api.a(posit_c_api.cpp.o)
          ...
      "std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::__init(unsigned long, char)", referenced from:
          std::__1::ostreambuf_iterator<char, std::__1::char_traits<char> > std::__1::__pad_and_output<char, std::__1::char_traits<char> >(std::__1::ostreambuf_iterator<char, std::__1::char_traits<char> >, char const*, char const*, char const*, std::__1::ios_base&, char) in libposit_c_api.a(posit_c_api.cpp.o)
      "std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::append(char const*, unsigned long)", referenced from:
          posit_internal_exception::posit_internal_exception(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) in libposit_c_api.a(posit_c_api.cpp.o)
          bitblock_arithmetic_exception::bitblock_arithmetic_exception(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) in libposit_c_api.a(posit_c_api.cpp.o)
      "std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::resize(unsigned long, char)", referenced from:
          std::__1::basic_stringbuf<char, std::__1::char_traits<char>, std::__1::allocator<char> >::overflow(int) in libposit_c_api.a(posit_c_api.cpp.o)
          std::__1::basic_stringbuf<char, std::__1::char_traits<char>, std::__1::allocator<char> >::str(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) in libposit_c_api.a(posit_c_api.cpp.o)
      "std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::push_back(char)", referenced from:
          std::__1::basic_stringbuf<char, std::__1::char_traits<char>, std::__1::allocator<char> >::overflow(int) in libposit_c_api.a(posit_c_api.cpp.o)
      "std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::~basic_string()", referenced from:
          sw::unum::to_string(sw::unum::posit<8ul, 0ul> const&, long) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::to_string(sw::unum::posit<16ul, 1ul> const&, long) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::to_string(sw::unum::posit<32ul, 2ul> const&, long) in libposit_c_api.a(posit_c_api.cpp.o)
          _posit_format8 in libposit_c_api.a(posit_c_api.cpp.o)
          _posit_format16 in libposit_c_api.a(posit_c_api.cpp.o)
          _posit_format32 in libposit_c_api.a(posit_c_api.cpp.o)
          _posit_format64 in libposit_c_api.a(posit_c_api.cpp.o)
          ...
      "std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::operator=(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)", referenced from:
          std::__1::basic_stringbuf<char, std::__1::char_traits<char>, std::__1::allocator<char> >::str(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) in libposit_c_api.a(posit_c_api.cpp.o)
      "std::__1::basic_istream<char, std::__1::char_traits<char> >::~basic_istream()", referenced from:
          construction vtable for std::__1::basic_istream<char, std::__1::char_traits<char> >-in-std::__1::basic_stringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> > in libposit_c_api.a(posit_c_api.cpp.o)
      "std::__1::basic_istream<char, std::__1::char_traits<char> >::~basic_istream()", referenced from:
          construction vtable for std::__1::basic_istream<char, std::__1::char_traits<char> >-in-std::__1::basic_stringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> > in libposit_c_api.a(posit_c_api.cpp.o)
      "std::__1::basic_ostream<char, std::__1::char_traits<char> >::sentry::sentry(std::__1::basic_ostream<char, std::__1::char_traits<char> >&)", referenced from:
          std::__1::basic_ostream<char, std::__1::char_traits<char> >& std::__1::__put_character_sequence<char, std::__1::char_traits<char> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, char const*, unsigned long) in libposit_c_api.a(posit_c_api.cpp.o)
      "std::__1::basic_ostream<char, std::__1::char_traits<char> >::sentry::~sentry()", referenced from:
          std::__1::basic_ostream<char, std::__1::char_traits<char> >& std::__1::__put_character_sequence<char, std::__1::char_traits<char> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, char const*, unsigned long) in libposit_c_api.a(posit_c_api.cpp.o)
      "std::__1::basic_ostream<char, std::__1::char_traits<char> >::~basic_ostream()", referenced from:
          construction vtable for std::__1::basic_ostream<char, std::__1::char_traits<char> >-in-std::__1::basic_stringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> > in libposit_c_api.a(posit_c_api.cpp.o)
      "std::__1::basic_ostream<char, std::__1::char_traits<char> >::~basic_ostream()", referenced from:
          construction vtable for std::__1::basic_ostream<char, std::__1::char_traits<char> >-in-std::__1::basic_stringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> > in libposit_c_api.a(posit_c_api.cpp.o)
      "std::__1::basic_ostream<char, std::__1::char_traits<char> >::operator<<(float)", referenced from:
          sw::unum::to_string(sw::unum::posit<8ul, 0ul> const&, long) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::to_string(sw::unum::posit<16ul, 1ul> const&, long) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::to_string(sw::unum::posit<32ul, 2ul> const&, long) in libposit_c_api.a(posit_c_api.cpp.o)
      "std::__1::basic_ostream<char, std::__1::char_traits<char> >::operator<<(unsigned long)", referenced from:
          std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > sw::unum::posit_format<8ul, 0ul>(sw::unum::posit<8ul, 0ul> const&) in libposit_c_api.a(posit_c_api.cpp.o)
          std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > sw::unum::posit_format<16ul, 1ul>(sw::unum::posit<16ul, 1ul> const&) in libposit_c_api.a(posit_c_api.cpp.o)
          std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > sw::unum::posit_format<32ul, 2ul>(sw::unum::posit<32ul, 2ul> const&) in libposit_c_api.a(posit_c_api.cpp.o)
          std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > sw::unum::posit_format<64ul, 3ul>(sw::unum::posit<64ul, 3ul> const&) in libposit_c_api.a(posit_c_api.cpp.o)
          std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > sw::unum::posit_format<128ul, 4ul>(sw::unum::posit<128ul, 4ul> const&) in libposit_c_api.a(posit_c_api.cpp.o)
      "std::__1::basic_iostream<char, std::__1::char_traits<char> >::~basic_iostream()", referenced from:
          construction vtable for std::__1::basic_iostream<char, std::__1::char_traits<char> >-in-std::__1::basic_stringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> > in libposit_c_api.a(posit_c_api.cpp.o)
      "std::__1::basic_iostream<char, std::__1::char_traits<char> >::~basic_iostream()", referenced from:
          construction vtable for std::__1::basic_iostream<char, std::__1::char_traits<char> >-in-std::__1::basic_stringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> > in libposit_c_api.a(posit_c_api.cpp.o)
      "std::__1::basic_iostream<char, std::__1::char_traits<char> >::~basic_iostream()", referenced from:
          sw::unum::to_string(sw::unum::posit<8ul, 0ul> const&, long) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::to_string(sw::unum::posit<16ul, 1ul> const&, long) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::to_string(sw::unum::posit<32ul, 2ul> const&, long) in libposit_c_api.a(posit_c_api.cpp.o)
          std::__1::basic_stringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> >::~basic_stringstream() in libposit_c_api.a(posit_c_api.cpp.o)
          std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > sw::unum::posit_format<8ul, 0ul>(sw::unum::posit<8ul, 0ul> const&) in libposit_c_api.a(posit_c_api.cpp.o)
          std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > sw::unum::posit_format<16ul, 1ul>(sw::unum::posit<16ul, 1ul> const&) in libposit_c_api.a(posit_c_api.cpp.o)
          std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > sw::unum::posit_format<32ul, 2ul>(sw::unum::posit<32ul, 2ul> const&) in libposit_c_api.a(posit_c_api.cpp.o)
          ...
      "std::__1::basic_streambuf<char, std::__1::char_traits<char> >::sync()", referenced from:
          vtable for std::__1::basic_stringbuf<char, std::__1::char_traits<char>, std::__1::allocator<char> > in libposit_c_api.a(posit_c_api.cpp.o)
      "std::__1::basic_streambuf<char, std::__1::char_traits<char> >::imbue(std::__1::locale const&)", referenced from:
          vtable for std::__1::basic_stringbuf<char, std::__1::char_traits<char>, std::__1::allocator<char> > in libposit_c_api.a(posit_c_api.cpp.o)
      "std::__1::basic_streambuf<char, std::__1::char_traits<char> >::uflow()", referenced from:
          vtable for std::__1::basic_stringbuf<char, std::__1::char_traits<char>, std::__1::allocator<char> > in libposit_c_api.a(posit_c_api.cpp.o)
      "std::__1::basic_streambuf<char, std::__1::char_traits<char> >::setbuf(char*, long)", referenced from:
          vtable for std::__1::basic_stringbuf<char, std::__1::char_traits<char>, std::__1::allocator<char> > in libposit_c_api.a(posit_c_api.cpp.o)
      "std::__1::basic_streambuf<char, std::__1::char_traits<char> >::xsgetn(char*, long)", referenced from:
          vtable for std::__1::basic_stringbuf<char, std::__1::char_traits<char>, std::__1::allocator<char> > in libposit_c_api.a(posit_c_api.cpp.o)
      "std::__1::basic_streambuf<char, std::__1::char_traits<char> >::xsputn(char const*, long)", referenced from:
          vtable for std::__1::basic_stringbuf<char, std::__1::char_traits<char>, std::__1::allocator<char> > in libposit_c_api.a(posit_c_api.cpp.o)
      "std::__1::basic_streambuf<char, std::__1::char_traits<char> >::showmanyc()", referenced from:
          vtable for std::__1::basic_stringbuf<char, std::__1::char_traits<char>, std::__1::allocator<char> > in libposit_c_api.a(posit_c_api.cpp.o)
      "std::__1::basic_streambuf<char, std::__1::char_traits<char> >::basic_streambuf()", referenced from:
          sw::unum::to_string(sw::unum::posit<8ul, 0ul> const&, long) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::to_string(sw::unum::posit<16ul, 1ul> const&, long) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::to_string(sw::unum::posit<32ul, 2ul> const&, long) in libposit_c_api.a(posit_c_api.cpp.o)
          std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > sw::unum::posit_format<8ul, 0ul>(sw::unum::posit<8ul, 0ul> const&) in libposit_c_api.a(posit_c_api.cpp.o)
          std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > sw::unum::posit_format<16ul, 1ul>(sw::unum::posit<16ul, 1ul> const&) in libposit_c_api.a(posit_c_api.cpp.o)
          std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > sw::unum::posit_format<32ul, 2ul>(sw::unum::posit<32ul, 2ul> const&) in libposit_c_api.a(posit_c_api.cpp.o)
          std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > sw::unum::posit_format<64ul, 3ul>(sw::unum::posit<64ul, 3ul> const&) in libposit_c_api.a(posit_c_api.cpp.o)
          ...
      "std::__1::basic_streambuf<char, std::__1::char_traits<char> >::~basic_streambuf()", referenced from:
          sw::unum::to_string(sw::unum::posit<8ul, 0ul> const&, long) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::to_string(sw::unum::posit<16ul, 1ul> const&, long) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::to_string(sw::unum::posit<32ul, 2ul> const&, long) in libposit_c_api.a(posit_c_api.cpp.o)
          std::__1::basic_stringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> >::~basic_stringstream() in libposit_c_api.a(posit_c_api.cpp.o)
          std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > sw::unum::posit_format<8ul, 0ul>(sw::unum::posit<8ul, 0ul> const&) in libposit_c_api.a(posit_c_api.cpp.o)
          std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > sw::unum::posit_format<16ul, 1ul>(sw::unum::posit<16ul, 1ul> const&) in libposit_c_api.a(posit_c_api.cpp.o)
          std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > sw::unum::posit_format<32ul, 2ul>(sw::unum::posit<32ul, 2ul> const&) in libposit_c_api.a(posit_c_api.cpp.o)
          ...
      "std::__1::ctype<char>::id", referenced from:
          std::__1::basic_ostream<char, std::__1::char_traits<char> >& std::__1::__put_character_sequence<char, std::__1::char_traits<char> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, char const*, unsigned long) in libposit_c_api.a(posit_c_api.cpp.o)
      "std::__1::locale::~locale()", referenced from:
          std::__1::basic_ostream<char, std::__1::char_traits<char> >& std::__1::__put_character_sequence<char, std::__1::char_traits<char> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, char const*, unsigned long) in libposit_c_api.a(posit_c_api.cpp.o)
      "std::__1::ios_base::__set_badbit_and_consider_rethrow()", referenced from:
          std::__1::basic_ostream<char, std::__1::char_traits<char> >& std::__1::__put_character_sequence<char, std::__1::char_traits<char> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, char const*, unsigned long) in libposit_c_api.a(posit_c_api.cpp.o)
      "std::__1::ios_base::init(void*)", referenced from:
          sw::unum::to_string(sw::unum::posit<8ul, 0ul> const&, long) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::to_string(sw::unum::posit<16ul, 1ul> const&, long) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::to_string(sw::unum::posit<32ul, 2ul> const&, long) in libposit_c_api.a(posit_c_api.cpp.o)
          std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > sw::unum::posit_format<8ul, 0ul>(sw::unum::posit<8ul, 0ul> const&) in libposit_c_api.a(posit_c_api.cpp.o)
          std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > sw::unum::posit_format<16ul, 1ul>(sw::unum::posit<16ul, 1ul> const&) in libposit_c_api.a(posit_c_api.cpp.o)
          std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > sw::unum::posit_format<32ul, 2ul>(sw::unum::posit<32ul, 2ul> const&) in libposit_c_api.a(posit_c_api.cpp.o)
          std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > sw::unum::posit_format<64ul, 3ul>(sw::unum::posit<64ul, 3ul> const&) in libposit_c_api.a(posit_c_api.cpp.o)
          ...
      "std::__1::ios_base::clear(unsigned int)", referenced from:
          std::__1::basic_ostream<char, std::__1::char_traits<char> >& std::__1::__put_character_sequence<char, std::__1::char_traits<char> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, char const*, unsigned long) in libposit_c_api.a(posit_c_api.cpp.o)
      "std::__1::basic_ios<char, std::__1::char_traits<char> >::~basic_ios()", referenced from:
          sw::unum::to_string(sw::unum::posit<8ul, 0ul> const&, long) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::to_string(sw::unum::posit<16ul, 1ul> const&, long) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::to_string(sw::unum::posit<32ul, 2ul> const&, long) in libposit_c_api.a(posit_c_api.cpp.o)
          std::__1::basic_stringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> >::~basic_stringstream() in libposit_c_api.a(posit_c_api.cpp.o)
          std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > sw::unum::posit_format<8ul, 0ul>(sw::unum::posit<8ul, 0ul> const&) in libposit_c_api.a(posit_c_api.cpp.o)
          std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > sw::unum::posit_format<16ul, 1ul>(sw::unum::posit<16ul, 1ul> const&) in libposit_c_api.a(posit_c_api.cpp.o)
          std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > sw::unum::posit_format<32ul, 2ul>(sw::unum::posit<32ul, 2ul> const&) in libposit_c_api.a(posit_c_api.cpp.o)
          ...
      "std::terminate()", referenced from:
          ___clang_call_terminate in libposit_c_api.a(posit_c_api.cpp.o)
      "typeinfo for std::__1::basic_istream<char, std::__1::char_traits<char> >", referenced from:
          construction vtable for std::__1::basic_istream<char, std::__1::char_traits<char> >-in-std::__1::basic_stringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> > in libposit_c_api.a(posit_c_api.cpp.o)
      "typeinfo for std::__1::basic_ostream<char, std::__1::char_traits<char> >", referenced from:
          construction vtable for std::__1::basic_ostream<char, std::__1::char_traits<char> >-in-std::__1::basic_stringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> > in libposit_c_api.a(posit_c_api.cpp.o)
      "typeinfo for std::__1::basic_iostream<char, std::__1::char_traits<char> >", referenced from:
          construction vtable for std::__1::basic_iostream<char, std::__1::char_traits<char> >-in-std::__1::basic_stringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> > in libposit_c_api.a(posit_c_api.cpp.o)
          typeinfo for std::__1::basic_stringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> > in libposit_c_api.a(posit_c_api.cpp.o)
      "typeinfo for std::__1::basic_streambuf<char, std::__1::char_traits<char> >", referenced from:
          typeinfo for std::__1::basic_stringbuf<char, std::__1::char_traits<char>, std::__1::allocator<char> > in libposit_c_api.a(posit_c_api.cpp.o)
      "typeinfo for std::out_of_range", referenced from:
          std::__1::bitset<8ul>::set(unsigned long, bool) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::regime<8ul, 0ul>::assign_regime_pattern(int) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::regime<16ul, 1ul>::assign_regime_pattern(int) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::regime<32ul, 2ul>::assign_regime_pattern(int) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::bitblock<8ul>& sw::unum::convert_to_bb<8ul, 0ul, 23ul>(bool, int, sw::unum::bitblock<23ul> const&, sw::unum::bitblock<8ul>&) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::bitblock<16ul>& sw::unum::convert_to_bb<16ul, 1ul, 23ul>(bool, int, sw::unum::bitblock<23ul> const&, sw::unum::bitblock<16ul>&) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::bitblock<32ul>& sw::unum::convert_to_bb<32ul, 2ul, 52ul>(bool, int, sw::unum::bitblock<52ul> const&, sw::unum::bitblock<32ul>&) in libposit_c_api.a(posit_c_api.cpp.o)
          ...
      "typeinfo for std::runtime_error", referenced from:
          typeinfo for posit_internal_exception in libposit_c_api.a(posit_c_api.cpp.o)
          typeinfo for bitblock_arithmetic_exception in libposit_c_api.a(posit_c_api.cpp.o)
      "vtable for __cxxabiv1::__si_class_type_info", referenced from:
          typeinfo for std::__1::basic_stringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> > in libposit_c_api.a(posit_c_api.cpp.o)
          typeinfo for std::__1::basic_stringbuf<char, std::__1::char_traits<char>, std::__1::allocator<char> > in libposit_c_api.a(posit_c_api.cpp.o)
          typeinfo for posit_internal_exception in libposit_c_api.a(posit_c_api.cpp.o)
          typeinfo for shift_too_large in libposit_c_api.a(posit_c_api.cpp.o)
          typeinfo for bitblock_arithmetic_exception in libposit_c_api.a(posit_c_api.cpp.o)
          typeinfo for integer_divide_by_zero in libposit_c_api.a(posit_c_api.cpp.o)
      NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
      "vtable for std::out_of_range", referenced from:
          std::__1::bitset<8ul>::set(unsigned long, bool) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::regime<8ul, 0ul>::assign_regime_pattern(int) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::regime<16ul, 1ul>::assign_regime_pattern(int) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::regime<32ul, 2ul>::assign_regime_pattern(int) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::bitblock<8ul>& sw::unum::convert_to_bb<8ul, 0ul, 23ul>(bool, int, sw::unum::bitblock<23ul> const&, sw::unum::bitblock<8ul>&) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::bitblock<16ul>& sw::unum::convert_to_bb<16ul, 1ul, 23ul>(bool, int, sw::unum::bitblock<23ul> const&, sw::unum::bitblock<16ul>&) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::bitblock<32ul>& sw::unum::convert_to_bb<32ul, 2ul, 52ul>(bool, int, sw::unum::bitblock<52ul> const&, sw::unum::bitblock<32ul>&) in libposit_c_api.a(posit_c_api.cpp.o)
          ...
      NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
      "non-virtual thunk to std::__1::basic_iostream<char, std::__1::char_traits<char> >::~basic_iostream()", referenced from:
          construction vtable for std::__1::basic_iostream<char, std::__1::char_traits<char> >-in-std::__1::basic_stringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> > in libposit_c_api.a(posit_c_api.cpp.o)
      "non-virtual thunk to std::__1::basic_iostream<char, std::__1::char_traits<char> >::~basic_iostream()", referenced from:
          construction vtable for std::__1::basic_iostream<char, std::__1::char_traits<char> >-in-std::__1::basic_stringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> > in libposit_c_api.a(posit_c_api.cpp.o)
      "virtual thunk to std::__1::basic_istream<char, std::__1::char_traits<char> >::~basic_istream()", referenced from:
          construction vtable for std::__1::basic_istream<char, std::__1::char_traits<char> >-in-std::__1::basic_stringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> > in libposit_c_api.a(posit_c_api.cpp.o)
      "virtual thunk to std::__1::basic_istream<char, std::__1::char_traits<char> >::~basic_istream()", referenced from:
          construction vtable for std::__1::basic_istream<char, std::__1::char_traits<char> >-in-std::__1::basic_stringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> > in libposit_c_api.a(posit_c_api.cpp.o)
      "virtual thunk to std::__1::basic_ostream<char, std::__1::char_traits<char> >::~basic_ostream()", referenced from:
          construction vtable for std::__1::basic_ostream<char, std::__1::char_traits<char> >-in-std::__1::basic_stringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> > in libposit_c_api.a(posit_c_api.cpp.o)
      "virtual thunk to std::__1::basic_ostream<char, std::__1::char_traits<char> >::~basic_ostream()", referenced from:
          construction vtable for std::__1::basic_ostream<char, std::__1::char_traits<char> >-in-std::__1::basic_stringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> > in libposit_c_api.a(posit_c_api.cpp.o)
      "virtual thunk to std::__1::basic_iostream<char, std::__1::char_traits<char> >::~basic_iostream()", referenced from:
          construction vtable for std::__1::basic_iostream<char, std::__1::char_traits<char> >-in-std::__1::basic_stringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> > in libposit_c_api.a(posit_c_api.cpp.o)
      "virtual thunk to std::__1::basic_iostream<char, std::__1::char_traits<char> >::~basic_iostream()", referenced from:
          construction vtable for std::__1::basic_iostream<char, std::__1::char_traits<char> >-in-std::__1::basic_stringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> > in libposit_c_api.a(posit_c_api.cpp.o)
      "operator delete(void*)", referenced from:
          std::__1::basic_stringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> >::~basic_stringstream() in libposit_c_api.a(posit_c_api.cpp.o)
          non-virtual thunk to std::__1::basic_stringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> >::~basic_stringstream() in libposit_c_api.a(posit_c_api.cpp.o)
          virtual thunk to std::__1::basic_stringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> >::~basic_stringstream() in libposit_c_api.a(posit_c_api.cpp.o)
          std::__1::basic_stringbuf<char, std::__1::char_traits<char>, std::__1::allocator<char> >::~basic_stringbuf() in libposit_c_api.a(posit_c_api.cpp.o)
          shift_too_large::~shift_too_large() in libposit_c_api.a(posit_c_api.cpp.o)
          posit_internal_exception::~posit_internal_exception() in libposit_c_api.a(posit_c_api.cpp.o)
          integer_divide_by_zero::~integer_divide_by_zero() in libposit_c_api.a(posit_c_api.cpp.o)
          ...
      "operator new(unsigned long)", referenced from:
          std::__1::basic_stringbuf<char, std::__1::char_traits<char>, std::__1::allocator<char> >::str() const in libposit_c_api.a(posit_c_api.cpp.o)
      "___cxa_allocate_exception", referenced from:
          std::__1::bitset<8ul>::set(unsigned long, bool) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::regime<8ul, 0ul>::assign_regime_pattern(int) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::regime<16ul, 1ul>::assign_regime_pattern(int) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::regime<32ul, 2ul>::assign_regime_pattern(int) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::bitblock<8ul>& sw::unum::convert_to_bb<8ul, 0ul, 23ul>(bool, int, sw::unum::bitblock<23ul> const&, sw::unum::bitblock<8ul>&) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::bitblock<16ul>& sw::unum::convert_to_bb<16ul, 1ul, 23ul>(bool, int, sw::unum::bitblock<23ul> const&, sw::unum::bitblock<16ul>&) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::bitblock<32ul>& sw::unum::convert_to_bb<32ul, 2ul, 52ul>(bool, int, sw::unum::bitblock<52ul> const&, sw::unum::bitblock<32ul>&) in libposit_c_api.a(posit_c_api.cpp.o)
          ...
      "___cxa_begin_catch", referenced from:
          ___clang_call_terminate in libposit_c_api.a(posit_c_api.cpp.o)
          std::__1::basic_stringbuf<char, std::__1::char_traits<char>, std::__1::allocator<char> >::overflow(int) in libposit_c_api.a(posit_c_api.cpp.o)
          std::__1::basic_ostream<char, std::__1::char_traits<char> >& std::__1::__put_character_sequence<char, std::__1::char_traits<char> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, char const*, unsigned long) in libposit_c_api.a(posit_c_api.cpp.o)
      "___cxa_end_catch", referenced from:
          std::__1::basic_stringbuf<char, std::__1::char_traits<char>, std::__1::allocator<char> >::overflow(int) in libposit_c_api.a(posit_c_api.cpp.o)
          std::__1::basic_ostream<char, std::__1::char_traits<char> >& std::__1::__put_character_sequence<char, std::__1::char_traits<char> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, char const*, unsigned long) in libposit_c_api.a(posit_c_api.cpp.o)
      "___cxa_free_exception", referenced from:
          std::__1::bitset<8ul>::set(unsigned long, bool) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::regime<8ul, 0ul>::assign_regime_pattern(int) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::regime<16ul, 1ul>::assign_regime_pattern(int) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::regime<32ul, 2ul>::assign_regime_pattern(int) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::bitblock<8ul>& sw::unum::convert_to_bb<8ul, 0ul, 23ul>(bool, int, sw::unum::bitblock<23ul> const&, sw::unum::bitblock<8ul>&) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::bitblock<16ul>& sw::unum::convert_to_bb<16ul, 1ul, 23ul>(bool, int, sw::unum::bitblock<23ul> const&, sw::unum::bitblock<16ul>&) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::bitblock<32ul>& sw::unum::convert_to_bb<32ul, 2ul, 52ul>(bool, int, sw::unum::bitblock<52ul> const&, sw::unum::bitblock<32ul>&) in libposit_c_api.a(posit_c_api.cpp.o)
          ...
      "___cxa_throw", referenced from:
          std::__1::bitset<8ul>::set(unsigned long, bool) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::regime<8ul, 0ul>::assign_regime_pattern(int) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::regime<16ul, 1ul>::assign_regime_pattern(int) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::regime<32ul, 2ul>::assign_regime_pattern(int) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::bitblock<8ul>& sw::unum::convert_to_bb<8ul, 0ul, 23ul>(bool, int, sw::unum::bitblock<23ul> const&, sw::unum::bitblock<8ul>&) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::bitblock<16ul>& sw::unum::convert_to_bb<16ul, 1ul, 23ul>(bool, int, sw::unum::bitblock<23ul> const&, sw::unum::bitblock<16ul>&) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::bitblock<32ul>& sw::unum::convert_to_bb<32ul, 2ul, 52ul>(bool, int, sw::unum::bitblock<52ul> const&, sw::unum::bitblock<32ul>&) in libposit_c_api.a(posit_c_api.cpp.o)
          ...
      "___gxx_personality_v0", referenced from:
          sw::unum::to_string(sw::unum::posit<8ul, 0ul> const&, long) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::to_string(sw::unum::posit<16ul, 1ul> const&, long) in libposit_c_api.a(posit_c_api.cpp.o)
          sw::unum::to_string(sw::unum::posit<32ul, 2ul> const&, long) in libposit_c_api.a(posit_c_api.cpp.o)
          std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > sw::unum::posit_format<8ul, 0ul>(sw::unum::posit<8ul, 0ul> const&) in libposit_c_api.a(posit_c_api.cpp.o)
          std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > sw::unum::posit_format<16ul, 1ul>(sw::unum::posit<16ul, 1ul> const&) in libposit_c_api.a(posit_c_api.cpp.o)
          std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > sw::unum::posit_format<32ul, 2ul>(sw::unum::posit<32ul, 2ul> const&) in libposit_c_api.a(posit_c_api.cpp.o)
          std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > sw::unum::posit_format<64ul, 3ul>(sw::unum::posit<64ul, 3ul> const&) in libposit_c_api.a(posit_c_api.cpp.o)
          ...
    ld: symbol(s) not found for architecture x86_64
    collect2: error: ld returned 1 exit status
    notgay:build user$
    
    help wanted 
    opened by cjdelisle 7
  • cmake's

    cmake's "install" target is broken: No such file or directory.

    ===>   Generating temporary packing list
    [0/1] cd /usr/ports/math/universal/work/.build && /usr/local/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake
    -- Install configuration: "Release"
    -- Up-to-date: /usr/ports/math/universal/work/stage/usr/local/share/Universal/universal-config.cmake
    -- Up-to-date: /usr/ports/math/universal/work/stage/usr/local/share/Universal/universal-config-version.cmake
    CMake Error at cmake_install.cmake:48 (file):
      file INSTALL cannot find
      "/usr/ports/math/universal/work/universal-1c244646b8f616881f8b5b95ee542c96e49e5580/universal":
      No such file or directory.
    
    opened by yurivict 6
  • performance improvements: we want a fastPosit sw emulation

    performance improvements: we want a fastPosit sw emulation

    Right now, the core bit implementation is based on std::bitset<>. Some of the key operators on posits need to be implemented by bit searches in the bitset<>, which is particularly painful for big posits. The current lib runs in the 1MOPS range for small posit, but in the 100KOPS range for big posits.

    Looking for help to create a fastPosit implementation that is based on integer arithmetic that will improve performance by several orders of magnitude. Should be a drop-in replacement, so that an application can swap out the two interfaces seamlessly.

    enhancement help wanted 
    opened by Ravenwater 6
  • MinMax does not operate well when value is small

    MinMax does not operate well when value is small

    Problem:

    In include/universal/number/posit/math/minmax.hpp, expression sw::universal::posit<32,2>(std::pow(double(0.00978569), double(std::numeric_limits<sw::universal::posit<32,2>>::min()))) gives 1 rather than 0.00978569.

    opened by dingjr27 5
  • Compilation with Clang leads to constexpr errors

    Compilation with Clang leads to constexpr errors

    Compiling with Clang 8 on Mac:

    /Users/gus/universal-llvm/./include/universal/posit/posit.hpp:1732:27: error: constexpr variable 'nbits' must be initialized by a constant expression
            constexpr size_t nbits = number.nbits;
                                     ^~~~~~~~~~~~
    /Users/gus/universal-llvm/numerical/thin_triangle.cpp:223:35: note: in instantiation of function template specialization
          'sw::unum::to_binary<sw::unum::posit<32, 2> >' requested here
            ostr << "    a  = " << sw::unum::to_binary(a) << " " << sw::unum::to_base2_scientific(a) << " : " << std::showpos << a << std::noshowpos << std::endl;
                                             ^
    /Users/gus/universal-llvm/numerical/thin_triangle.cpp:289:3: note: in instantiation of function template specialization
          'printTriangleConfiguration<sw::unum::posit<32, 2> >' requested here
                    printTriangleConfiguration<Posit>(cout, a, b, c);
                    ^
    

    There are many instances of this same error. Any ideas?

    fixed 
    opened by gussmith23 5
  • Matrix equality (==) operator

    Matrix equality (==) operator

    The overloaded operator == returns incorrect results. As a test case:

    sw::universal::blas::matrix<double> A = { { 5.0, 1.0, 0.0, 3.0}, { 0.0, -7.0, -1.0, -5.0}, { 0.0, -4.0, -8.0, -7.0}, { 0.0, 3.0, 3.0, 12.0 } };

    std::cout << ((inv(A)*A) == I) << std::endl;

    where I is the 4x4 identity matrix, returns false.

    Others (e.g., MATLAB) have same issue due to rounding. Perhaps a better approach is to include a tolerance, that is equal within epsilon.

    opened by jamesquinlan 0
  • Compiling to RISC-V

    Compiling to RISC-V

    Hello!

    I'm having some trouble using Universal for RISC-V. I have a small test project with the following directories:

    test_universal/
        build/
        src/
            mymain.cpp
        CMakeLists.txt
    

    The content of CMakeLists.txt is:

    cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
    project(example)
    
    set(CMAKE_CXX_COMPILER riscv64-unknown-elf-g++)
    
    set(SRC_FOLDER "${CMAKE_CURRENT_LIST_DIR}/src")
    
    include_directories("~/universal-3.52/include")
    
    add_executable(test_posit ${SRC_FOLDER}/mymain.cpp)
    set_property(TARGET test_posit PROPERTY CXX_STANDARD 17)
    

    When executing:

    mkdir build
    cd build
    cmake ..
    make
    

    I get the following errors:

    [ 50%] Building CXX object CMakeFiles/test_posit.dir/src/mymain.cpp.o
    In file included from /home/david/universal-3.52/include/universal/native/nonconstexpr754.hpp:406,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:12,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/universal-3.52/include/universal/native/nonconstexpr/gcc_long_double.hpp: In function 'void sw::universal::extract_fp_components(long double, bool&, int&, long double&, long long unsigned int&)':
    /home/david/universal-3.52/include/universal/native/nonconstexpr/gcc_long_double.hpp:195:57: error: static assertion failed: This function only works when long double significant is <= 64 bit.
      195 |  static_assert(std::numeric_limits<long double>::digits <= 64, "This function only works when long double significant is <= 64 bit.");
          |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~
    /home/david/universal-3.52/include/universal/native/nonconstexpr/gcc_long_double.hpp:203:9: error: 'frexpl' was not declared in this scope; did you mean 'frexpf'?
      203 |   _fr = frexpl(fp, &_exponent);
          |         ^~~~~~
          |         frexpf
    In file included from /home/david/universal-3.52/include/universal/native/nonconstexpr754.hpp:407,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:12,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/universal-3.52/include/universal/native/nonconstexpr/riscv_long_double.hpp: At global scope:
    /home/david/universal-3.52/include/universal/native/nonconstexpr/riscv_long_double.hpp:23:7: error: redefinition of 'union sw::universal::long_double_decoder'
       23 | union long_double_decoder {
          |       ^~~~~~~~~~~~~~~~~~~
    In file included from /home/david/universal-3.52/include/universal/native/nonconstexpr754.hpp:406,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:12,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/universal-3.52/include/universal/native/nonconstexpr/gcc_long_double.hpp:23:7: note: previous definition of 'union sw::universal::long_double_decoder'
       23 | union long_double_decoder {
          |       ^~~~~~~~~~~~~~~~~~~
    In file included from /home/david/universal-3.52/include/universal/native/nonconstexpr754.hpp:407,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:12,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/universal-3.52/include/universal/native/nonconstexpr/riscv_long_double.hpp:33:13: error: redefinition of 'void sw::universal::extractFields(long double, bool&, uint64_t&, uint64_t&)'
       33 | inline void extractFields(long double value, bool& s, uint64_t& rawExponentBits, uint64_t& rawFractionBits) {
          |             ^~~~~~~~~~~~~
    In file included from /home/david/universal-3.52/include/universal/native/nonconstexpr754.hpp:406,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:12,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/universal-3.52/include/universal/native/nonconstexpr/gcc_long_double.hpp:33:13: note: 'void sw::universal::extractFields(long double, bool&, uint64_t&, uint64_t&)' previously defined here
       33 | inline void extractFields(long double value, bool& s, uint64_t& rawExponentBits, uint64_t& rawFractionBits) {
          |             ^~~~~~~~~~~~~
    In file included from /home/david/universal-3.52/include/universal/native/nonconstexpr754.hpp:407,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:12,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/universal-3.52/include/universal/native/nonconstexpr/riscv_long_double.hpp:42:20: error: redefinition of 'std::string sw::universal::to_base2_scientific(long double)'
       42 | inline std::string to_base2_scientific(long double number) {
          |                    ^~~~~~~~~~~~~~~~~~~
    In file included from /home/david/universal-3.52/include/universal/native/nonconstexpr754.hpp:406,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:12,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/universal-3.52/include/universal/native/nonconstexpr/gcc_long_double.hpp:42:20: note: 'std::string sw::universal::to_base2_scientific(long double)' previously defined here
       42 | inline std::string to_base2_scientific(long double number) {
          |                    ^~~~~~~~~~~~~~~~~~~
    In file included from /home/david/universal-3.52/include/universal/native/nonconstexpr754.hpp:407,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:12,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/universal-3.52/include/universal/native/nonconstexpr/riscv_long_double.hpp:57:20: error: redefinition of 'std::string sw::universal::to_hex(long double)'
       57 | inline std::string to_hex(long double number) {
          |                    ^~~~~~
    In file included from /home/david/universal-3.52/include/universal/native/nonconstexpr754.hpp:406,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:12,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/universal-3.52/include/universal/native/nonconstexpr/gcc_long_double.hpp:57:20: note: 'std::string sw::universal::to_hex(long double)' previously defined here
       57 | inline std::string to_hex(long double number) {
          |                    ^~~~~~
    In file included from /home/david/universal-3.52/include/universal/native/nonconstexpr754.hpp:407,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:12,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/universal-3.52/include/universal/native/nonconstexpr/riscv_long_double.hpp:66:20: error: redefinition of 'std::string sw::universal::to_binary(long double, bool)'
       66 | inline std::string to_binary(long double number, bool bNibbleMarker = false) {
          |                    ^~~~~~~~~
    In file included from /home/david/universal-3.52/include/universal/native/nonconstexpr754.hpp:406,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:12,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/universal-3.52/include/universal/native/nonconstexpr/gcc_long_double.hpp:66:20: note: 'std::string sw::universal::to_binary(long double, bool)' previously defined here
       66 | inline std::string to_binary(long double number, bool bNibbleMarker = false) {
          |                    ^~~~~~~~~
    In file included from /home/david/universal-3.52/include/universal/native/nonconstexpr754.hpp:407,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:12,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/universal-3.52/include/universal/native/nonconstexpr/riscv_long_double.hpp:100:20: error: redefinition of 'std::string sw::universal::to_triple(long double)'
      100 | inline std::string to_triple(long double number) {
          |                    ^~~~~~~~~
    In file included from /home/david/universal-3.52/include/universal/native/nonconstexpr754.hpp:406,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:12,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/universal-3.52/include/universal/native/nonconstexpr/gcc_long_double.hpp:100:20: note: 'std::string sw::universal::to_triple(long double)' previously defined here
      100 | inline std::string to_triple(long double number) {
          |                    ^~~~~~~~~
    In file included from /home/david/universal-3.52/include/universal/native/nonconstexpr754.hpp:407,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:12,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/universal-3.52/include/universal/native/nonconstexpr/riscv_long_double.hpp:135:20: error: redefinition of 'std::string sw::universal::color_print(long double)'
      135 | inline std::string color_print(long double number) {
          |                    ^~~~~~~~~~~
    In file included from /home/david/universal-3.52/include/universal/native/nonconstexpr754.hpp:406,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:12,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/universal-3.52/include/universal/native/nonconstexpr/gcc_long_double.hpp:135:20: note: 'std::string sw::universal::color_print(long double)' previously defined here
      135 | inline std::string color_print(long double number) {
          |                    ^~~~~~~~~~~
    In file included from /home/david/universal-3.52/include/universal/native/nonconstexpr754.hpp:407,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:12,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/universal-3.52/include/universal/native/nonconstexpr/riscv_long_double.hpp: In function 'void sw::universal::extract_fp_components(long double, bool&, int&, long double&, uint64_t&)':
    /home/david/universal-3.52/include/universal/native/nonconstexpr/riscv_long_double.hpp:181:31: error: static assertion failed: This function only works when long double is 128 bits.
      181 |  static_assert(sizeof(double) == 16, "This function only works when long double is 128 bits.");
          |                ~~~~~~~~~~~~~~~^~~~~
    /home/david/universal-3.52/include/universal/native/nonconstexpr/riscv_long_double.hpp:183:8: error: 'frexpl' was not declared in this scope; did you mean 'frexpf'?
      183 |  _fr = frexpl(fp, &_exponent);
          |        ^~~~~~
          |        frexpf
    In file included from /home/david/universal-3.52/include/universal/number/posit/mathlib.hpp:20,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:89,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/universal-3.52/include/universal/number/posit/math/error_and_gamma.hpp: In function 'sw::universal::posit<nbits, es> sw::universal::erf(sw::universal::posit<nbits, es>)':
    /home/david/universal-3.52/include/universal/number/posit/math/error_and_gamma.hpp:16:30: error: 'erf' is not a member of 'std'; did you mean 'ref'?
       16 |  return posit<nbits,es>(std::erf(double(x)));
          |                              ^~~
          |                              ref
    /home/david/universal-3.52/include/universal/number/posit/math/error_and_gamma.hpp: In function 'sw::universal::posit<nbits, es> sw::universal::erfc(sw::universal::posit<nbits, es>)':
    /home/david/universal-3.52/include/universal/number/posit/math/error_and_gamma.hpp:22:30: error: 'erfc' is not a member of 'std'; did you mean 'errc'?
       22 |  return posit<nbits,es>(std::erfc(double(x)));
          |                              ^~~~
          |                              errc
    In file included from /home/david/universal-3.52/include/universal/number/posit/mathlib.hpp:21,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:89,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/universal-3.52/include/universal/number/posit/math/exponent.hpp: In function 'sw::universal::posit<nbits, es> sw::universal::exp2(sw::universal::posit<nbits, es>)':
    /home/david/universal-3.52/include/universal/number/posit/math/exponent.hpp:33:18: error: 'exp2' is not a member of 'std'; did you mean 'exp'?
       33 |  double d = std::exp2(double(x));
          |                  ^~~~
          |                  exp
    /home/david/universal-3.52/include/universal/number/posit/math/exponent.hpp: In function 'sw::universal::posit<nbits, es> sw::universal::expm1(sw::universal::posit<nbits, es>)':
    /home/david/universal-3.52/include/universal/number/posit/math/exponent.hpp:52:30: error: 'expm1' is not a member of 'std'; did you mean 'exp'?
       52 |  return posit<nbits,es>(std::expm1(double(x)));
          |                              ^~~~~
          |                              exp
    In file included from /home/david/universal-3.52/include/universal/number/posit/mathlib.hpp:22,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:89,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/universal-3.52/include/universal/number/posit/math/fractional.hpp: In function 'sw::universal::posit<nbits, es> sw::universal::remainder(sw::universal::posit<nbits, es>, sw::universal::posit<nbits, es>)':
    /home/david/universal-3.52/include/universal/number/posit/math/fractional.hpp:20:30: error: 'remainder' is not a member of 'std'
       20 |  return posit<nbits,es>(std::remainder(double(x), double(y)));
          |                              ^~~~~~~~~
    /home/david/universal-3.52/include/universal/number/posit/math/fractional.hpp:20:30: note: suggested alternatives:
    In file included from /home/david/riscv/riscv64-unknown-elf/include/c++/10.2.0/cmath:45,
                     from /home/david/universal-3.52/include/universal/native/nonconstexpr754.hpp:9,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:12,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/riscv/riscv64-unknown-elf/include/math.h:336:15: note:   'remainder'
      336 | extern double remainder (double, double);
          |               ^~~~~~~~~
    In file included from /home/david/universal-3.52/include/universal/number/posit/mathlib.hpp:22,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:89,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/universal-3.52/include/universal/number/posit/math/fractional.hpp:19:17: note:   'sw::universal::remainder'
       19 | posit<nbits,es> remainder(posit<nbits,es> x, posit<nbits,es> y) {
          |                 ^~~~~~~~~
    In file included from /home/david/universal-3.52/include/universal/number/posit/mathlib.hpp:23,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:89,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/universal-3.52/include/universal/number/posit/math/hyperbolic.hpp: In function 'sw::universal::posit<nbits, es> sw::universal::atanh(sw::universal::posit<nbits, es>)':
    /home/david/universal-3.52/include/universal/number/posit/math/hyperbolic.hpp:37:45: error: no matching function for call to 'atanh(double)'
       37 |  return posit<nbits,es>(std::atanh(double(x)));
          |                                             ^
    In file included from /home/david/universal-3.52/include/universal/number/posit/math/complex.hpp:7,
                     from /home/david/universal-3.52/include/universal/number/posit/mathlib.hpp:19,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:89,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/riscv/riscv64-unknown-elf/include/c++/10.2.0/complex:1833:5: note: candidate: 'template<class _Tp> std::complex<_Tp> std::atanh(const std::complex<_Tp>&)'
     1833 |     atanh(const std::complex<_Tp>& __z)
          |     ^~~~~
    /home/david/riscv/riscv64-unknown-elf/include/c++/10.2.0/complex:1833:5: note:   template argument deduction/substitution failed:
    In file included from /home/david/universal-3.52/include/universal/number/posit/mathlib.hpp:23,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:89,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/universal-3.52/include/universal/number/posit/math/hyperbolic.hpp:37:45: note:   mismatched types 'const std::complex<_Tp>' and 'double'
       37 |  return posit<nbits,es>(std::atanh(double(x)));
          |                                             ^
    /home/david/universal-3.52/include/universal/number/posit/math/hyperbolic.hpp: In function 'sw::universal::posit<nbits, es> sw::universal::acosh(sw::universal::posit<nbits, es>)':
    /home/david/universal-3.52/include/universal/number/posit/math/hyperbolic.hpp:43:45: error: no matching function for call to 'acosh(double)'
       43 |  return posit<nbits,es>(std::acosh(double(x)));
          |                                             ^
    In file included from /home/david/universal-3.52/include/universal/number/posit/math/complex.hpp:7,
                     from /home/david/universal-3.52/include/universal/number/posit/mathlib.hpp:19,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:89,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/riscv/riscv64-unknown-elf/include/c++/10.2.0/complex:1750:5: note: candidate: 'template<class _Tp> std::complex<_Tp> std::acosh(const std::complex<_Tp>&)'
     1750 |     acosh(const std::complex<_Tp>& __z)
          |     ^~~~~
    /home/david/riscv/riscv64-unknown-elf/include/c++/10.2.0/complex:1750:5: note:   template argument deduction/substitution failed:
    In file included from /home/david/universal-3.52/include/universal/number/posit/mathlib.hpp:23,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:89,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/universal-3.52/include/universal/number/posit/math/hyperbolic.hpp:43:45: note:   mismatched types 'const std::complex<_Tp>' and 'double'
       43 |  return posit<nbits,es>(std::acosh(double(x)));
          |                                             ^
    /home/david/universal-3.52/include/universal/number/posit/math/hyperbolic.hpp: In function 'sw::universal::posit<nbits, es> sw::universal::asinh(sw::universal::posit<nbits, es>)':
    /home/david/universal-3.52/include/universal/number/posit/math/hyperbolic.hpp:49:45: error: no matching function for call to 'asinh(double)'
       49 |  return posit<nbits,es>(std::asinh(double(x)));
          |                                             ^
    In file included from /home/david/universal-3.52/include/universal/number/posit/math/complex.hpp:7,
                     from /home/david/universal-3.52/include/universal/number/posit/mathlib.hpp:19,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:89,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/riscv/riscv64-unknown-elf/include/c++/10.2.0/complex:1789:5: note: candidate: 'template<class _Tp> std::complex<_Tp> std::asinh(const std::complex<_Tp>&)'
     1789 |     asinh(const std::complex<_Tp>& __z)
          |     ^~~~~
    /home/david/riscv/riscv64-unknown-elf/include/c++/10.2.0/complex:1789:5: note:   template argument deduction/substitution failed:
    In file included from /home/david/universal-3.52/include/universal/number/posit/mathlib.hpp:23,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:89,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/universal-3.52/include/universal/number/posit/math/hyperbolic.hpp:49:45: note:   mismatched types 'const std::complex<_Tp>' and 'double'
       49 |  return posit<nbits,es>(std::asinh(double(x)));
          |                                             ^
    In file included from /home/david/universal-3.52/include/universal/number/posit/mathlib.hpp:24,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:89,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/universal-3.52/include/universal/number/posit/math/hypot.hpp: In function 'sw::universal::posit<nbits, es> sw::universal::hypot(sw::universal::posit<nbits, es>, sw::universal::posit<nbits, es>)':
    /home/david/universal-3.52/include/universal/number/posit/math/hypot.hpp:48:55: error: no matching function for call to 'hypot(double, double)'
       48 |  return posit<nbits,es>(std::hypot(double(x),double(y)));
          |                                                       ^
    In file included from /home/david/universal-3.52/include/universal/native/nonconstexpr754.hpp:9,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:12,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/riscv/riscv64-unknown-elf/include/c++/10.2.0/cmath:1868:3: note: candidate: 'float std::hypot(float, float, float)'
     1868 |   hypot(float __x, float __y, float __z)
          |   ^~~~~
    /home/david/riscv/riscv64-unknown-elf/include/c++/10.2.0/cmath:1868:3: note:   candidate expects 3 arguments, 2 provided
    /home/david/riscv/riscv64-unknown-elf/include/c++/10.2.0/cmath:1872:3: note: candidate: 'double std::hypot(double, double, double)'
     1872 |   hypot(double __x, double __y, double __z)
          |   ^~~~~
    /home/david/riscv/riscv64-unknown-elf/include/c++/10.2.0/cmath:1872:3: note:   candidate expects 3 arguments, 2 provided
    /home/david/riscv/riscv64-unknown-elf/include/c++/10.2.0/cmath:1876:3: note: candidate: 'long double std::hypot(long double, long double, long double)'
     1876 |   hypot(long double __x, long double __y, long double __z)
          |   ^~~~~
    /home/david/riscv/riscv64-unknown-elf/include/c++/10.2.0/cmath:1876:3: note:   candidate expects 3 arguments, 2 provided
    /home/david/riscv/riscv64-unknown-elf/include/c++/10.2.0/cmath:1881:5: note: candidate: 'template<class _Tp, class _Up, class _Vp> typename __gnu_cxx::__promote_3<_Tp, _Up, _Vp>::__type std::hypot(_Tp, _Up, _Vp)'
     1881 |     hypot(_Tp __x, _Up __y, _Vp __z)
          |     ^~~~~
    /home/david/riscv/riscv64-unknown-elf/include/c++/10.2.0/cmath:1881:5: note:   template argument deduction/substitution failed:
    In file included from /home/david/universal-3.52/include/universal/number/posit/mathlib.hpp:24,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:89,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/universal-3.52/include/universal/number/posit/math/hypot.hpp:48:55: note:   candidate expects 3 arguments, 2 provided
       48 |  return posit<nbits,es>(std::hypot(double(x),double(y)));
          |                                                       ^
    /home/david/universal-3.52/include/universal/number/posit/math/hypot.hpp: In function 'sw::universal::posit<nbits, es> sw::universal::hypotf(sw::universal::posit<nbits, es>, sw::universal::posit<nbits, es>)':
    /home/david/universal-3.52/include/universal/number/posit/math/hypot.hpp:53:30: error: 'hypotf' is not a member of 'std'; did you mean 'hypot'?
       53 |  return posit<nbits,es>(std::hypotf(float(x),float(y)));
          |                              ^~~~~~
          |                              hypot
    /home/david/universal-3.52/include/universal/number/posit/math/hypot.hpp: In function 'sw::universal::posit<nbits, es> sw::universal::hypotl(sw::universal::posit<nbits, es>, sw::universal::posit<nbits, es>)':
    /home/david/universal-3.52/include/universal/number/posit/math/hypot.hpp:58:30: error: 'hypotl' is not a member of 'std'; did you mean 'hypot'?
       58 |  return posit<nbits,es>(std::hypotl((long double)(x),(long double)(y)));
          |                              ^~~~~~
          |                              hypot
    In file included from /home/david/universal-3.52/include/universal/number/posit/mathlib.hpp:25,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:89,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/universal-3.52/include/universal/number/posit/math/logarithm.hpp: In function 'sw::universal::posit<nbits, es> sw::universal::log2(sw::universal::posit<nbits, es>)':
    /home/david/universal-3.52/include/universal/number/posit/math/logarithm.hpp:22:30: error: 'log2' is not a member of 'std'; did you mean 'log'?
       22 |  return posit<nbits,es>(std::log2(double(x)));
          |                              ^~~~
          |                              log
    /home/david/universal-3.52/include/universal/number/posit/math/logarithm.hpp: In function 'sw::universal::posit<nbits, es> sw::universal::log1p(sw::universal::posit<nbits, es>)':
    /home/david/universal-3.52/include/universal/number/posit/math/logarithm.hpp:34:30: error: 'log1p' is not a member of 'std'; did you mean 'log10'?
       34 |  return posit<nbits,es>(std::log1p(double(x)));
          |                              ^~~~~
          |                              log10
    In file included from /home/david/universal-3.52/include/universal/native/ieee754.hpp:49,
                     from /home/david/universal-3.52/include/universal/number/posit/math/sqrt.hpp:7,
                     from /home/david/universal-3.52/include/universal/number/posit/mathlib.hpp:29,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:89,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/universal-3.52/include/universal/native/ieee754_riscv.hpp: At global scope:
    /home/david/universal-3.52/include/universal/native/ieee754_riscv.hpp:15:7: error: redefinition of 'class sw::universal::ieee754_parameter<float>'
       15 | class ieee754_parameter<float> {
          |       ^~~~~~~~~~~~~~~~~~~~~~~~
    In file included from /home/david/universal-3.52/include/universal/native/ieee754.hpp:47,
                     from /home/david/universal-3.52/include/universal/number/posit/math/sqrt.hpp:7,
                     from /home/david/universal-3.52/include/universal/number/posit/mathlib.hpp:29,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:89,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/universal-3.52/include/universal/native/ieee754_gcc.hpp:16:7: note: previous definition of 'class sw::universal::ieee754_parameter<float>'
       16 | class ieee754_parameter<float> {
          |       ^~~~~~~~~~~~~~~~~~~~~~~~
    In file included from /home/david/universal-3.52/include/universal/native/ieee754.hpp:49,
                     from /home/david/universal-3.52/include/universal/number/posit/math/sqrt.hpp:7,
                     from /home/david/universal-3.52/include/universal/number/posit/mathlib.hpp:29,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:89,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/universal-3.52/include/universal/native/ieee754_riscv.hpp:32:7: error: redefinition of 'class sw::universal::ieee754_parameter<double>'
       32 | class ieee754_parameter<double> {
          |       ^~~~~~~~~~~~~~~~~~~~~~~~~
    In file included from /home/david/universal-3.52/include/universal/native/ieee754.hpp:47,
                     from /home/david/universal-3.52/include/universal/number/posit/math/sqrt.hpp:7,
                     from /home/david/universal-3.52/include/universal/number/posit/mathlib.hpp:29,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:89,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/universal-3.52/include/universal/native/ieee754_gcc.hpp:38:7: note: previous definition of 'class sw::universal::ieee754_parameter<double>'
       38 | class ieee754_parameter<double> {
          |       ^~~~~~~~~~~~~~~~~~~~~~~~~
    In file included from /home/david/universal-3.52/include/universal/native/ieee754.hpp:49,
                     from /home/david/universal-3.52/include/universal/number/posit/math/sqrt.hpp:7,
                     from /home/david/universal-3.52/include/universal/number/posit/mathlib.hpp:29,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:89,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/universal-3.52/include/universal/native/ieee754_riscv.hpp:52:7: error: redefinition of 'class sw::universal::ieee754_parameter<long double>'
       52 | class ieee754_parameter<long double> {
          |       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    In file included from /home/david/universal-3.52/include/universal/native/ieee754.hpp:47,
                     from /home/david/universal-3.52/include/universal/number/posit/math/sqrt.hpp:7,
                     from /home/david/universal-3.52/include/universal/number/posit/mathlib.hpp:29,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:89,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/universal-3.52/include/universal/native/ieee754_gcc.hpp:63:7: note: previous definition of 'class sw::universal::ieee754_parameter<long double>'
       63 | class ieee754_parameter<long double> {
          |       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    In file included from /home/david/universal-3.52/include/universal/number/posit/math/sqrt.hpp:7,
                     from /home/david/universal-3.52/include/universal/number/posit/mathlib.hpp:29,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:89,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/universal-3.52/include/universal/native/ieee754.hpp: In function 'Real sw::universal::ulp(const Real&)':
    /home/david/universal-3.52/include/universal/native/ieee754.hpp:97:14: error: 'nextafter' is not a member of 'std'
       97 |  return std::nextafter(a, a + a/2.0f) - a;
          |              ^~~~~~~~~
    /home/david/universal-3.52/include/universal/native/ieee754.hpp:97:14: note: suggested alternatives:
    In file included from /home/david/riscv/riscv64-unknown-elf/include/c++/10.2.0/cmath:45,
                     from /home/david/universal-3.52/include/universal/native/nonconstexpr754.hpp:9,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:12,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/riscv/riscv64-unknown-elf/include/math.h:308:15: note:   'nextafter'
      308 | extern double nextafter (double, double);
          |               ^~~~~~~~~
    In file included from /home/david/universal-3.52/include/universal/number/posit/mathlib.hpp:27,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:89,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/universal-3.52/include/universal/number/posit/math/next.hpp:27:17: note:   'sw::universal::nextafter'
       27 | posit<nbits,es> nextafter(posit<nbits,es> x, posit<nbits, es> target) {
          |                 ^~~~~~~~~
    In file included from /home/david/universal-3.52/include/universal/number/posit/mathlib.hpp:31,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:89,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/universal-3.52/include/universal/number/posit/math/truncate.hpp: In function 'sw::universal::posit<nbits, es> sw::universal::trunc(sw::universal::posit<nbits, es>)':
    /home/david/universal-3.52/include/universal/number/posit/math/truncate.hpp:16:30: error: 'trunc' is not a member of 'std'
       16 |  return posit<nbits,es>(std::trunc(double(x)));
          |                              ^~~~~
    /home/david/universal-3.52/include/universal/number/posit/math/truncate.hpp:16:30: note: suggested alternatives:
    In file included from /home/david/riscv/riscv64-unknown-elf/include/c++/10.2.0/cmath:45,
                     from /home/david/universal-3.52/include/universal/native/nonconstexpr754.hpp:9,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:12,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/riscv/riscv64-unknown-elf/include/math.h:321:15: note:   'trunc'
      321 | extern double trunc (double);
          |               ^~~~~
    In file included from /home/david/universal-3.52/include/universal/number/posit/mathlib.hpp:31,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:89,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/universal-3.52/include/universal/number/posit/math/truncate.hpp:15:17: note:   'sw::universal::trunc'
       15 | posit<nbits,es> trunc(posit<nbits,es> x) {
          |                 ^~~~~
    /home/david/universal-3.52/include/universal/number/posit/math/truncate.hpp: In function 'sw::universal::posit<nbits, es> sw::universal::round(sw::universal::posit<nbits, es>)':
    /home/david/universal-3.52/include/universal/number/posit/math/truncate.hpp:22:30: error: 'round' is not a member of 'std'
       22 |  return posit<nbits,es>(std::round(double(x)));
          |                              ^~~~~
    /home/david/universal-3.52/include/universal/number/posit/math/truncate.hpp:22:30: note: suggested alternatives:
    In file included from /home/david/riscv/riscv64-unknown-elf/include/c++/10.2.0/cmath:45,
                     from /home/david/universal-3.52/include/universal/native/nonconstexpr754.hpp:9,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:12,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/riscv/riscv64-unknown-elf/include/math.h:318:15: note:   'round'
      318 | extern double round (double);
          |               ^~~~~
    In file included from /home/david/riscv/riscv64-unknown-elf/include/c++/10.2.0/condition_variable:38,
                     from /home/david/riscv/riscv64-unknown-elf/include/c++/10.2.0/shared_mutex:37,
                     from /home/david/riscv/riscv64-unknown-elf/include/c++/10.2.0/memory_resource:40,
                     from /home/david/riscv/riscv64-unknown-elf/include/c++/10.2.0/regex:66,
                     from /home/david/universal-3.52/include/universal/number/posit/posit_parse.hpp:8,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:58,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/riscv/riscv64-unknown-elf/include/c++/10.2.0/chrono:853:7: note:   'std::chrono::round'
      853 |       round(const time_point<_Clock, _Dur>& __tp)
          |       ^~~~~
    In file included from /home/david/universal-3.52/include/universal/number/posit/mathlib.hpp:31,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:89,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/universal-3.52/include/universal/number/posit/math/truncate.hpp:21:17: note:   'sw::universal::round'
       21 | posit<nbits,es> round(posit<nbits,es> x) {
          |                 ^~~~~
    In file included from /home/david/universal-3.52/include/universal/number/posit/posit_impl.hpp:39,
                     from /home/david/universal-3.52/include/universal/number/posit/posit.hpp:59,
                     from /home/david/test_universal/src/mymain.cpp:3:
    /home/david/universal-3.52/include/universal/internal/bitblock/bitblock.hpp:591:20: note:   'sw::universal::internal::round'
      591 | bitblock<tgt_size> round(const bitblock<src_size>& src, size_t n)
          |                    ^~~~~
    make[2]: *** [CMakeFiles/test_posit.dir/build.make:63: CMakeFiles/test_posit.dir/src/mymain.cpp.o] Error 1
    make[1]: *** [CMakeFiles/Makefile2:76: CMakeFiles/test_posit.dir/all] Error 2
    make: *** [Makefile:84: all] Error 2
    

    The cpp file includes <universal/number/posit/posit.hpp>, and the same small code is working when compiling in Ubuntu by default without the

    set(CMAKE_CXX_COMPILER riscv64-unknown-elf-g++)
    

    line in CMakeLists.txt. I have also tried using clang++ with the same result. Any insights into how to solve this? Thanks!

    opened by davidmallasen 8
  • Posit representation precision problem

    Posit representation precision problem

    For representation with posit in the command line, the decimal output does not have enough bits, which will confuse rounding results with accurate results.

    For example:

    posit 0.1
    

    The output:

    posit< 8,0>  = 00000110 : 0.09375
     posit< 8,1>  = 00010101 : 0.101562
     posit< 8,2>  = 00100101 : 0.101562
     posit< 8,3>  = 00110010 : 0.09375
     posit<16,1>  = 0001010011001101 : 0.10001
     posit<16,2>  = 0010010011001101 : 0.10001
     posit<16,3>  = 0011001001100110 : 0.099976
     posit<24,1>  = 000101001100110011001101 : 0.1
     posit<24,2>  = 001001001100110011001101 : 0.1
     posit<24,3>  = 001100100110011001100110 : 0.0999999
     posit<32,1>  = 00010100110011001100110011001101 : 0.1
     posit<32,2>  = 00100100110011001100110011001101 : 0.1
     posit<32,3>  = 00110010011001100110011001100110 : 0.0999999996
     posit<48,1>  = 000101001100110011001100110011001100110011001101 : 0.1
     posit<48,2>  = 001001001100110011001100110011001100110011001101 : 0.1
     posit<48,3>  = 001100100110011001100110011001100110011001100110 : 0.099999999999994
     posit<64,1>  = 0001010011001100110011001100110011001100110011001100110100000000 : 0.100000000000000006
     posit<64,2>  = 0010010011001100110011001100110011001100110011001100110100000000 : 0.100000000000000006
     posit<64,3>  = 0011001001100110011001100110011001100110011001100110011010000000 : 0.100000000000000006
     posit<64,4>  = 0011100100110011001100110011001100110011001100110011001101000000 : 0.100000000000000006
    

    However, no posit can exactly represent 0.1. For instance, posit<32,2> (0.1) = 0.10000000009313226... not 0.1. The command line output seems to not have enough bits to cover the dynamic range of inaccurate representation.

    opened by Yunfei-Ma-McMaster 1
  • Posit to uint64_t conversion

    Posit to uint64_t conversion

    Is it possible to convert posit to uint64_t which result the same as (uint64_t) &( posit to double) without converting to double first? In fact, I can't use xmm register at conversion.

    opened by MJChku 3
  • SVD with posits

    SVD with posits

    Hi,

    Looking through the codebase, it seems the SVD function is all commented, while the Jacobi solver isn't. Can I perform a SVD on a square posit matrix using universal, yet? How would i go from (for example) a 3x3 single precision to a 3x3 (32,2 for example) posit one? Any numbers on the performance of SVD/Jacobi on posits on CPU/GPU? Would the use of posits help to converge faster and/or more precisely?

    Thanks in advance.

    opened by touisteur 1
  • Posit log & log1p native implementations

    Posit log & log1p native implementations

    Hi,

    I was looking for a posit implementation of the log and log1p functions, actually trying to benchmark how a posit32 (2,30?) would fare (precision and perf-wise) on a gpu or cpu (compared to a float binary32) - also trying to use (otherwise unused) int32 resources in a CUDA kernel.

    Reading the code on elementary functions, they seem implemented as 'call std::log and convert to posit'? Did I miss anything?

    If not present, is there a canonical posit log/log1p implementation I could start from?

    Thanks in advance, Lionel

    opened by touisteur 16
Releases(v3.58b)
  • v3.58b(Jul 30, 2022)

  • v3.49(Dec 29, 2021)

  • v3.48(Nov 19, 2021)

    Bringing in all the number systems into the new exception hierarchy.

    Code hygiene for gcc and clang.

    Streamlining cfloat regression suites.

    Source code(tar.gz)
    Source code(zip)
  • v3.43.1(Oct 15, 2021)

    fixpnt number system is now using bit_cast when C++20 is enabled.

    Restructured the build with new classifications.

    Moved areal forward.

    Added number traits to command line tools that deal with IEEE-754.

    Enabled long double support on ieee754_parameter class.

    Source code(tar.gz)
    Source code(zip)
Owner
Stillwater Supercomputing, Inc.
We design and develop high-performance advanced analytics for big data, IIoT, and robotics applications.
Stillwater Supercomputing, Inc.
Long integer arithmetic.

LongInt Содержимое репозитория представляет из себя исходный код примитивного консольного калькулятора, который использует реализацию длинных чисел из

null 13 Nov 2, 2022
C++ Matrix -- High performance and accurate (e.g. edge cases) matrix math library with expression template arithmetic operators

Matrix This is a math and arithmetic matrix library. It has stood many years of performing in mission critical production for financial systems. It ha

Hossein Moein 71 Oct 29, 2022
LibTomMath is a free open source portable number theoretic multiple-precision integer library written entirely in C.

libtommath This is the git repository for LibTomMath, a free open source portable number theoretic multiple-precision integer (MPI) library written en

libtom 543 Dec 27, 2022
Optimized implementations of the Number Theoretic Transform (NTT) algorithm for the ring R/(X^N + 1) where N=2^m.

optimized-number-theoretic-transform-implementations This sample code package is an implementation of the Number Theoretic Transform (NTT) algorithm f

International Business Machines 12 Nov 14, 2022
Using Visual Studio C++ to read IP addresses and comport number (Serial number) on Windows platform

Using Visual Studio C++ to read IP addresses on Windows platform

zhuhuijin 0 Feb 2, 2022
Kaprekar constant, number 6174, number 495.

Kaprekar Constant Demos Kaprekar constant, number 6174, number 495. This repository contains 1 Visual Studio solution, which managing 2 Visual Studio

MatrixLife 1 Dec 25, 2021
MIRACL Cryptographic SDK: Multiprecision Integer and Rational Arithmetic Cryptographic Library is a C software library that is widely regarded by developers as the gold standard open source SDK for elliptic curve cryptography (ECC).

MIRACL What is MIRACL? Multiprecision Integer and Rational Arithmetic Cryptographic Library – the MIRACL Crypto SDK – is a C software library that is

MIRACL 527 Jan 7, 2023
MIRACL Cryptographic SDK: Multiprecision Integer and Rational Arithmetic Cryptographic Library is a C software library that is widely regarded by developers as the gold standard open source SDK for elliptic curve cryptography (ECC).

MIRACL What is MIRACL? Multiprecision Integer and Rational Arithmetic Cryptographic Library – the MIRACL Crypto SDK – is a C software library that is

MIRACL 524 Jan 2, 2023
C library for arbitrary-precision ball arithmetic

Arb Arb is a C library for arbitrary-precision interval arithmetic. It has full support for both real and complex numbers. The library is thread-safe,

Fredrik Johansson 399 Dec 31, 2022
Fixed point 48.16 bit arithmetic type

fixed_math written from scratch fixed point math library in C++17 features minimum c++17 compiler required fixed point 48.16 arithmethic strong type w

Artur Bac 52 Dec 30, 2022
Intel:registered: Homomorphic Encryption Acceleration Library accelerates modular arithmetic operations used in homomorphic encryption

Intel Homomorphic Encryption Acceleration Library (HEXL) Intel ®️ HEXL is an open-source library which provides efficient implementations of integer a

Intel Corporation 166 Dec 30, 2022
A single-header C/C++ library for parsing and evaluation of arithmetic expressions

ceval A C/C++ header for parsing and evaluation of arithmetic expressions. [README file is almost identical to that of the ceval library] Functions ac

e_t 9 Oct 10, 2022
A single-header C/C++ library for parsing and evaluation of arithmetic expressions

ceval A C/C++ header for parsing and evaluation of arithmetic expressions. [README file is almost identical to that of the ceval library] Functions ac

e_t 9 Oct 10, 2022
Long integer arithmetic.

LongInt Содержимое репозитория представляет из себя исходный код примитивного консольного калькулятора, который использует реализацию длинных чисел из

null 13 Nov 2, 2022
C++ Matrix -- High performance and accurate (e.g. edge cases) matrix math library with expression template arithmetic operators

Matrix This is a math and arithmetic matrix library. It has stood many years of performing in mission critical production for financial systems. It ha

Hossein Moein 71 Oct 29, 2022
A C/C++ library for parsing and evaluation of arithmetic expressions.

ceval A C/C++ header for parsing and evaluation of arithmetic expressions. Functions accessibe from main() Function Argument(s) Return Value ceval_res

e_t 6 Nov 8, 2022
Tests to check the determinism of the basic floating point arithmetic operations on different devices, using Unity and Rust.

This repo contains tests to check the determinism (consistency) of the basic floating point arithmetic operations (add, subtract, multiply, divide) on

Erik Roystan 9 Dec 20, 2022
TurboRC - Turbo Range Coder / Arithmetic Coding

TurboRC: Turbo Range Coder Fastest Range Coder / Arithmetic Coder 100% C (C++ headers). OS/Arch: Linux amd/inte

powturbo 34 Dec 2, 2022
A Console Based Arithmetic Program/Game

Welcome to Operator Fill This is a console based MATH program/game made in C++ which in current stage has 700+ lines of code.(I have plans to make it

Asutosh Mishra 2 Jan 12, 2022