Passing uint64_t from C++ to R: Hilbert Mapping - xy2d function












4












$begingroup$


I have been working with Rcpp to perform a forward and backward Hilbert Mapping. Below is an implementation based on this code.



My application is in genomics and I may be dealing with enormous datasets, which necessitates the use of very large integers for indices, so I found this code for passing large integers to R using Rcpp and the bit64 R package and incorporated it after the for loop.



The xy2d() function works properly. My interest is on your thought regarding the code AFTER the for loop, which prepared the result for passage back to R. Please let me know what you think :)



#include <Rcpp.h>
using namespace Rcpp;
# include <bitset>
# include <cstdint>
# include <ctime>
# include <iomanip>
# include <iostream>
using namespace std;
//****************************************************************************80
// [[Rcpp::export]]
Rcpp::NumericVector xy2d ( int m, uint64_t x, uint64_t y )
//
//****************************************************************************80
{
uint64_t d = 0;
uint64_t n;
int rx;
int ry;
uint64_t s;

n = i4_power ( 2, m );

if ( x > n - 1 || y > n - 1) {
throw std::range_error("Neither x nor y may be larger than (2^m - 1)n");
}

for ( s = n / 2; s > 0; s = s / 2 )
{
rx = ( x & s ) > 0;
ry = ( y & s ) > 0;
d = d + s * s * ( ( 3 * rx ) ^ ry );
rot ( s, x, y, rx, ry );
}

std::vector<uint64_t> v;
v.push_back(d);
//v[0] = d

size_t len = v.size();
Rcpp::NumericVector nn(len); // storage vehicle we return them in

// transfers values 'keeping bits' but changing type
// using reinterpret_cast would get us a warning
std::memcpy(&(nn[0]), &(v[0]), len * sizeof(uint64_t));

nn.attr("class") = "integer64";
return nn;
}


This post will be followed up shortly with another post regarding the rot() function, and well as the reverse d2xy() function










share|improve this question









New contributor




Lewkrr is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.







$endgroup$












  • $begingroup$
    @422_unprocessable_entity: The Hilbert mapping function works with no problems. I am seeking advice on the code AFTER the for-loop in which I prepare the results to be passed to R. "Hilbert Mapping - xy2d function" makes that unclear. I feel that my original title was better, would you agree?
    $endgroup$
    – Lewkrr
    9 hours ago










  • $begingroup$
    Welcome to CR. I edited the question title because I thought it can be improved as recommended here. Anyway it is a good question.
    $endgroup$
    – 422_unprocessable_entity
    8 hours ago


















4












$begingroup$


I have been working with Rcpp to perform a forward and backward Hilbert Mapping. Below is an implementation based on this code.



My application is in genomics and I may be dealing with enormous datasets, which necessitates the use of very large integers for indices, so I found this code for passing large integers to R using Rcpp and the bit64 R package and incorporated it after the for loop.



The xy2d() function works properly. My interest is on your thought regarding the code AFTER the for loop, which prepared the result for passage back to R. Please let me know what you think :)



#include <Rcpp.h>
using namespace Rcpp;
# include <bitset>
# include <cstdint>
# include <ctime>
# include <iomanip>
# include <iostream>
using namespace std;
//****************************************************************************80
// [[Rcpp::export]]
Rcpp::NumericVector xy2d ( int m, uint64_t x, uint64_t y )
//
//****************************************************************************80
{
uint64_t d = 0;
uint64_t n;
int rx;
int ry;
uint64_t s;

n = i4_power ( 2, m );

if ( x > n - 1 || y > n - 1) {
throw std::range_error("Neither x nor y may be larger than (2^m - 1)n");
}

for ( s = n / 2; s > 0; s = s / 2 )
{
rx = ( x & s ) > 0;
ry = ( y & s ) > 0;
d = d + s * s * ( ( 3 * rx ) ^ ry );
rot ( s, x, y, rx, ry );
}

std::vector<uint64_t> v;
v.push_back(d);
//v[0] = d

size_t len = v.size();
Rcpp::NumericVector nn(len); // storage vehicle we return them in

// transfers values 'keeping bits' but changing type
// using reinterpret_cast would get us a warning
std::memcpy(&(nn[0]), &(v[0]), len * sizeof(uint64_t));

nn.attr("class") = "integer64";
return nn;
}


This post will be followed up shortly with another post regarding the rot() function, and well as the reverse d2xy() function










share|improve this question









New contributor




Lewkrr is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.







$endgroup$












  • $begingroup$
    @422_unprocessable_entity: The Hilbert mapping function works with no problems. I am seeking advice on the code AFTER the for-loop in which I prepare the results to be passed to R. "Hilbert Mapping - xy2d function" makes that unclear. I feel that my original title was better, would you agree?
    $endgroup$
    – Lewkrr
    9 hours ago










  • $begingroup$
    Welcome to CR. I edited the question title because I thought it can be improved as recommended here. Anyway it is a good question.
    $endgroup$
    – 422_unprocessable_entity
    8 hours ago
















4












4








4





$begingroup$


I have been working with Rcpp to perform a forward and backward Hilbert Mapping. Below is an implementation based on this code.



My application is in genomics and I may be dealing with enormous datasets, which necessitates the use of very large integers for indices, so I found this code for passing large integers to R using Rcpp and the bit64 R package and incorporated it after the for loop.



The xy2d() function works properly. My interest is on your thought regarding the code AFTER the for loop, which prepared the result for passage back to R. Please let me know what you think :)



#include <Rcpp.h>
using namespace Rcpp;
# include <bitset>
# include <cstdint>
# include <ctime>
# include <iomanip>
# include <iostream>
using namespace std;
//****************************************************************************80
// [[Rcpp::export]]
Rcpp::NumericVector xy2d ( int m, uint64_t x, uint64_t y )
//
//****************************************************************************80
{
uint64_t d = 0;
uint64_t n;
int rx;
int ry;
uint64_t s;

n = i4_power ( 2, m );

if ( x > n - 1 || y > n - 1) {
throw std::range_error("Neither x nor y may be larger than (2^m - 1)n");
}

for ( s = n / 2; s > 0; s = s / 2 )
{
rx = ( x & s ) > 0;
ry = ( y & s ) > 0;
d = d + s * s * ( ( 3 * rx ) ^ ry );
rot ( s, x, y, rx, ry );
}

std::vector<uint64_t> v;
v.push_back(d);
//v[0] = d

size_t len = v.size();
Rcpp::NumericVector nn(len); // storage vehicle we return them in

// transfers values 'keeping bits' but changing type
// using reinterpret_cast would get us a warning
std::memcpy(&(nn[0]), &(v[0]), len * sizeof(uint64_t));

nn.attr("class") = "integer64";
return nn;
}


This post will be followed up shortly with another post regarding the rot() function, and well as the reverse d2xy() function










share|improve this question









New contributor




Lewkrr is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.







$endgroup$




I have been working with Rcpp to perform a forward and backward Hilbert Mapping. Below is an implementation based on this code.



My application is in genomics and I may be dealing with enormous datasets, which necessitates the use of very large integers for indices, so I found this code for passing large integers to R using Rcpp and the bit64 R package and incorporated it after the for loop.



The xy2d() function works properly. My interest is on your thought regarding the code AFTER the for loop, which prepared the result for passage back to R. Please let me know what you think :)



#include <Rcpp.h>
using namespace Rcpp;
# include <bitset>
# include <cstdint>
# include <ctime>
# include <iomanip>
# include <iostream>
using namespace std;
//****************************************************************************80
// [[Rcpp::export]]
Rcpp::NumericVector xy2d ( int m, uint64_t x, uint64_t y )
//
//****************************************************************************80
{
uint64_t d = 0;
uint64_t n;
int rx;
int ry;
uint64_t s;

n = i4_power ( 2, m );

if ( x > n - 1 || y > n - 1) {
throw std::range_error("Neither x nor y may be larger than (2^m - 1)n");
}

for ( s = n / 2; s > 0; s = s / 2 )
{
rx = ( x & s ) > 0;
ry = ( y & s ) > 0;
d = d + s * s * ( ( 3 * rx ) ^ ry );
rot ( s, x, y, rx, ry );
}

std::vector<uint64_t> v;
v.push_back(d);
//v[0] = d

size_t len = v.size();
Rcpp::NumericVector nn(len); // storage vehicle we return them in

// transfers values 'keeping bits' but changing type
// using reinterpret_cast would get us a warning
std::memcpy(&(nn[0]), &(v[0]), len * sizeof(uint64_t));

nn.attr("class") = "integer64";
return nn;
}


This post will be followed up shortly with another post regarding the rot() function, and well as the reverse d2xy() function







c++ c++11 r rcpp






share|improve this question









New contributor




Lewkrr is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











share|improve this question









New contributor




Lewkrr is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









share|improve this question




share|improve this question








edited 9 hours ago







Lewkrr













New contributor




Lewkrr is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









asked 10 hours ago









LewkrrLewkrr

234




234




New contributor




Lewkrr is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.





New contributor





Lewkrr is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






Lewkrr is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.












  • $begingroup$
    @422_unprocessable_entity: The Hilbert mapping function works with no problems. I am seeking advice on the code AFTER the for-loop in which I prepare the results to be passed to R. "Hilbert Mapping - xy2d function" makes that unclear. I feel that my original title was better, would you agree?
    $endgroup$
    – Lewkrr
    9 hours ago










  • $begingroup$
    Welcome to CR. I edited the question title because I thought it can be improved as recommended here. Anyway it is a good question.
    $endgroup$
    – 422_unprocessable_entity
    8 hours ago




















  • $begingroup$
    @422_unprocessable_entity: The Hilbert mapping function works with no problems. I am seeking advice on the code AFTER the for-loop in which I prepare the results to be passed to R. "Hilbert Mapping - xy2d function" makes that unclear. I feel that my original title was better, would you agree?
    $endgroup$
    – Lewkrr
    9 hours ago










  • $begingroup$
    Welcome to CR. I edited the question title because I thought it can be improved as recommended here. Anyway it is a good question.
    $endgroup$
    – 422_unprocessable_entity
    8 hours ago


















$begingroup$
@422_unprocessable_entity: The Hilbert mapping function works with no problems. I am seeking advice on the code AFTER the for-loop in which I prepare the results to be passed to R. "Hilbert Mapping - xy2d function" makes that unclear. I feel that my original title was better, would you agree?
$endgroup$
– Lewkrr
9 hours ago




$begingroup$
@422_unprocessable_entity: The Hilbert mapping function works with no problems. I am seeking advice on the code AFTER the for-loop in which I prepare the results to be passed to R. "Hilbert Mapping - xy2d function" makes that unclear. I feel that my original title was better, would you agree?
$endgroup$
– Lewkrr
9 hours ago












$begingroup$
Welcome to CR. I edited the question title because I thought it can be improved as recommended here. Anyway it is a good question.
$endgroup$
– 422_unprocessable_entity
8 hours ago






$begingroup$
Welcome to CR. I edited the question title because I thought it can be improved as recommended here. Anyway it is a good question.
$endgroup$
– 422_unprocessable_entity
8 hours ago












1 Answer
1






active

oldest

votes


















3












$begingroup$


  • Because we write C++, there's no reason to declare (most) variables at the beginning of the scope of your function. For example, all of d, rx, ry and s have been declared for no reason if you happen to throw and exit the function.


  • You don't need s after the for-loop, so it should be local to the loop only. Similar for rx and ry.


  • Make use of shorthand operators like /= and +=.


  • You can make v const and initialize it with a suitable constructor, in this case std::vector<uint64_t> v(1, d); initializes v to hold one element equal to d. But really, as it stands, I see no point in using an array here if you just have a single value (I suspect your example is incomplete and not representative of your real use case, which is a shame).


  • Because len can be const, make it const. This protects from unintended errors and possibly allows the compiler to perform more optimizations.


  • As a general comment, avoid saying using namespace std;, it's not good for you.


  • I don't know the interface of Rcpp::NumericVector, but might you initialize it directly in the spirit of const Rcpp::NumericVector nn(v.cbegin(), v.cend()), for instance?







share|improve this answer









$endgroup$













    Your Answer





    StackExchange.ifUsing("editor", function () {
    return StackExchange.using("mathjaxEditing", function () {
    StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
    StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
    });
    });
    }, "mathjax-editing");

    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "196"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: false,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });






    Lewkrr is a new contributor. Be nice, and check out our Code of Conduct.










    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f216000%2fpassing-uint64-t-from-c-to-r-hilbert-mapping-xy2d-function%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    3












    $begingroup$


    • Because we write C++, there's no reason to declare (most) variables at the beginning of the scope of your function. For example, all of d, rx, ry and s have been declared for no reason if you happen to throw and exit the function.


    • You don't need s after the for-loop, so it should be local to the loop only. Similar for rx and ry.


    • Make use of shorthand operators like /= and +=.


    • You can make v const and initialize it with a suitable constructor, in this case std::vector<uint64_t> v(1, d); initializes v to hold one element equal to d. But really, as it stands, I see no point in using an array here if you just have a single value (I suspect your example is incomplete and not representative of your real use case, which is a shame).


    • Because len can be const, make it const. This protects from unintended errors and possibly allows the compiler to perform more optimizations.


    • As a general comment, avoid saying using namespace std;, it's not good for you.


    • I don't know the interface of Rcpp::NumericVector, but might you initialize it directly in the spirit of const Rcpp::NumericVector nn(v.cbegin(), v.cend()), for instance?







    share|improve this answer









    $endgroup$


















      3












      $begingroup$


      • Because we write C++, there's no reason to declare (most) variables at the beginning of the scope of your function. For example, all of d, rx, ry and s have been declared for no reason if you happen to throw and exit the function.


      • You don't need s after the for-loop, so it should be local to the loop only. Similar for rx and ry.


      • Make use of shorthand operators like /= and +=.


      • You can make v const and initialize it with a suitable constructor, in this case std::vector<uint64_t> v(1, d); initializes v to hold one element equal to d. But really, as it stands, I see no point in using an array here if you just have a single value (I suspect your example is incomplete and not representative of your real use case, which is a shame).


      • Because len can be const, make it const. This protects from unintended errors and possibly allows the compiler to perform more optimizations.


      • As a general comment, avoid saying using namespace std;, it's not good for you.


      • I don't know the interface of Rcpp::NumericVector, but might you initialize it directly in the spirit of const Rcpp::NumericVector nn(v.cbegin(), v.cend()), for instance?







      share|improve this answer









      $endgroup$
















        3












        3








        3





        $begingroup$


        • Because we write C++, there's no reason to declare (most) variables at the beginning of the scope of your function. For example, all of d, rx, ry and s have been declared for no reason if you happen to throw and exit the function.


        • You don't need s after the for-loop, so it should be local to the loop only. Similar for rx and ry.


        • Make use of shorthand operators like /= and +=.


        • You can make v const and initialize it with a suitable constructor, in this case std::vector<uint64_t> v(1, d); initializes v to hold one element equal to d. But really, as it stands, I see no point in using an array here if you just have a single value (I suspect your example is incomplete and not representative of your real use case, which is a shame).


        • Because len can be const, make it const. This protects from unintended errors and possibly allows the compiler to perform more optimizations.


        • As a general comment, avoid saying using namespace std;, it's not good for you.


        • I don't know the interface of Rcpp::NumericVector, but might you initialize it directly in the spirit of const Rcpp::NumericVector nn(v.cbegin(), v.cend()), for instance?







        share|improve this answer









        $endgroup$




        • Because we write C++, there's no reason to declare (most) variables at the beginning of the scope of your function. For example, all of d, rx, ry and s have been declared for no reason if you happen to throw and exit the function.


        • You don't need s after the for-loop, so it should be local to the loop only. Similar for rx and ry.


        • Make use of shorthand operators like /= and +=.


        • You can make v const and initialize it with a suitable constructor, in this case std::vector<uint64_t> v(1, d); initializes v to hold one element equal to d. But really, as it stands, I see no point in using an array here if you just have a single value (I suspect your example is incomplete and not representative of your real use case, which is a shame).


        • Because len can be const, make it const. This protects from unintended errors and possibly allows the compiler to perform more optimizations.


        • As a general comment, avoid saying using namespace std;, it's not good for you.


        • I don't know the interface of Rcpp::NumericVector, but might you initialize it directly in the spirit of const Rcpp::NumericVector nn(v.cbegin(), v.cend()), for instance?








        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered 8 hours ago









        JuhoJuho

        1,441612




        1,441612






















            Lewkrr is a new contributor. Be nice, and check out our Code of Conduct.










            draft saved

            draft discarded


















            Lewkrr is a new contributor. Be nice, and check out our Code of Conduct.













            Lewkrr is a new contributor. Be nice, and check out our Code of Conduct.












            Lewkrr is a new contributor. Be nice, and check out our Code of Conduct.
















            Thanks for contributing an answer to Code Review Stack Exchange!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            Use MathJax to format equations. MathJax reference.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f216000%2fpassing-uint64-t-from-c-to-r-hilbert-mapping-xy2d-function%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            How to reconfigure Docker Trusted Registry 2.x.x to use CEPH FS mount instead of NFS and other traditional...

            is 'sed' thread safe

            How to make a Squid Proxy server?