Skip to content

Commit

Permalink
Added the mf::function::real, imag, and cmplx function objects for
Browse files Browse the repository at this point in the history
...use in expressions.
  • Loading branch information
tedmiddleton committed Apr 26, 2023
1 parent b508024 commit 72a5d86
Show file tree
Hide file tree
Showing 3 changed files with 217 additions and 0 deletions.
95 changes: 95 additions & 0 deletions mainframe/detail/expression.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#ifndef INCLUDED_mainframe_detail_expression_hpp
#define INCLUDED_mainframe_detail_expression_hpp

#include <complex>
#include <string>

#include "mainframe/frame_iterator.hpp"
Expand Down Expand Up @@ -623,6 +624,100 @@ typename make_func_expr<Func, Args...>::type fn( Func& func, Args... args )
return make_func_expr<Func, Args...>::create( func, args... );
}

namespace function
{

///
/// real function object
///
/// real let's you pull the real value out of a std::complex value in an expression as if you
/// called std::real() on it. For example:
///
/// frame<double> f1;
/// f1.set_column_names("complex");
/// f1.push_back(1.1 + 3.1i);
/// f1.push_back(2.1 + 3.2i);
/// f1.push_back(3.1 + 3.3i);
/// frame<double, complex<double>> f2 =
/// f1.append_column<complex<double>>("imaginary", real<double>(_0));
///
/// // f2 is now
/// // | complex | real
/// // __|____________|______
/// // 0| (1.1, 3.1) | 1.1
/// // 1| (2.1, 3.2) | 2.1
/// // 2| (3.1, 3.3) | 3.1
///
template<typename T, typename Arg>
typename make_func_expr<T(const std::complex<T>&), Arg>::type real( Arg c )
{
return make_func_expr<T(const std::complex<T>&), Arg>::create( std::real, c );
}

///
/// imag function object
///
/// imag let's you pull the imaginary value out of a std::complex value in an expression as if you
/// called std::imag() on it. For example:
///
/// frame<double> f1;
/// f1.set_column_names("complex");
/// f1.push_back(1.1 + 3.1i);
/// f1.push_back(2.1 + 3.2i);
/// f1.push_back(3.1 + 3.3i);
/// frame<double, complex<double>> f2 =
/// f1.append_column<complex<double>>("imaginary", imag<double>(_0));
///
/// // f2 is now
/// // | complex | imaginary
/// // __|____________|___________
/// // 0| (1.1, 3.1) | 3.1
/// // 1| (2.1, 3.2) | 3.2
/// // 2| (3.1, 3.3) | 3.3
///
template<typename T, typename Arg>
typename make_func_expr<T(const std::complex<T>&), Arg>::type imag( Arg c )
{
return make_func_expr<T(const std::complex<T>&), Arg>::create( std::imag, c );
}

template<typename T>
std::complex<T>
mkcomplex( const T& r, const T& i )
{
return std::complex<T>(r,i);
}

///
/// cmplx function object
///
/// cmplx let's you build a std::complex value from a couple of expression
/// objects in an expression. For example:
///
/// frame<float, float> f1;
/// f1.set_column_names("real", "imaginary");
/// f1.push_back(1.1f, 3.1f);
/// f1.push_back(2.1f, 3.2f);
/// f1.push_back(3.1f, 3.3f);
/// frame<float, float, complex<float>> f2 =
/// f1.append_column<complex<float>>("complex", cmplx<float>(_0, _1));
///
/// // f2 is now
/// // | real | imaginary | complex
/// // __|______|___________|____________
/// // 0| 1.1 | 3.1 | (1.1, 3.1)
/// // 1| 2.1 | 3.2 | (2.1, 3.2)
/// // 2| 3.1 | 3.3 | (3.1, 3.3)
///
template<typename T, typename Arg1, typename Arg2>
typename make_func_expr<std::complex<T>(const T&, const T&), Arg1, Arg2>::type cmplx( Arg1 r, Arg2 i )
{
return make_func_expr<std::complex<T>(const T&, const T&), Arg1, Arg2>::create( mkcomplex, r, i );
}

} // namespace function


template<typename L, typename R>
typename std::enable_if<std::disjunction<is_expression<L>, is_expression<R>>::value,
typename make_binary_expr<expr_op::LT, L, R>::type>::type
Expand Down
1 change: 1 addition & 0 deletions mainframe/expression.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#ifndef INCLUDED_mainframe_expression_hpp
#define INCLUDED_mainframe_expression_hpp

#include <complex>
#include <string>

#include "mainframe/frame_iterator.hpp"
Expand Down
121 changes: 121 additions & 0 deletions tests/mainframe_test_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ using namespace date::literals;
using namespace date;
using namespace mf;
using namespace mf::placeholders;
using mf::function::real;
using mf::function::imag;
using mf::function::cmplx;


namespace std
Expand Down Expand Up @@ -3277,6 +3280,124 @@ TEST_CASE("minmax", "[frame]")

}

TEST_CASE("complex", "[frame]")
{
SECTION("cmplx")
{
frame<double, year_month_day, double> f1;
f1.set_column_names("real", "date", "imag");
f1.push_back( 8.9, 2022_y / January / 1, 10.2);
f1.push_back(10.2, 2022_y / January / 2, 10.2);
f1.push_back(11.1, 2022_y / January / 3, 7.7);
f1.push_back(12.2, 2022_y / January / 4, 10.2);
f1.push_back(13.3, 2022_y / January / 5, 10.2);
f1.push_back(14.4, 2022_y / January / 6, 7.7);
f1.push_back(15.5, 2022_y / January / 7, 10.2);
f1.push_back( 9.1, 2022_y / January / 8, 7.7);
f1.push_back( 9.3, 2022_y / January / 9, 10.2);

auto f2 = f1.prepend_column<complex<double>>("cmplx", cmplx<double>(_0, _2));
auto it = f2.cbegin();
REQUIRE((it + 0)->at(_0) == 8.9 + 10.2i);
REQUIRE((it + 1)->at(_0) == 10.0 + 10.2i);
REQUIRE((it + 2)->at(_0) == 11.1 + 7.7i);
REQUIRE((it + 3)->at(_0) == 12.2 + 10.2i);
REQUIRE((it + 4)->at(_0) == 13.3 + 10.2i);
REQUIRE((it + 5)->at(_0) == 14.4 + 7.7i);
REQUIRE((it + 6)->at(_0) == 15.5 + 10.2i);
REQUIRE((it + 7)->at(_0) == 9.1 + 7.7i);
REQUIRE((it + 8)->at(_0) == 9.3 + 10.2i);

REQUIRE((it + 0)->at(_1) == 8.9);
REQUIRE((it + 1)->at(_1) == 10.0);
REQUIRE((it + 2)->at(_1) == 11.1);
REQUIRE((it + 3)->at(_1) == 12.2);
REQUIRE((it + 4)->at(_1) == 13.3);
REQUIRE((it + 5)->at(_1) == 14.4);
REQUIRE((it + 6)->at(_1) == 15.5);
REQUIRE((it + 7)->at(_1) == 9.1);
REQUIRE((it + 8)->at(_1) == 9.3);

REQUIRE((it + 0)->at(_2) == 2022_y / January / 1);
REQUIRE((it + 1)->at(_2) == 2022_y / January / 2);
REQUIRE((it + 2)->at(_2) == 2022_y / January / 3);
REQUIRE((it + 3)->at(_2) == 2022_y / January / 4);
REQUIRE((it + 4)->at(_2) == 2022_y / January / 5);
REQUIRE((it + 5)->at(_2) == 2022_y / January / 6);
REQUIRE((it + 6)->at(_2) == 2022_y / January / 7);
REQUIRE((it + 7)->at(_2) == 2022_y / January / 8);
REQUIRE((it + 8)->at(_2) == 2022_y / January / 9);

REQUIRE((it + 0)->at(_3) == 10.2);
REQUIRE((it + 1)->at(_3) == 10.2);
REQUIRE((it + 2)->at(_3) == 7.7);
REQUIRE((it + 3)->at(_3) == 10.2);
REQUIRE((it + 4)->at(_3) == 10.2);
REQUIRE((it + 5)->at(_3) == 7.7);
REQUIRE((it + 6)->at(_3) == 10.2);
REQUIRE((it + 7)->at(_3) == 7.7);
REQUIRE((it + 8)->at(_3) == 10.2);
}

SECTION("realimag")
{
frame<complex<double>, year_month_day> f1;
f1.set_column_names("cmplx", "date");
f1.push_back( 8.9 + 10.2i, 2022_y / January / 1);
f1.push_back(10.2 + 10.2i, 2022_y / January / 2);
f1.push_back(11.1 + 7.7i, 2022_y / January / 3);
f1.push_back(12.2 + 10.2i, 2022_y / January / 4);
f1.push_back(13.3 + 10.2i, 2022_y / January / 5);
f1.push_back(14.4 + 7.7i, 2022_y / January / 6);
f1.push_back(15.5 + 10.2i, 2022_y / January / 7);
f1.push_back( 9.1 + 7.7i, 2022_y / January / 8);
f1.push_back( 9.3 + 10.2i, 2022_y / January / 9);

auto f2 = f1.append_column<double>("real", real<double>(_0));
auto f3 = f2.append_column<double>("imag", imag<double>(_0));
auto it = f3.cbegin();
REQUIRE((it + 0)->at(_0) == 8.9 + 10.2i);
REQUIRE((it + 1)->at(_0) == 10.0 + 10.2i);
REQUIRE((it + 2)->at(_0) == 11.1 + 7.7i);
REQUIRE((it + 3)->at(_0) == 12.2 + 10.2i);
REQUIRE((it + 4)->at(_0) == 13.3 + 10.2i);
REQUIRE((it + 5)->at(_0) == 14.4 + 7.7i);
REQUIRE((it + 6)->at(_0) == 15.5 + 10.2i);
REQUIRE((it + 7)->at(_0) == 9.1 + 7.7i);
REQUIRE((it + 8)->at(_0) == 9.3 + 10.2i);

REQUIRE((it + 0)->at(_1) == 2022_y / January / 1);
REQUIRE((it + 1)->at(_1) == 2022_y / January / 2);
REQUIRE((it + 2)->at(_1) == 2022_y / January / 3);
REQUIRE((it + 3)->at(_1) == 2022_y / January / 4);
REQUIRE((it + 4)->at(_1) == 2022_y / January / 5);
REQUIRE((it + 5)->at(_1) == 2022_y / January / 6);
REQUIRE((it + 6)->at(_1) == 2022_y / January / 7);
REQUIRE((it + 7)->at(_1) == 2022_y / January / 8);
REQUIRE((it + 8)->at(_1) == 2022_y / January / 9);

REQUIRE((it + 0)->at(_2) == 8.9);
REQUIRE((it + 1)->at(_2) == 10.0);
REQUIRE((it + 2)->at(_2) == 11.1);
REQUIRE((it + 3)->at(_2) == 12.2);
REQUIRE((it + 4)->at(_2) == 13.3);
REQUIRE((it + 5)->at(_2) == 14.4);
REQUIRE((it + 6)->at(_2) == 15.5);
REQUIRE((it + 7)->at(_2) == 9.1);
REQUIRE((it + 8)->at(_2) == 9.3);

REQUIRE((it + 0)->at(_3) == 10.2);
REQUIRE((it + 1)->at(_3) == 10.2);
REQUIRE((it + 2)->at(_3) == 7.7);
REQUIRE((it + 3)->at(_3) == 10.2);
REQUIRE((it + 4)->at(_3) == 10.2);
REQUIRE((it + 5)->at(_3) == 7.7);
REQUIRE((it + 6)->at(_3) == 10.2);
REQUIRE((it + 7)->at(_3) == 7.7);
REQUIRE((it + 8)->at(_3) == 10.2);
}
}

TEST_CASE("remove_column", "[frame]")
{
frame<year_month_day, double, int> f1;
Expand Down

0 comments on commit 72a5d86

Please sign in to comment.