Right shift a binary string efficiently in C++











up vote
-1
down vote

favorite












If I have a string that represents an integer in binary form such as



1101101


and I want to circularly right shift it to obtain



1110110


One way I could think of would be converting the string into an int and use (taken from wikipedia)



// https://stackoverflow.com/a/776550/3770260
template <typename INT>
#if __cplusplus > 201100L // Apply constexpr to C++ 11 to ease optimization
constexpr
#endif // See also https://stackoverflow.com/a/7269693/3770260
INT rol(INT val, size_t len) {
#if __cplusplus > 201100L && _wp_force_unsigned_rotate // Apply unsigned check C++ 11 to make sense
static_assert(std::is_unsigned<INT>::value,
"Rotate Left only makes sense for unsigned types");
#endif
return (val << len) | ((unsigned) val >> (-len & (sizeof(INT) * CHAR_BIT - 1)));
}


However, if the string consists of, say, 10^6 char then this does not work as the integer representation exceeds even the range of __int64.



In that case I could think of a solution by looping over the string



//let str be a char string of length n
char temp = str[n - 1];
for(int i = n - 1; i > 0; i--)
{
str[i] = str[i - 1];
}
str[0] = temp;


This solution runs in O(n) due the loop over the length of the string, n. My question is, is there much more efficient way to implement circular shifting for large binary strings?



EDIT



Both input and output are std::strings










share|improve this question




















  • 1




    Ever think of using std::rotate?
    – PaulMcKenzie
    Nov 10 at 0:51










  • Use a std::deque instead of a string if you can. deque has zounds-fast insert and removal from both ends while still allowing iterating and indexing.
    – user4581301
    Nov 10 at 0:52










  • @PaulMcKenzie std::rotate also runs in O(n)
    – iambrj
    Nov 10 at 0:53










  • Just keep a pointer to the first bit. O(1).
    – stark
    Nov 10 at 0:54










  • Do you need contiguous container ? Else a (circular) string + index should do the job.
    – Jarod42
    Nov 10 at 0:55

















up vote
-1
down vote

favorite












If I have a string that represents an integer in binary form such as



1101101


and I want to circularly right shift it to obtain



1110110


One way I could think of would be converting the string into an int and use (taken from wikipedia)



// https://stackoverflow.com/a/776550/3770260
template <typename INT>
#if __cplusplus > 201100L // Apply constexpr to C++ 11 to ease optimization
constexpr
#endif // See also https://stackoverflow.com/a/7269693/3770260
INT rol(INT val, size_t len) {
#if __cplusplus > 201100L && _wp_force_unsigned_rotate // Apply unsigned check C++ 11 to make sense
static_assert(std::is_unsigned<INT>::value,
"Rotate Left only makes sense for unsigned types");
#endif
return (val << len) | ((unsigned) val >> (-len & (sizeof(INT) * CHAR_BIT - 1)));
}


However, if the string consists of, say, 10^6 char then this does not work as the integer representation exceeds even the range of __int64.



In that case I could think of a solution by looping over the string



//let str be a char string of length n
char temp = str[n - 1];
for(int i = n - 1; i > 0; i--)
{
str[i] = str[i - 1];
}
str[0] = temp;


This solution runs in O(n) due the loop over the length of the string, n. My question is, is there much more efficient way to implement circular shifting for large binary strings?



EDIT



Both input and output are std::strings










share|improve this question




















  • 1




    Ever think of using std::rotate?
    – PaulMcKenzie
    Nov 10 at 0:51










  • Use a std::deque instead of a string if you can. deque has zounds-fast insert and removal from both ends while still allowing iterating and indexing.
    – user4581301
    Nov 10 at 0:52










  • @PaulMcKenzie std::rotate also runs in O(n)
    – iambrj
    Nov 10 at 0:53










  • Just keep a pointer to the first bit. O(1).
    – stark
    Nov 10 at 0:54










  • Do you need contiguous container ? Else a (circular) string + index should do the job.
    – Jarod42
    Nov 10 at 0:55















up vote
-1
down vote

favorite









up vote
-1
down vote

favorite











If I have a string that represents an integer in binary form such as



1101101


and I want to circularly right shift it to obtain



1110110


One way I could think of would be converting the string into an int and use (taken from wikipedia)



// https://stackoverflow.com/a/776550/3770260
template <typename INT>
#if __cplusplus > 201100L // Apply constexpr to C++ 11 to ease optimization
constexpr
#endif // See also https://stackoverflow.com/a/7269693/3770260
INT rol(INT val, size_t len) {
#if __cplusplus > 201100L && _wp_force_unsigned_rotate // Apply unsigned check C++ 11 to make sense
static_assert(std::is_unsigned<INT>::value,
"Rotate Left only makes sense for unsigned types");
#endif
return (val << len) | ((unsigned) val >> (-len & (sizeof(INT) * CHAR_BIT - 1)));
}


However, if the string consists of, say, 10^6 char then this does not work as the integer representation exceeds even the range of __int64.



In that case I could think of a solution by looping over the string



//let str be a char string of length n
char temp = str[n - 1];
for(int i = n - 1; i > 0; i--)
{
str[i] = str[i - 1];
}
str[0] = temp;


This solution runs in O(n) due the loop over the length of the string, n. My question is, is there much more efficient way to implement circular shifting for large binary strings?



EDIT



Both input and output are std::strings










share|improve this question















If I have a string that represents an integer in binary form such as



1101101


and I want to circularly right shift it to obtain



1110110


One way I could think of would be converting the string into an int and use (taken from wikipedia)



// https://stackoverflow.com/a/776550/3770260
template <typename INT>
#if __cplusplus > 201100L // Apply constexpr to C++ 11 to ease optimization
constexpr
#endif // See also https://stackoverflow.com/a/7269693/3770260
INT rol(INT val, size_t len) {
#if __cplusplus > 201100L && _wp_force_unsigned_rotate // Apply unsigned check C++ 11 to make sense
static_assert(std::is_unsigned<INT>::value,
"Rotate Left only makes sense for unsigned types");
#endif
return (val << len) | ((unsigned) val >> (-len & (sizeof(INT) * CHAR_BIT - 1)));
}


However, if the string consists of, say, 10^6 char then this does not work as the integer representation exceeds even the range of __int64.



In that case I could think of a solution by looping over the string



//let str be a char string of length n
char temp = str[n - 1];
for(int i = n - 1; i > 0; i--)
{
str[i] = str[i - 1];
}
str[0] = temp;


This solution runs in O(n) due the loop over the length of the string, n. My question is, is there much more efficient way to implement circular shifting for large binary strings?



EDIT



Both input and output are std::strings







c++ runtime bit-shift






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 10 at 1:21

























asked Nov 10 at 0:47









iambrj

1916




1916








  • 1




    Ever think of using std::rotate?
    – PaulMcKenzie
    Nov 10 at 0:51










  • Use a std::deque instead of a string if you can. deque has zounds-fast insert and removal from both ends while still allowing iterating and indexing.
    – user4581301
    Nov 10 at 0:52










  • @PaulMcKenzie std::rotate also runs in O(n)
    – iambrj
    Nov 10 at 0:53










  • Just keep a pointer to the first bit. O(1).
    – stark
    Nov 10 at 0:54










  • Do you need contiguous container ? Else a (circular) string + index should do the job.
    – Jarod42
    Nov 10 at 0:55
















  • 1




    Ever think of using std::rotate?
    – PaulMcKenzie
    Nov 10 at 0:51










  • Use a std::deque instead of a string if you can. deque has zounds-fast insert and removal from both ends while still allowing iterating and indexing.
    – user4581301
    Nov 10 at 0:52










  • @PaulMcKenzie std::rotate also runs in O(n)
    – iambrj
    Nov 10 at 0:53










  • Just keep a pointer to the first bit. O(1).
    – stark
    Nov 10 at 0:54










  • Do you need contiguous container ? Else a (circular) string + index should do the job.
    – Jarod42
    Nov 10 at 0:55










1




1




Ever think of using std::rotate?
– PaulMcKenzie
Nov 10 at 0:51




Ever think of using std::rotate?
– PaulMcKenzie
Nov 10 at 0:51












Use a std::deque instead of a string if you can. deque has zounds-fast insert and removal from both ends while still allowing iterating and indexing.
– user4581301
Nov 10 at 0:52




Use a std::deque instead of a string if you can. deque has zounds-fast insert and removal from both ends while still allowing iterating and indexing.
– user4581301
Nov 10 at 0:52












@PaulMcKenzie std::rotate also runs in O(n)
– iambrj
Nov 10 at 0:53




@PaulMcKenzie std::rotate also runs in O(n)
– iambrj
Nov 10 at 0:53












Just keep a pointer to the first bit. O(1).
– stark
Nov 10 at 0:54




Just keep a pointer to the first bit. O(1).
– stark
Nov 10 at 0:54












Do you need contiguous container ? Else a (circular) string + index should do the job.
– Jarod42
Nov 10 at 0:55






Do you need contiguous container ? Else a (circular) string + index should do the job.
– Jarod42
Nov 10 at 0:55














1 Answer
1






active

oldest

votes

















up vote
0
down vote













You have to move memory one way or another, so your proposed solution is as fast as it gets.



You might also use standard std::string functions:



str.insert(str.begin(), str[n - 1]);
str.erase(str.end() - 1);


or memmove, or memcpy (I don't actually recommend this, it's for an argument)



char temp = str[n - 1];
memmove(str.data() + 1, str.data(), n - 1);
str[0] = temp;


Note that memmove may look faster, but it's essentially the same thing as your loop. It is moving bytes one by one, it's just encapsulated in a different function. This method might be faster for much larger data blocks, of size 1000 bytes or more, since the CPU is optimized to move large chunks of memory. But you won't be able to measure any difference for 10 or 20 bytes.



Moreover, the compiler will most likely run additional optimizations when it sees your for loop, it realizes that you are moving memory and chooses the best option.



The compiler is also good at dealing with std::string methods. These are common operations and the compiler knows the best way to handle it.






share|improve this answer























    Your Answer






    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: "1"
    };
    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',
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    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
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53235032%2fright-shift-a-binary-string-efficiently-in-c%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








    up vote
    0
    down vote













    You have to move memory one way or another, so your proposed solution is as fast as it gets.



    You might also use standard std::string functions:



    str.insert(str.begin(), str[n - 1]);
    str.erase(str.end() - 1);


    or memmove, or memcpy (I don't actually recommend this, it's for an argument)



    char temp = str[n - 1];
    memmove(str.data() + 1, str.data(), n - 1);
    str[0] = temp;


    Note that memmove may look faster, but it's essentially the same thing as your loop. It is moving bytes one by one, it's just encapsulated in a different function. This method might be faster for much larger data blocks, of size 1000 bytes or more, since the CPU is optimized to move large chunks of memory. But you won't be able to measure any difference for 10 or 20 bytes.



    Moreover, the compiler will most likely run additional optimizations when it sees your for loop, it realizes that you are moving memory and chooses the best option.



    The compiler is also good at dealing with std::string methods. These are common operations and the compiler knows the best way to handle it.






    share|improve this answer



























      up vote
      0
      down vote













      You have to move memory one way or another, so your proposed solution is as fast as it gets.



      You might also use standard std::string functions:



      str.insert(str.begin(), str[n - 1]);
      str.erase(str.end() - 1);


      or memmove, or memcpy (I don't actually recommend this, it's for an argument)



      char temp = str[n - 1];
      memmove(str.data() + 1, str.data(), n - 1);
      str[0] = temp;


      Note that memmove may look faster, but it's essentially the same thing as your loop. It is moving bytes one by one, it's just encapsulated in a different function. This method might be faster for much larger data blocks, of size 1000 bytes or more, since the CPU is optimized to move large chunks of memory. But you won't be able to measure any difference for 10 or 20 bytes.



      Moreover, the compiler will most likely run additional optimizations when it sees your for loop, it realizes that you are moving memory and chooses the best option.



      The compiler is also good at dealing with std::string methods. These are common operations and the compiler knows the best way to handle it.






      share|improve this answer

























        up vote
        0
        down vote










        up vote
        0
        down vote









        You have to move memory one way or another, so your proposed solution is as fast as it gets.



        You might also use standard std::string functions:



        str.insert(str.begin(), str[n - 1]);
        str.erase(str.end() - 1);


        or memmove, or memcpy (I don't actually recommend this, it's for an argument)



        char temp = str[n - 1];
        memmove(str.data() + 1, str.data(), n - 1);
        str[0] = temp;


        Note that memmove may look faster, but it's essentially the same thing as your loop. It is moving bytes one by one, it's just encapsulated in a different function. This method might be faster for much larger data blocks, of size 1000 bytes or more, since the CPU is optimized to move large chunks of memory. But you won't be able to measure any difference for 10 or 20 bytes.



        Moreover, the compiler will most likely run additional optimizations when it sees your for loop, it realizes that you are moving memory and chooses the best option.



        The compiler is also good at dealing with std::string methods. These are common operations and the compiler knows the best way to handle it.






        share|improve this answer














        You have to move memory one way or another, so your proposed solution is as fast as it gets.



        You might also use standard std::string functions:



        str.insert(str.begin(), str[n - 1]);
        str.erase(str.end() - 1);


        or memmove, or memcpy (I don't actually recommend this, it's for an argument)



        char temp = str[n - 1];
        memmove(str.data() + 1, str.data(), n - 1);
        str[0] = temp;


        Note that memmove may look faster, but it's essentially the same thing as your loop. It is moving bytes one by one, it's just encapsulated in a different function. This method might be faster for much larger data blocks, of size 1000 bytes or more, since the CPU is optimized to move large chunks of memory. But you won't be able to measure any difference for 10 or 20 bytes.



        Moreover, the compiler will most likely run additional optimizations when it sees your for loop, it realizes that you are moving memory and chooses the best option.



        The compiler is also good at dealing with std::string methods. These are common operations and the compiler knows the best way to handle it.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Nov 10 at 7:41

























        answered Nov 10 at 7:00









        Barmak Shemirani

        20.3k42044




        20.3k42044






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • 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.


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





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • 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.


            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%2fstackoverflow.com%2fquestions%2f53235032%2fright-shift-a-binary-string-efficiently-in-c%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

            Schultheiß

            Verwaltungsgliederung Dänemarks

            Liste der Kulturdenkmale in Wilsdruff