Skip to content

Instantly share code, notes, and snippets.

@WardBrian
Last active February 14, 2024 15:09
Show Gist options
  • Save WardBrian/85ca3a4bfb3a23f55ef40604987c04eb to your computer and use it in GitHub Desktop.
Save WardBrian/85ca3a4bfb3a23f55ef40604987c04eb to your computer and use it in GitHub Desktop.
/**
* Demonstration of `scalar_type_t`, `base_type_t`, and `value_type_t`, for
* examples where they do the same thing and examples where they differ.
*
* Place in math repo directory and compile with:
make -f make/standalone test_types
*/
#include <stan/math/prim.hpp>
#include <stan/math/prim/fun/typedefs.hpp>
#include <stan/math/rev/meta.hpp>
#include <stan/math/mix.hpp>
#include <complex>
#include <vector>
#include <iostream>
/* Code to print a type de-mangled, from
* https://stackoverflow.com/questions/81870/is-it-possible-to-print-a-variables-type-in-standard-c
*/
#include <type_traits>
#include <cxxabi.h>
#include <memory>
#include <string>
#include <cstdlib>
template <class T>
std::string type_name() {
typedef typename std::remove_reference<T>::type TR;
std::unique_ptr<char, void (*)(void*)> own(
abi::__cxa_demangle(typeid(TR).name(), nullptr, nullptr, nullptr),
std::free);
std::string r = own != nullptr ? own.get() : typeid(TR).name();
return r;
}
template <typename T>
void print_for_type(int number) {
std::cout << "Test type " << number << ":\t" << type_name<T>() << '\n';
std::cout << "Base type:\t" << type_name<stan::base_type_t<T>>() << '\n';
std::cout << "Scalar type:\t" << type_name<stan::scalar_type_t<T>>() << '\n';
std::cout << "Value type:\t" << type_name<stan::value_type_t<T>>() << '\n';
std::cout << "Partial type:\t" << type_name<stan::partials_return_t<T>>() << '\n';
std::cout << "Return type:\t" << type_name<stan::return_type_t<T>>() << '\n';
std::cout << "------------------------------" << '\n';
}
int main() {
using v_t = stan::math::var;
using fv_t = stan::math::fvar<v_t>;
using ffv_t = stan::math::fvar<fv_t>;
using cffv_t = std::complex<ffv_t>;
print_for_type<cffv_t>(-1);
using test_type0 = Eigen::Matrix<v_t, -1, -1>;
print_for_type<test_type0>(0);
using test_type1 = std::vector<cffv_t>;
print_for_type<test_type1>(1);
using test_type2 = std::vector<test_type1>;
print_for_type<test_type2>(2);
using test_type3 = Eigen::Matrix<std::complex<v_t>, -1, -1>;
print_for_type<test_type3>(3);
using test_type4 = std::vector<test_type3>;
print_for_type<test_type4>(4);
using test_type5 = stan::math::var_value<Eigen::MatrixXd>;
print_for_type<test_type5>(5);
using test_type6 = v_t;
print_for_type<test_type6>(6);
using test_type7 = Eigen::Matrix<fv_t, -1, -1>;
print_for_type<test_type7>(7);
print_for_type<int>(8);
std::cout << "Summary: Base type and Scalar type only differ when dealing "
"with complex numbers, which base type strips but scalar "
"type does not. Value Type only removes one layer of the onion, "
"which leads to different behavior for var<matrix> types"
<< '\n';
return 0;
}
Test type -1: std::complex<stan::math::fvar<stan::math::fvar<stan::math::var_value<double, void> > > >
Base type: stan::math::fvar<stan::math::fvar<stan::math::var_value<double, void> > >
Scalar type: std::complex<stan::math::fvar<stan::math::fvar<stan::math::var_value<double, void> > > >
Value type: std::complex<stan::math::fvar<stan::math::fvar<stan::math::var_value<double, void> > > >
Partial type: std::complex<stan::math::fvar<stan::math::fvar<stan::math::var_value<double, void> > > >
Return type: std::complex<stan::math::fvar<stan::math::fvar<stan::math::var_value<double, void> > > >
------------------------------
Test type 0: Eigen::Matrix<stan::math::var_value<double, void>, -1, -1, 0, -1, -1>
Base type: stan::math::var_value<double, void>
Scalar type: stan::math::var_value<double, void>
Value type: stan::math::var_value<double, void>
Partial type: double
Return type: stan::math::var_value<double, void>
------------------------------
Test type 1: std::vector<std::complex<stan::math::fvar<stan::math::fvar<stan::math::var_value<double, void> > > >, std::allocator<std::complex<stan::math::fvar<stan::math::fvar<stan::math::var_value<double, void> > > > > >
Base type: stan::math::fvar<stan::math::fvar<stan::math::var_value<double, void> > >
Scalar type: std::complex<stan::math::fvar<stan::math::fvar<stan::math::var_value<double, void> > > >
Value type: std::complex<stan::math::fvar<stan::math::fvar<stan::math::var_value<double, void> > > >
Partial type: std::complex<stan::math::fvar<stan::math::fvar<stan::math::var_value<double, void> > > >
Return type: std::complex<stan::math::fvar<stan::math::fvar<stan::math::var_value<double, void> > > >
------------------------------
Test type 2: std::vector<std::vector<std::complex<stan::math::fvar<stan::math::fvar<stan::math::var_value<double, void> > > >, std::allocator<std::complex<stan::math::fvar<stan::math::fvar<stan::math::var_value<double, void> > > > > >, std::allocator<std::vector<std::complex<stan::math::fvar<stan::math::fvar<stan::math::var_value<double, void> > > >, std::allocator<std::complex<stan::math::fvar<stan::math::fvar<stan::math::var_value<double, void> > > > > > > >
Base type: stan::math::fvar<stan::math::fvar<stan::math::var_value<double, void> > >
Scalar type: std::complex<stan::math::fvar<stan::math::fvar<stan::math::var_value<double, void> > > >
Value type: std::vector<std::complex<stan::math::fvar<stan::math::fvar<stan::math::var_value<double, void> > > >, std::allocator<std::complex<stan::math::fvar<stan::math::fvar<stan::math::var_value<double, void> > > > > >
Partial type: std::complex<stan::math::fvar<stan::math::fvar<stan::math::var_value<double, void> > > >
Return type: std::complex<stan::math::fvar<stan::math::fvar<stan::math::var_value<double, void> > > >
------------------------------
Test type 3: Eigen::Matrix<std::complex<stan::math::var_value<double, void> >, -1, -1, 0, -1, -1>
Base type: stan::math::var_value<double, void>
Scalar type: std::complex<stan::math::var_value<double, void> >
Value type: std::complex<stan::math::var_value<double, void> >
Partial type: std::complex<stan::math::var_value<double, void> >
Return type: std::complex<stan::math::var_value<double, void> >
------------------------------
Test type 4: std::vector<Eigen::Matrix<std::complex<stan::math::var_value<double, void> >, -1, -1, 0, -1, -1>, std::allocator<Eigen::Matrix<std::complex<stan::math::var_value<double, void> >, -1, -1, 0, -1, -1> > >
Base type: stan::math::var_value<double, void>
Scalar type: std::complex<stan::math::var_value<double, void> >
Value type: Eigen::Matrix<std::complex<stan::math::var_value<double, void> >, -1, -1, 0, -1, -1>
Partial type: std::complex<stan::math::var_value<double, void> >
Return type: std::complex<stan::math::var_value<double, void> >
------------------------------
Test type 5: stan::math::var_value<Eigen::Matrix<double, -1, -1, 0, -1, -1>, void>
Base type: stan::math::var_value<Eigen::Matrix<double, -1, -1, 0, -1, -1>, void>
Scalar type: stan::math::var_value<double, void>
Value type: Eigen::Matrix<double, -1, -1, 0, -1, -1>
Partial type: double
Return type: stan::math::var_value<double, void>
------------------------------
Test type 6: stan::math::var_value<double, void>
Base type: stan::math::var_value<double, void>
Scalar type: stan::math::var_value<double, void>
Value type: double
Partial type: double
Return type: stan::math::var_value<double, void>
------------------------------
Test type 7: Eigen::Matrix<stan::math::fvar<stan::math::var_value<double, void> >, -1, -1, 0, -1, -1>
Base type: stan::math::fvar<stan::math::var_value<double, void> >
Scalar type: stan::math::fvar<stan::math::var_value<double, void> >
Value type: stan::math::fvar<stan::math::var_value<double, void> >
Partial type: stan::math::var_value<double, void>
Return type: stan::math::fvar<stan::math::var_value<double, void> >
------------------------------
Test type 8: int
Base type: int
Scalar type: int
Value type: int
Partial type: double
Return type: double
------------------------------
Summary: Base type and Scalar type only differ when dealing with complex numbers, which base type strips but scalar type does not. Value Type only removes one layer of the onion, which leads to different behavior for var<matrix> types
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment