1

Could you pls help me in this type of task.Actually I dont understand what I should provide as an answer
A given bit vector has length n. It is known that the vector can contain only two ones. A combinational system needs to calculate the distance between the ones. For example, in vector "10100" the distance is 2. Give the high-level specification.

Kooss
  • 71
  • 1
  • 1
  • 8
  • just look at the bit vector and count ;). Seriously, would you mind to specify a language? – Serge Sep 08 '16 at 19:24
  • Yes I know how to count))but if the length of the vector is n.how to give high level specification? – Kooss Sep 08 '16 at 19:26
  • for example: "it's a number of consecutive zero bits bounded by non-zero bits plus one" – Serge Sep 08 '16 at 19:28
  • ok,so I can say that.if you want to calculate distance between ones in the vector with n length,I need to .............your comment little bit unclear for me – Kooss Sep 08 '16 at 19:34
  • "... you need to count the number of consecutive zero bits between non-zero bits and add one" – Serge Sep 08 '16 at 19:36

1 Answers1

0

When google turned up this SO question for me, I was pretty excited. I was hoping there'd be some code here I could repurpose. Alas, the OP's question was too abstract for a concrete solution to get proposed.

Still, for the next guy, here's at least /a/ solution, designed for MSVC x64:

#include <intrin.h> // __lzcnt64 & _BitScanForward64
#include <stdint.h>
#include <stdio.h>
#include <assert.h>

/// <summary>
/// Given a pointer to an array of bits, prints out the distance between the bits.
/// </summary>
/// <param name="pBits">Pointer to the bits</param>
/// <param name="len">Length of the array in bytes</param>
/// <param name="carry">Previous value of carry</param>
/// <returns>Final carry</returns>
/// <remarks>Reading right to left, a bit pattern of 11100101 (aka 0xE5) will print 1, 2, 3, 1, 1</remarks>
uint64_t CountBitDistance(const uint8_t* pBits, const size_t len, uint64_t carry = 0)
{
    // Assumes len divides evenly by 8.  Depending on the platform,
    // pBits might also need to be 8 byte aligned.  Left as an exercise.
    assert((len % 8) == 0);

    const uint64_t* pUll = (const uint64_t*)pBits;

    for (size_t x = 0; x < len / 8; pUll++, x++)
    {
        uint64_t ull = *pUll;

        // Grab the value before we start modifying ull
        const uint64_t newcarry = __lzcnt64(ull);

        unsigned long res = 0;

        // Returns false when ull is zero.  res is zero based.
        while (_BitScanForward64(&res, ull))
        {
            // Tempting though it might be, you can't just increment res and 
            // do both shifts at once.  If the only bit set is the most 
            // significant one, adding 1 gives you 64.  Shifting a 64bit value 
            // by 64 is undefined behavior in C.  On x64 for example, it does 
            // nothing.  If you are *sure* that res will never be 63, or if 
            // you are on a platform that handles shifts > 63 differently (and 
            // don't need a portable solution), you could combine them and 
            // increase perf (by a tiny amount).
            
            // So, first get rid of the zeros...
            ull >>= res;

            // ... then turn off the bit we just found.
            ull >>= 1;

            // If we found a bit at position 0, we want to report 1.  
            res++;

            // And apply any carry in from the previous ull.
            const uint64_t d = carry + res;

            // Carry in applied.
            carry = 0;

            printf("%llu\n", d);
        }

        // Remember that we might not go into the loop above at all, so carry
        // won't necessarily be zero.
        carry += newcarry;
    }

    // Useful if the source of our bits is continuing to produce data.  We may
    // need the final value from the previous batch to apply to the next.
    return carry;
}

int main()
{
    constexpr const uint8_t bits[] = {
        0xAA, 0x25, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x80, 0x25, 0x42, 0x10, 0x08, 0x08, 0x10, 0x40, 0x00,
        0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0xAA, 0x25, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x80, 0x25, 0x42, 0x10, 0x08, 0x08, 0x10, 0x40, 0x00,
    };

    constexpr const uint8_t bits2[] = { 0x2, 0, 0, 0, 0, 0, 0, 0 };

    uint64_t t1 = CountBitDistance(bits, sizeof(bits));
    printf("t1: %llu\n\n", t1);

    uint64_t t2 = CountBitDistance(bits2, sizeof(bits2), t1);

    printf("t2: %llu\n", t2);
}

No doubt someone else will pop up with a drastically better solution using some clever bit twiddling hacks. Still, at least now there's something.

David Wohlferd
  • 7,110
  • 2
  • 29
  • 56