0

1, It is a pity that memset(void* dst, int value, size_t size) fools a lot of people when they first use this function! 2nd parameter "int value" should be "uchar value" to describe the real operation inside. Don't misunderstand me, I am asking a memset-like function!

2, I know there are some c++ candy function like std::fill_n(my_array, array_length, constant_value); even a pure c function in OS X: memset_pattern4(grid, &pattern, sizeof grid); mentioned in a perfect thread Why is memset() incorrectly initializing int?.

So, is there a similar c function in runtime library of visual studio like memset_pattern4()?

3, for somebody asked why i wouldn't use a for-loop to set integer by integer. here is my answer: memset turns to a better performance when setting big trunk(10K?) of memory at least in x86.

http://www.gamedev.net/topic/472631-performance-of-memset/page-2 gives more discussion, although without a conclusion(I doubt there will be).

4, said function can be used to simplify counting sort by avoiding useless Fibonacci accumulation. Original:

for (int i = 0; i < SRC_ARRY_SIZE; i++)
    counter_arry[src_arry[i]]++; 

for (int i = SRC_LOW_BOUND; i < SRC_HI_BOUND; i++)//forward fabnacci??
    counter_arry[i+1] += counter_arry[i];

for (int i = 0; i < SRC_ARRY_SIZE; i++) 
{   
    value = src_arry[i];
    map = --counter_arry[value];//then counter down!
    temp[map] = value;
}

Expected:

for (int i = 0; i < SRC_ARRY_SIZE; i++)
    counter_arry[src_arry[i]]++; 

for (int i = SRC_LOW_BOUND; i < SRC_HI_BOUND+1; i++)//forward fabnacci??
{           
    memset_4(cur_ptr,i, counter_arry[i]);
    cur_ptr += counter_arry[i];
}

Thanks for your kindly review and reply!

Community
  • 1
  • 1
Match Man
  • 11
  • 2
  • To help us: why do you want this? Remember .NET (outside `unsafe` blocks) does not allow any uninitialised values. – Richard Aug 26 '14 at 07:05
  • In my counting sort program, I want said function to speed up the memory remapping work - refer my revised question. I am working in a pure c computation environment without bounding any .NET service package. – Match Man Aug 26 '14 at 07:23
  • See here: http://stackoverflow.com/questions/18823493/beating-or-meeting-os-x-memset-and-memset-pattern4 for an analysis of how `memset_pattern4()` is implemented on OS X. – Michael Burr Aug 26 '14 at 07:42
  • Maybe write a macro wrapper that calls the platform's `memset_pattern4()` where it exists and calls your own implementation in other cases. Start with a naive implementation and improve/optimize as necessary or desired. – Michael Burr Aug 26 '14 at 07:50
  • Michael, Thanks! Here I simply want an already implemented function by MSVC or some other genius guy. DIY this function is kinda far from my original expectation. – Match Man Aug 26 '14 at 07:57

1 Answers1

0

Here's an implementation of memset_pattern4() that you might find useful. It's nothing like Darwin's SSE assembly language version, except that it has the same interface.

#include <string.h>
#include <stdint.h>

/*

A portable implementation of the Darwin memset_patternX() family of functions:

These are analogous to memset(), except that they fill memory with a replicated
pattern either 4, 8, or 16 bytes long.  b points to a buffer of size len bytes
which is to be filled.  The second parameter points to the pattern.  If the
buffer length is not an even multiple of the pattern length, the last instance
of the pattern will be truncated.  Neither the buffer nor the pattern pointer
need be aligned.

*/

/*
alignment utility macros stolen from Linux
see https://lkml.org/lkml/2006/11/25/2 for a discussion of why typeof() is used
*/

#if !_MSC_VER

       #define __ALIGN_KERNEL(x, a)            __ALIGN_KERNEL_MASK(x, (typeof(x))(a) - 1)
       #define __ALIGN_KERNEL_MASK(x, mask)    (((x) + (mask)) & ~(mask))

       #define ALIGN(x, a)             __ALIGN_KERNEL((x), (a))
       #define __ALIGN_MASK(x, mask)   __ALIGN_KERNEL_MASK((x), (mask))
       #define PTR_ALIGN(p, a)         ((typeof(p))ALIGN((uintptr_t)(p), (a)))
       #define IS_ALIGNED(x, a)        (((x) & ((typeof(x))(a) - 1)) == 0)

       #define IS_PTR_ALIGNED(p, a)      (IS_ALIGNED((uintptr_t)(p), (a)))
#else
       /* MS friendly versions */

       /* taken from the DDK's fltKernel.h header */
       #define IS_ALIGNED(_pointer, _alignment)                        \
                     ((((uintptr_t) (_pointer)) & ((_alignment) - 1)) == 0)

       #define ROUND_TO_SIZE(_length, _alignment)                      \
                           ((((uintptr_t)(_length)) + ((_alignment)-1)) & ~(uintptr_t) ((_alignment) - 1))

       #define __ALIGN_KERNEL(x, a)    ROUND_TO_SIZE( (x), (a))
       #define ALIGN(x, a)             __ALIGN_KERNEL((x), (a))
       #define PTR_ALIGN(p, a)         ALIGN((p), (a))

       #define IS_PTR_ALIGNED(p, a)      (IS_ALIGNED((uintptr_t)(p), (a)))
#endif



void nx_memset_pattern4(void *b, const void *pattern4, size_t len)
{
       enum { pattern_len = 4 };

       unsigned char* dst = (unsigned char*) b;
       unsigned const char* src = (unsigned const char*) pattern4;

       if (IS_PTR_ALIGNED( dst, pattern_len) && IS_PTR_ALIGNED( src, pattern_len)) {
              /* handle aligned moves */
              uint32_t val = *((uint32_t*)src);
              uint32_t* word_dst = (uint32_t*) dst;

              size_t word_count = len / pattern_len;
              dst += word_count * pattern_len;
              len -= word_count * pattern_len;

              for (; word_count != 0; --word_count) {
                     *word_dst++ = val;
              }
       }
       else {
              while (pattern_len <= len) {
                     memcpy(dst, src, pattern_len);
                     dst += pattern_len;
                     len -= pattern_len;
              }
       }

       memcpy( dst, src, len);
}
Michael Burr
  • 333,147
  • 50
  • 533
  • 760