Public Library Components

Exceptions

ALl exceptions thrown by this library that aren’t part of the STL’s suite of exceptions will be of the type svs::ANNException described below.

ANNEXCEPTION(format, ...)

Construct an exception with line information.

class ANNException : public std::runtime_error
#include <svs/lib/exception.h>

Generic exception thrown by routines within htelibrary.

Public Functions

inline explicit ANNException(const std::string &message)

Construct a new excpetion with the given error message.

Data Types

enum class DataType

Enum aliases for dense vector element types.

Values:

enumerator uint8
enumerator uint16
enumerator uint32
enumerator uint64
enumerator int8
enumerator int16
enumerator int32
enumerator int64
enumerator float16
enumerator float32
enumerator float64
enumerator byte
enumerator undef
template<DataType Type>
using cpp_type_t = typename detail::CppType<Type>::type

Convert an DataType to its corresponding C++ type.

template<typename T>
constexpr DataType datatype_v = detail::datatype_v<std::decay_t<T>>

Convert a C++ type into its corresponding DataType.

template<typename T>
constexpr bool has_datatype_v = (datatype_v<T> != DataType::undef)

Return whether the type T has a corresponding svs::DataType.

template<DataType Type>
constexpr std::string_view name()

Return a descriptive name for the corresponding datatype.

inline constexpr std::string_view name(DataType type)

Return a descriptive string for the corresponding datatype.

inline std::string format(const std::vector<DataType> &types)

Create a formatted string of all data types present.

Parameters:

types – Collection of data types to create a string for.

Static and Dynamic Dimensionality

Vector abstractions in the library often come with the ability to statically type dimensionality (i.e., the number of elements in a vector). When static dimensionality is used, the compiler/library can often generate better code resulting in substantial speedups. Unfortunately, there is no free lunch as specializing functions for specific dimensionalities results in extra compilation time and code generation. Therefore, we include the option for both static (compile time) and dynamic (run time) dimensionality for internal vectors.

const size_t Dynamic = std::dynamic_extent

Special value representing run-time dimensionality.

Throughout the code base, static size information for various vector types can be passed to potentially improve the quality of generated code.

While this can be beneficial at runtime, it does come at the cost of increased compilation time and the need to dispatch to specialized implementations if they exist.

When run-time dimensionality is desired instead, the use of the sentinel value Dynamic can be used.

template<size_t N>
class Val
#include <svs/lib/meta.h>

Compile-time dimensionality.

If dynamic (i.e. runtime) dimensionality is required, set N = svs::Dynamic.

Template Parameters:

N – - The static number of dimensions.

Public Functions

constexpr Val() = default

Construct a new Val instance.

Public Static Attributes

static constexpr size_t value = N

Return the value parameter N.

Types

The library has support for passing either types or lists of types explicitly to some functions. Often, this works better than relying on positional type parameters of those respective functions as these classes can be passed for any argument and are generally more flexible.

template<typename T, typename ...Ts>
constexpr bool in(Types<Ts...> typelist = {})

Return whether the requested type is in the type list.

template<typename ...Ts>
constexpr bool in(DataType datatype, Types<Ts...> typelist = {})

Return whether the requested runtime type is in the compiletime type list.

Requires that elements in the type list have a know corresponding data type.

Parameters:
  • datatype – The runtime data type.

  • typelist – The list of accepted types.

template<typename F, typename ...Ts>
constexpr void for_each_type(Types<Ts...> types, F &&f)

Generator helper for each type.

Parameters:
  • types – - The list of types to pass to the functor f.

  • f – - Functor accepting a single argument Type<T> called once for each T in types.

template<typename T>
struct Type
#include <svs/lib/meta.h>

Empty struct for reasoning about types.

Template Parameters:

T – - The C++ type this struct refers to.

Public Types

using type = T

The type this struct is representing.

Public Functions

inline constexpr operator DataType()

Implicit conversion for special types.

template<typename ...Ts>
struct Types
#include <svs/lib/meta.h>

A list of types.

Public Static Functions

static inline constexpr std::array<svs::DataType, sizeof...(Ts)> data_types()

Return an array of the type enums.

Public Static Attributes

static constexpr size_t size = sizeof...(Ts)

The number of types in the list.

Example

An example of using types is given below.

In this example, we’ll show usage of svs::lib::Types and svs::lib::for_each_type.

First, we include the appropriate headers:

#include "svs/lib/datatype.h"
#include "svs/lib/float16.h"
#include "svs/lib/meta.h"

#include <cstdint>
#include <iostream>

The “svs” headers include the following:

  • datatype.h: Type enums and naming for common C++ data types.

  • meta.h: Defines the Types class

  • float16.h: Support for 16-bit floating point.

With those included, we can define our main function.

int main() {
    auto types = svs::lib::Types<int64_t, float, svs::Float16>();
    // Print out the name of each type.
    svs::lib::for_each_type(types, []<typename T>(svs::lib::Type<T> /*svs_type*/) {
        // Print out the name of the data type.
        std::cout << svs::name<svs::datatype_v<T>>() << '\n';
    });
}

We first construct the variable types as a type list with three parameters. Then, we invoke svs::lib::for_each_type on the resulting object. To this function, we also pass a lambda accepting a single argument of type 8 svs::lib::Type. This lambda is called for each type in types’ parameter pack. The resulting output will be:

int64
float32
float16

The full code example is given below.

#include "svs/lib/datatype.h"
#include "svs/lib/float16.h"
#include "svs/lib/meta.h"

#include <cstdint>
#include <iostream>

int main() {
    auto types = svs::lib::Types<int64_t, float, svs::Float16>();
    // Print out the name of each type.
    svs::lib::for_each_type(types, []<typename T>(svs::lib::Type<T> /*svs_type*/) {
        // Print out the name of the data type.
        std::cout << svs::name<svs::datatype_v<T>>() << '\n';
    });
}

Memory Management

Reading and Writing to Streams

template<typename T, typename Stream>
size_t svs::lib::write_binary(Stream &stream, const T &val)

Write the canonical binary representation of val to the output stream.

Writing will occur sequentially on each byte beginning from the least significant byte.

Accepted types:

  • Any std::is_trivially_copyable type.

  • A std::vector or std::span of such types.

Parameters:
  • stream – A std::basic_ostream compatible object.j:wa

  • val – The value to write.

Returns:

The number of bytes written to the stream.

template<typename T, typename Stream>
void read_binary(Stream &stream, T &x)

Read the canonical binary representation of T and store the results in x.

Accepted types T:

  • Any type satisfying std::is_trivially_copyable. Parameter x will the be populated as if by std::memcpy.

  • A std::vector of such types. Each element of the vector will be populated as if by recursively calling svs::lib::read_binary on each element beginning from the beginning.

Parameters:
  • stream – A std::istream compatible object.

  • x – The destination to store the result.

template<typename T, typename Stream>
T read_binary(Stream &stream)

Read the canonical binary representation of T.

Read the canonical binary representation of T as if by std::memcpy. Requires that T satisfies std::is_trivially_copyable.

Template Parameters:

T – The type to read from the stream.

Parameters:

stream – A std::istream compatible object.