From ba3f12c93f7718db89399c0cda567d6798714fd8 Mon Sep 17 00:00:00 2001 From: Xiang Xiao Date: Mon, 21 Sep 2020 16:34:16 +0800 Subject: [PATCH] libc: Implement popcount/popcountl/popcountll specified here: https://www.unix.com/man-page/netbsd/3/popcountll/ Signed-off-by: Xiang Xiao --- include/nuttx/compiler.h | 5 +-- include/strings.h | 4 +++ libs/libc/string/Make.defs | 1 + libs/libc/string/lib_popcount.c | 55 +++++++++++++++++++++++++++++++ libs/libc/string/lib_popcountl.c | 55 +++++++++++++++++++++++++++++++ libs/libc/string/lib_popcountll.c | 55 +++++++++++++++++++++++++++++++ 6 files changed, 173 insertions(+), 2 deletions(-) create mode 100644 libs/libc/string/lib_popcount.c create mode 100644 libs/libc/string/lib_popcountl.c create mode 100644 libs/libc/string/lib_popcountll.c diff --git a/include/nuttx/compiler.h b/include/nuttx/compiler.h index 0be441ed62..6bb2e6c990 100644 --- a/include/nuttx/compiler.h +++ b/include/nuttx/compiler.h @@ -60,8 +60,9 @@ */ #if __GNUC__ >= 4 -# define CONFIG_HAVE_BUILTIN_CTZ 1 -# define CONFIG_HAVE_BUILTIN_CLZ 1 +# define CONFIG_HAVE_BUILTIN_CTZ 1 +# define CONFIG_HAVE_BUILTIN_CLZ 1 +# define CONFIG_HAVE_BUILTIN_POPCOUNT 1 #endif /* C++ support */ diff --git a/include/strings.h b/include/strings.h index 21b519cbde..1754356923 100644 --- a/include/strings.h +++ b/include/strings.h @@ -89,6 +89,10 @@ int flsl(long j); int flsll(long long j); #endif +unsigned int popcount(unsigned int j); +unsigned int popcountl(unsigned long j); +unsigned int popcountll(unsigned long long j); + FAR char *index(FAR const char *s, int c); FAR char *rindex(FAR const char *s, int c); diff --git a/libs/libc/string/Make.defs b/libs/libc/string/Make.defs index db9978a056..a40ce7215f 100644 --- a/libs/libc/string/Make.defs +++ b/libs/libc/string/Make.defs @@ -39,6 +39,7 @@ CSRCS += lib_ffs.c lib_ffsl.c lib_ffsll.c lib_fls.c lib_flsl.c CSRCS += lib_flsll.c lib_isbasedigit.c lib_memset.c lib_memchr.c CSRCS += lib_memccpy.c lib_memcmp.c lib_memmove.c lib_memrchr.c +CSRCS += lib_popcount.c lib_popcountl.c lib_popcountll.c CSRCS += lib_skipspace.c lib_stpcpy.c lib_stpncpy.c lib_strcasecmp.c CSRCS += lib_strcat.c lib_strchr.c lib_strcpy.c lib_strcmp.c lib_strcspn.c CSRCS += lib_strdup.c lib_strerror.c lib_strlen.c lib_strnlen.c diff --git a/libs/libc/string/lib_popcount.c b/libs/libc/string/lib_popcount.c new file mode 100644 index 0000000000..6988a45256 --- /dev/null +++ b/libs/libc/string/lib_popcount.c @@ -0,0 +1,55 @@ +/**************************************************************************** + * libs/libc/string/lib_popcount.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: popcount + ****************************************************************************/ + +unsigned int popcount(unsigned int j) +{ +#ifdef CONFIG_HAVE_BUILTIN_POPCOUNT + return __builtin_popcount(j); +#else + unsigned int count = 0; + + while (j > 0) + { + if ((j & 1) == 1) + { + count++; + } + + j >>= 1; + } + + return count; +#endif +} diff --git a/libs/libc/string/lib_popcountl.c b/libs/libc/string/lib_popcountl.c new file mode 100644 index 0000000000..027f4af88b --- /dev/null +++ b/libs/libc/string/lib_popcountl.c @@ -0,0 +1,55 @@ +/**************************************************************************** + * libs/libc/string/lib_popcountl.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: popcount + ****************************************************************************/ + +unsigned int popcountl(unsigned long j) +{ +#ifdef CONFIG_HAVE_BUILTIN_POPCOUNT + return __builtin_popcountl(j); +#else + unsigned int count = 0; + + while (j > 0) + { + if ((j & 1) == 1) + { + count++; + } + + j >>= 1; + } + + return count; +#endif +} diff --git a/libs/libc/string/lib_popcountll.c b/libs/libc/string/lib_popcountll.c new file mode 100644 index 0000000000..0854df4b76 --- /dev/null +++ b/libs/libc/string/lib_popcountll.c @@ -0,0 +1,55 @@ +/**************************************************************************** + * libs/libc/string/lib_popcountll.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: popcount + ****************************************************************************/ + +unsigned int popcountll(unsigned long long j) +{ +#ifdef CONFIG_HAVE_BUILTIN_POPCOUNT + return __builtin_popcountll(j); +#else + unsigned int count = 0; + + while (j > 0) + { + if ((j & 1) == 1) + { + count++; + } + + j >>= 1; + } + + return count; +#endif +}