Skip to content

Conversation

isuruf
Copy link
Member

@isuruf isuruf commented Nov 6, 2020

TODO:

  • rename serialize.h -> serialize-cereal.h
  • Add loads, dumps methods to basic.h and implement it using cereal in basic.cpp
  • Add tests
  • Make compiling conditional on cereal being available
  • Implement more classes.
  • Use something else than typeid. They are not stable across versions.

@isuruf-bot
Copy link

isuruf-bot commented Nov 6, 2020

Hi,

I've run clang-format and found that the code needs formatting.
Here's a commit that fixes this. isuruf-bot@2d24e7a

To use the commit you can do

curl -o format.diff https://github.com/isuruf-bot/symengine/commit/2d24e7abba25af146bd2221f59c59d7947c9a21d.diff
git apply format.diff


#define SYMENGINE_ENUM(type, Class) \
template <class Archive> \
inline void save_basic(Archive &ar, const Class &b) \
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use save_basic(Archive &ar, const OneArgFunction &b) and get rid of defining these multiple times.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, of course, will fix this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this really reduced the number of save_basic implementations. For load_basic I haven't yet come up with anything as elegant. I have the gut feeling it should be possible to do something leaner, any ideas?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

load_basic(Archive &ar, RCP<const OneArgFunction> &b) ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OneArgFunction is abstract, so I don't think that's possible?

Copy link
Contributor

@bjodah bjodah Nov 8, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean I can dispatch on it, but after that I'm at loss:

template <class Archive>
RCP<const Basic> load_basic(Archive &ar, RCP<const OneArgFunction> &)
{
    RCP<const Basic> arg;
    ar(arg);
    return basic_rcp_from_type_code_and_args(type_code, arg);
}

I guess I could change the signature of all load_basic dispatch functions to take type_code as an arguemnt, but then we still need the hypothetical basic_rcp_from_type_code_and_args?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See f7ada37

@bjodah
Copy link
Contributor

bjodah commented Nov 7, 2020

OK, I'm done for tonight (GMT+1 in Stockholm). If you get the chance to take a look: let me know what you think so far ☺.

template <class Archive, typename T>
RCP<const Basic> load_basic(Archive &ar, RCP<const T> &b)
{
const auto t_code = b->get_type_code();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

b is a dummy to allow writing code with inheritance. Don't use it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, but isn't it guaranteed that it inherits from Basic?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but the pointer inside might be NULL, so you can't call methods on it.

@@ -24,6 +43,20 @@ std::string Basic::__str__() const
return str(*this);
}

std::string Basic::dumps() const {
std::ostringstream oss;
cereal::BinaryOutputArchive{oss}(this->rcp_from_this());
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is BinaryOutputArchive portable?

Copy link
Contributor

@bjodah bjodah Nov 8, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, no it wasn't: endianness is handled by PortableBinaryOutputArchive. I just changed this.

@bjodah
Copy link
Contributor

bjodah commented Nov 8, 2020

As for TypeIDs not being stable across versions of symengine: Cereal supports versioned serialization. We could write one new migrator for each new version of SymEngine, translating TypeIDs from version x to version x + 1. No performance impact for users keeping their serialized data up to date, and probably an acceptable cost for users using old data?

@bjodah
Copy link
Contributor

bjodah commented Nov 8, 2020

Ah, nice, std::is_base_of & std::enable_if, so this is SFINAE in action I presume? (I never seem to get it right whenever I try to use those).

@isuruf
Copy link
Member Author

isuruf commented Nov 8, 2020

Yes, it is SFINAE

@bjodah
Copy link
Contributor

bjodah commented Nov 8, 2020

Thanks, I got rid of those helpers I introduced before your SFINAE design.

So debugging SFINAE is a bit of a pain right? I'm trying to support URatPoly but it's not picking up my save_basic overload:

template <class Archive>
inline void save_basic(Archive &ar, const URatPoly &b)
{
    ar(b.get_var());
    ar(b.get_poly());
}
Excerpt from test_lambda_double
Evaluate functions
-------------------------------------------------------------------------------
../symengine/tests/eval/test_lambda_double.cpp:187
...............................................................................

../symengine/tests/eval/test_lambda_double.cpp:187: FAILED:
{Unknown expression after the reported line}
due to unexpected exception with message:
../symengine/serialize-cereal.h:23: void SymEngine::save_basic(Archive&,
const SymEngine::Basic&) [with Archive = cereal::PortableBinaryOutputArchive]
not supported: URatPoly (15), tan(x)*sec(x)

I guess some one or several of my overloads for the building blocks here (URatDict -> rational_class -> integer_class) isn't quite working. But I don't know how to debug this behavior, any tips?

@isuruf
Copy link
Member Author

isuruf commented Nov 8, 2020

Don't know how to debug the general case. In this case you probably need Mul

@isuruf isuruf requested a review from a team November 7, 2021 16:55
Copy link
Contributor

@rikardn rikardn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great work!

One question: What would happen if attempting to serialize an object that isn't (yet) supported?

@@ -0,0 +1,696 @@
#pragma once
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is non-standard. Use include guards instead?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm curious: can you name a compiler which can compile symengine, but doesn't support #pragma once? 🙂

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've seen the #pragma once used lately in C++. So far I always suggested to just use the old fashion include guards.

I am not against using #pragma once, it is definitely simpler. However I want to make sure we do not break the compilation.

@bjodah can you summarize the support in compilers for #pragma once? And why is it not standard?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. The only compiler I've seen is Oracle Development Studio which we have partial support for. #1646

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know why it's not supported by the standard (the standard doesn't say much about the preprocessor from what I've seen). My question was genuine: I was curious about the existence of any compilers which lacks support for it (and I've seen multiple recommendations to prefer the pragma approach). But now we know: Oracle doesn't support it then. 🙂

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to support Oracle?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not a big deal to keep using include guards instead of pragma once. I think we are using Oracle for R wrappers.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use the guards then.

@isuruf
Copy link
Member Author

isuruf commented Nov 7, 2021

One question: What would happen if attempting to serialize an object that isn't (yet) supported?

A SymEngine::NotImplementedError exception is thrown.

@bjodah
Copy link
Contributor

bjodah commented Nov 7, 2021

Do we want to add a .gitattributes file so that vendored files from cereal doesn't show up in the "Files changed view"?, I think a .gitattributes file with an entry such as this would work:

symengine/utilities/cereal/include/cereal/* linguist-vendored

@isuruf isuruf requested review from certik, rikardn and bjodah November 9, 2021 20:42
Copy link
Contributor

@bjodah bjodah left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great stuff! I only spotted two potential minor issues.

@isuruf isuruf merged commit 4b841d1 into symengine:master Nov 10, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants