-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rework to conversion and allowing many input types #49
base: master
Are you sure you want to change the base?
Rework to conversion and allowing many input types #49
Conversation
While clones may seem more common I believe they have simply been made more explicit (not hiding inside the respective `into()` method).
The design is simpler and I like that. The thing I am not a fan of is that there is no conversion from reference in this version leading to clones in the code that might be avoided (if the data will be copied during the convertion process anyway). The two potential fixes I see are:
I would go with the first one. |
Also, adding tests to cover the various conversions would be good, that is a hole in the test coverage. |
Considering:
I would note that in the conversion via reference in the old approach it was just obfuscating a clone, I tend to be of the opinion it is best to bubble up things like clones so they are as explicit as possible. |
The old approach used a clone as the default implementation but few of the actual implementations used a clone (from memory only the ones taking an nalgebra type as reference and returning an owned nalgebra type). Most conversion functions used under the hood take a reference so a lot of clones are not needed. |
Okay, I'll look into it and commit some changes to sort it. |
I can't find where data is now being cloned that it was previously reinterpreted. Notably all the cases of conversion functions I've found as you mention with:
Are the same as clones, just less explicit. They not reinterpret castes or creating a |
Your version does a clone of the initial I can give you some line numbers if my explanation is not clear. |
Copying to nalgebra types is no different to cloning (copying is just implicit cloning after all), it will compile to the same. Except implementing a But if you have any specific examples you disagree with if you reference some code that'd be good. |
That's my point, your version does a clone followed by the conversion (so two clones, here for example: My suggestion would be to have an |
It doesn't do 2 clone, for instance see this code: use std::collections::HashSet;
fn main() {
let a = vec![String::from("1"),String::from("2"),String::from("3")]
// Without using `a` and `b` further it will simply be moved here, not cloned
let b = some_function(a.clone());
// let b = some_function_2(&a);
// If we use both `a` and `b`, we have effectively cloned `a` once.
}
fn some_function(x: Vec<String>) -> HashSet<String> {
x.into_iter().collect::<HashSet<_>>()
}
// If we replace our `some_function` with something like, we have obfuscated the clone
// from the user and produced the exact same result.
fn some_function_2(x: &[String]) -> HashSet<String> {
x.iter().cloned().collect::<HashSet<_>>()
} Some of your previous implementations are like There is a reason
This is effectively mimicking that (it may be helpful to look up move semantics). Saying:
Is entirely counter to this point and the design of conversion, if a clone is happening, which it is, the user should know about it (and further you don't need to be particularly concerned about things clone/copying twice, unless it is necessary it will not happen and will almost always be optimized out by the compiler in any possible case). You should not pass a reference to a conversion in which values are cloned or copied as this gives the user the implicit impression a copy/clone is not occurring when it is. All the methods for converting to nalgebra structures involve cloning/copying all of the given data. |
I understand your point. There are two aspect to it, the implementation and the user interface: ImplementationWhen you call Now, if we have a function that takes the data by reference ( (Yes, the previous ndarray conversion functions didn't do that and did some useless cloning along the User interfaceFor all versions (the main branch as well as your PR), the conversion functions are used inside friedrich's code. On the API side, this design decision makes no change to the user who passes their value by reference. Introducing The other alternative is to take user input by value eliminating the case for SummaryMy point is that introducing Am I missing something? |
If I changed my implementation to implement The point being, it is okay to clone. This is not an unoptimized |
I am not convinced of that in this particular case. The clone and actual use of the data would happen in two different crates and the datastructure might be non-trivial. I usually trust the compiler but here I would bet on an actual memcopy happening. But I might be shaving yacks here. The code is fine and, ultimately, even the cost of two clones is small compared to the cost of the Cholesky decomposition. You can add some tests and I will merge :) |
In essence the traits:
are in my opinion a more explicit and extensible approach than:
While there are no criterion benchmarks to guarantee no performance regression I do not believe these change would have any affect.