Skip to content
/ memcnt Public

A C function that computes the number of characters equal to a value in a buffer

License

Notifications You must be signed in to change notification settings

hisahi/memcnt

Repository files navigation

memcnt is a C function (or function compatible with and usable from C code)
with the following signature:

    size_t memcnt(const void *s, int c, size_t n);

which returns the number of bytes (characters) equal to c (converted to an
unsigned char) in the initial n characters in an array pointed to by s. The
values in the array will be interpreted as unsigned chars and compared to c.

The function is undefined if s is a null pointer and n is non-zero, or if n
is larger than the number of unsigned chars in the array pointed to by s.

The type size_t is as defined by <stddef.h>.

A correct memcnt implementation is:

    size_t memcnt(const void *s, int c, size_t n) {
        size_t i, count = 0;
        const unsigned char *p = (const unsigned char *)s, v = (unsigned char)c;
        for (i = 0; i < n; ++i)
            if (p[i] == v)
                ++count;
        return count;
    }

Any implementation of memcnt shall return the same value as the above function
with the same parameters, unless the function is undefined due to one or more
of the aforementioned conditions.

memcnt shall return zero if n is zero regardless of the values of s and c.

This repository contains implementations of memcnt, including optimized
implementations for various architectures. See LICENSE for the license of these
implementations (the prototype and concept of memcnt are in the public domain).
memcnt is designed to work on any compiler that supports at least the first
ISO C standard (C89), but provide optimized implementations if supported.

Only single-core, CPU-only implementations are included. Multi-core or GPU
implementations will probably get their own repository at some point.

The implementations for memcnt were originally split from an experimental
version of lrg <https://github.com/hisahi/lrg>.

The intended use of this library is to link it statically into programs, but
dynamic linking is also possible. memcnt.c is a source file that automatically
includes the correct implementation(s). If you want to choose manually, do
the following:

1.  Define MEMCNT_NAMED as 0 if you are only compiling one implementation
    (which will then be called memcnt) or as 1 if you want to compile multiple
    implementations (which will be named starting with memcnt_). If you do the
    latter, you must provide your own dispatch function as memcnt to choose
    which one to use. By default, MEMCNT_NAMED will be set to 0.
2.  Make sure you have memcnt-impl.h. (This file is used by the memcnt
    implementations and should not be included by other code.)
3.  Select one or more of the .c files (one implementation per file) and compile
    into your program or library.

If your tools do not support the above process, you can skip all of the above
steps by using memcnt-strict.c(/.h). It is however only a basic implementation
with no optimizations.

test-memcnt.c is a test program for testing memcnt implementations and is not
needed for use in other programs.

If you want to build an universal binary (or a "fat binary"), the following
information may prove useful for you.

If MEMCNT_DYNAMIC=1 is defined for memcnt.c, a dynamic dispatcher is used for
memcnt if supported for your compiler. This allows compiling multiple
implementations in the same binary and picking the fastest supported
implementation during runtime. By default, the implementation picked during
compile time is used, and that implementation may result in an error if
executed on a platform that does not support the instruction set the
implementation uses.

With dynamic dispatching, you must call memcnt_optimize(), after which memcnt()
will use the fastest implementation available on the platform. memcnt MUST NOT
be called while memcnt_optimize is running, and memcnt_optimize likewise MUST
not itself be called again while running (it is not reentrant nor concurrent).
It is recommended to place a memcnt_optimize call as one of the first things
to do in main(); it is not a very slow function.

The dynamic dispatcher should only be used if you are statically linking your
program and want it to be a "universal" (or "fat") binary that works on a
variety of CPUs of the same architecture. If you are statically linking for one
architecture only, you don't need the dynamic dispatcher. The same applies if
you want to build a dynamically linkable ("shared") memcnt library -- you
probably don't need your library binary to work on a variety of CPUs, but if you
do, you SHOULD figure out a way to call memcnt_optimize() yourself when the
library is loaded/linked (such as by using DllMain on Win32). Define
MEMCNT_DYNALINK to 1 if building a dynamic/shared library to help with this.
(Also, look into memcnt.h and how to define PUBLIC.)

memcnt_optimize may be safely called even if the dynamic dispatcher is not
compiled in, but will do nothing in that case. Calling memcnt_optimize again
will likewise do nothing if it has already been run. The exception is if you
use -strict.c/.h -- memcnt_optimize does not exist at all for them.

TL:DR; don't worry about calling memcnt_optimize() unless you want *the program
YOU are writing* to work on other variants of the CPU you're writing it on
WITHOUT any need to compile the program separately for that CPU (such as if
you're writing on an x86 CPU that supports AVX2 but the BINARY YOU COMPILE
should also work on ones that don't.) If your program relies on dynamically
linking a memcnt library, you don't need memcnt_optimize either (the library
should call it for you).

TL:DR for TL:DR; Almost always you can run memcnt() directly just fine without
having to do anything else. Pretend you never heard of memcnt_optimize().

If you want to use a dynamic link library for memcnt in your program, you only
need memcnt.h, and you should define MEMCNT_IMPORT in that case.

About

A C function that computes the number of characters equal to a value in a buffer

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published