Skip to content
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

Sugar median with unit tests #425

Merged
merged 4 commits into from Jan 21, 2016
Merged

Sugar median with unit tests #425

merged 4 commits into from Jan 21, 2016

Conversation

@nathan-russell
Copy link
Contributor

@nathan-russell nathan-russell commented Jan 18, 2016

As discussed in #424, this adds a sugar function Rcpp::median with corresponding unit tests.

@@ -0,0 +1,297 @@
// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; tab-width: 8 -*-

This comment has been minimized.

@eddelbuettel

eddelbuettel Jan 18, 2016
Member

I have a much newer version of this line but then I never said anything official about it...

//
// median.h: Rcpp R/C++ interface class library -- median
//
// Copyright (C) 2012 - 2013 Dirk Eddelbuettel and Romain Francois

This comment has been minimized.

@eddelbuettel

eddelbuettel Jan 18, 2016
Member

2012-2013 makes no sense (and just shows the copy and pasty). If the file is all yours may as well drop us. Or keep us in as a courtesy. Your file, your call.

// median.h: Rcpp R/C++ interface class library -- median
//
// Copyright (C) 2012 - 2013 Dirk Eddelbuettel and Romain Francois
// Copyright (C) 2016 - Nathan Russell

This comment has been minimized.

@eddelbuettel

eddelbuettel Jan 18, 2016
Member

If there is one year only, no hyphen. (Not that it matters but as I am in nitpick mode...)

@eddelbuettel
Copy link
Member

@eddelbuettel eddelbuettel commented Jan 18, 2016

This looks good. I had in the back of my mind a though that R's median() had a bazillion further options, but maybe I was thinking about quantile() and its (crazy but impressive) type= argument.

So this is probably good too but one or two seconds would be nice.

@nathan-russell
Copy link
Contributor Author

@nathan-russell nathan-russell commented Jan 18, 2016

Okay, that sounds good. In the meantime I will make the appropriate changes regarding your comments above. Is this the newer version of the formatting line you referred to:

-*- mode: C++; c-indent-level: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*-

@eddelbuettel
Copy link
Member

@eddelbuettel eddelbuettel commented Jan 18, 2016

Yep. Hard tabs are evil, which we learned eventually. But I leave commits touching every single file to @kevinushey :) -- in short, bulk changes aren't worth it either.

There isn't too much about code style you don't already know or do. Four spaces is better than too, indentation pretty much like R Core and other sensible people do etc pp. No biggies.

@nathan-russell
Copy link
Contributor Author

@nathan-russell nathan-russell commented Jan 18, 2016

Agreed on the spaces vs. tabs - it was just sloppy copy & paste on my part from another sugar file, and being a vim guy (sorry!) the outdated formatting settings didn't catch my eye.

@kevinushey
Copy link
Contributor

@kevinushey kevinushey commented Jan 19, 2016

FWIW we now use .dir-locals.el to enforce indentation rules when editing with Emacs; does Vim have an analogue for directory-local variables / indentation rules?


public:
Median(const VECTOR& xx)
: x(Rcpp::clone(xx)) {}

This comment has been minimized.

@kevinushey

kevinushey Jan 19, 2016
Contributor

Just to confirm -- we clone the vector here because the std:: algorithm we use will modify the passed vector?

public:
typedef typename median_detail::result<RTYPE>::type result_type;
typedef typename Rcpp::traits::storage_type<RTYPE>::type stored_type;
enum { RTYPE2 = median_detail::result<RTYPE>::rtype };

This comment has been minimized.

@kevinushey

kevinushey Jan 19, 2016
Contributor

Maybe instead of RTYPE2 we could use RESULT_RTYPE or result_rtype or something?

template <int RTYPE, bool NA, typename T>
inline typename sugar::median_detail::result<RTYPE>::type
median(const Rcpp::VectorBase<RTYPE, NA, T>& x, bool na_rm = false) {
switch (static_cast<int>(na_rm)) {

This comment has been minimized.

@kevinushey

kevinushey Jan 19, 2016
Contributor

How come we can't just use an if-else on the na_rm parameter? The static_cast<int> is kind of funky.

@thirdwing
Copy link
Member

@thirdwing thirdwing commented Jan 19, 2016

Maybe we can also have a .vim.custom to set indent.

But if we really want to have a consistent coding style, we might think about cpplint from Google.

@eddelbuettel
Copy link
Member

@eddelbuettel eddelbuettel commented Jan 19, 2016

Re .dir-locals.el, the fanciest / most general scheme I know is via editorconfig where, as I understand it, you define a 'policy' or outcome and the editor-specific plugins implement it in the editor of choice.

Alternatively, and there clang-format but all of that is a bit of the heavy-handed side.

@eddelbuettel
Copy link
Member

@eddelbuettel eddelbuettel commented Jan 19, 2016

My bad for the close and re-open. Hit the wrong button.

@kevinushey
Copy link
Contributor

@kevinushey kevinushey commented Jan 19, 2016

Other than some minor comments this looks good to me.

@nathan-russell
Copy link
Contributor Author

@nathan-russell nathan-russell commented Jan 19, 2016

@kevinushey Thanks for the feedback - I do believe it is necessary to call Rcpp::clone in the constructor as above. I just did a rebuild without the use of clone and it appears to modify the original vector:

#include <Rcpp.h>

// [[Rcpp::export]]
double median_dbl(Rcpp::NumericVector x, bool na_rm = false) {
    return Rcpp::median(x, na_rm);
}

// [[Rcpp::export]]
double median_int(Rcpp::IntegerVector x, bool na_rm = false) {
    return Rcpp::median(x, na_rm);
}

// [[Rcpp::export]]
Rcomplex median_cx(Rcpp::ComplexVector x, bool na_rm = false) {
    return Rcpp::median(x, na_rm);
}

// [[Rcpp::export]]
Rcpp::String median_ch(Rcpp::CharacterVector x, bool na_rm = false) {
    return Rcpp::median(x, na_rm);
}


/*** R

set.seed(123)
(xx <- rnorm(5))
#[1] -0.56047565 -0.23017749  1.55870831  0.07050839  0.12928774

median_dbl(xx)
#[1] 0.07050839

xx
#[1] -0.56047565 -0.23017749  0.07050839  0.12928774  1.55870831

set.seed(123)
(xx <- as.integer(rpois(5, 20)))
#[1] 17 25 12 20 27

median_int(xx)
#[1] 20

xx
#[1] 17 12 20 25 27

set.seed(123)
(xx <- rnorm(5) + 2i)
#[1] -0.560476+2i -0.230177+2i  1.558708+2i  0.070508+2i  0.129288+2i

median_cx(xx)
#[1] 0.070508+2i

xx
#[1] -0.560476+2i -0.230177+2i  0.070508+2i  0.129288+2i  1.558708+2i

set.seed(123)
(xx <- sample(letters, 5))
#[1] "h" "t" "j" "u" "w"

median_ch(xx)
#[1] "t"

xx
##[1] "h" "j" "t" "u" "w"

*/

As for the other points, I'll set RTYPE2 to RESULT_RTYPE and swap out the switch statement with an if statement and commit the changes.

I have not used / am not aware of anything analogous to .dir-locals.el or the Emacs configuration lines embedded in the Rcpp headers; I just have the standard ~/.vimrc and ~/.vim/ftplugin/*.vim files on my machines.

@eddelbuettel
Copy link
Member

@eddelbuettel eddelbuettel commented Jan 21, 2016

Time to pull this one in!

eddelbuettel added a commit that referenced this pull request Jan 21, 2016
Sugar median with unit tests
@eddelbuettel eddelbuettel merged commit fcbfcc6 into RcppCore:master Jan 21, 2016
1 check passed
1 check passed
continuous-integration/travis-ci/pr The Travis CI build passed
Details
@nathan-russell
Copy link
Contributor Author

@nathan-russell nathan-russell commented Jan 21, 2016

👍

@eddelbuettel
Copy link
Member

@eddelbuettel eddelbuettel commented Jan 21, 2016

No, thumbs up to you -- that was really well done (but I was a little tied up yesterday and the day before).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

None yet

4 participants
You can’t perform that action at this time.