1*5ceeb040Sjruoho /* $NetBSD: t_bitops.c,v 1.3 2011/03/24 07:37:04 jruoho Exp $ */ 2acf13bc7Sjruoho 3acf13bc7Sjruoho /*- 4acf13bc7Sjruoho * Copyright (c) 2011 The NetBSD Foundation, Inc. 5acf13bc7Sjruoho * All rights reserved. 6acf13bc7Sjruoho * 7acf13bc7Sjruoho * This code is derived from software contributed to The NetBSD Foundation 8acf13bc7Sjruoho * by Jukka Ruohonen. 9acf13bc7Sjruoho * 10acf13bc7Sjruoho * Redistribution and use in source and binary forms, with or without 11acf13bc7Sjruoho * modification, are permitted provided that the following conditions 12acf13bc7Sjruoho * are met: 13acf13bc7Sjruoho * 1. Redistributions of source code must retain the above copyright 14acf13bc7Sjruoho * notice, this list of conditions and the following disclaimer. 15acf13bc7Sjruoho * 2. Redistributions in binary form must reproduce the above copyright 16acf13bc7Sjruoho * notice, this list of conditions and the following disclaimer in the 17acf13bc7Sjruoho * documentation and/or other materials provided with the distribution. 18acf13bc7Sjruoho * 19acf13bc7Sjruoho * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20acf13bc7Sjruoho * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21acf13bc7Sjruoho * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22acf13bc7Sjruoho * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23acf13bc7Sjruoho * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24acf13bc7Sjruoho * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25acf13bc7Sjruoho * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26acf13bc7Sjruoho * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27acf13bc7Sjruoho * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28acf13bc7Sjruoho * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29acf13bc7Sjruoho * POSSIBILITY OF SUCH DAMAGE. 30acf13bc7Sjruoho */ 31acf13bc7Sjruoho 32acf13bc7Sjruoho #include <atf-c.h> 33acf13bc7Sjruoho 3456d0179bSjruoho #include <sys/cdefs.h> 35acf13bc7Sjruoho #include <sys/bitops.h> 3656d0179bSjruoho 37acf13bc7Sjruoho #include <math.h> 38acf13bc7Sjruoho 3956d0179bSjruoho static const struct { 4056d0179bSjruoho uint32_t val; 4156d0179bSjruoho int ffs; 4256d0179bSjruoho int fls; 4356d0179bSjruoho } bits[] = { 4456d0179bSjruoho 4556d0179bSjruoho { 0x00, 0, 0 }, { 0x01, 1, 1 }, { 0x02, 2, 2 }, { 0x03, 1, 2 }, 4656d0179bSjruoho { 0x04, 3, 3 }, { 0x05, 1, 3 }, { 0x06, 2, 3 }, { 0x07, 1, 3 }, 4756d0179bSjruoho { 0x08, 4, 4 }, { 0x09, 1, 4 }, { 0x0A, 2, 4 }, { 0x0B, 1, 4 }, 4856d0179bSjruoho { 0x0C, 3, 4 }, { 0x0D, 1, 4 }, { 0x0E, 2, 4 }, { 0x0F, 1, 4 }, 4956d0179bSjruoho 5056d0179bSjruoho { 0x10, 5, 5 }, { 0x11, 1, 5 }, { 0x12, 2, 5 }, { 0x13, 1, 5 }, 5156d0179bSjruoho { 0x14, 3, 5 }, { 0x15, 1, 5 }, { 0x16, 2, 5 }, { 0x17, 1, 5 }, 5256d0179bSjruoho { 0x18, 4, 5 }, { 0x19, 1, 5 }, { 0x1A, 2, 5 }, { 0x1B, 1, 5 }, 5356d0179bSjruoho { 0x1C, 3, 5 }, { 0x1D, 1, 5 }, { 0x1E, 2, 5 }, { 0x1F, 1, 5 }, 5456d0179bSjruoho 5556d0179bSjruoho { 0xF0, 5, 8 }, { 0xF1, 1, 8 }, { 0xF2, 2, 8 }, { 0xF3, 1, 8 }, 5656d0179bSjruoho { 0xF4, 3, 8 }, { 0xF5, 1, 8 }, { 0xF6, 2, 8 }, { 0xF7, 1, 8 }, 5756d0179bSjruoho { 0xF8, 4, 8 }, { 0xF9, 1, 8 }, { 0xFA, 2, 8 }, { 0xFB, 1, 8 }, 5856d0179bSjruoho { 0xFC, 3, 8 }, { 0xFD, 1, 8 }, { 0xFE, 2, 8 }, { 0xFF, 1, 8 }, 5956d0179bSjruoho 6056d0179bSjruoho }; 6156d0179bSjruoho 62*5ceeb040Sjruoho ATF_TC(fast_divide32); 63*5ceeb040Sjruoho ATF_TC_HEAD(fast_divide32, tc) 64*5ceeb040Sjruoho { 65*5ceeb040Sjruoho atf_tc_set_md_var(tc, "descr", "A basic test of fast_divide32(3)"); 66*5ceeb040Sjruoho } 67*5ceeb040Sjruoho 68*5ceeb040Sjruoho ATF_TC_BODY(fast_divide32, tc) 69*5ceeb040Sjruoho { 70*5ceeb040Sjruoho uint32_t a, b, q, r, m; 71*5ceeb040Sjruoho uint8_t i, s1, s2; 72*5ceeb040Sjruoho 73*5ceeb040Sjruoho a = 0xFFFF; 74*5ceeb040Sjruoho b = 0x000F; 75*5ceeb040Sjruoho 76*5ceeb040Sjruoho fast_divide32_prepare(b, &m, &s1, &s2); 77*5ceeb040Sjruoho 78*5ceeb040Sjruoho q = fast_divide32(a, b, m, s1, s2); 79*5ceeb040Sjruoho r = fast_remainder32(a, b, m, s1, s2); 80*5ceeb040Sjruoho 81*5ceeb040Sjruoho ATF_REQUIRE(q == 0x1111 && r == 0); 82*5ceeb040Sjruoho 83*5ceeb040Sjruoho for (i = 1; i < __arraycount(bits); i++) { 84*5ceeb040Sjruoho 85*5ceeb040Sjruoho a = bits[i].val; 86*5ceeb040Sjruoho b = bits[i].ffs; 87*5ceeb040Sjruoho 88*5ceeb040Sjruoho fast_divide32_prepare(b, &m, &s1, &s2); 89*5ceeb040Sjruoho 90*5ceeb040Sjruoho q = fast_divide32(a, b, m, s1, s2); 91*5ceeb040Sjruoho r = fast_remainder32(a, b, m, s1, s2); 92*5ceeb040Sjruoho 93*5ceeb040Sjruoho ATF_REQUIRE(q == a / b); 94*5ceeb040Sjruoho ATF_REQUIRE(r == a % b); 95*5ceeb040Sjruoho } 96*5ceeb040Sjruoho } 97*5ceeb040Sjruoho 9856d0179bSjruoho ATF_TC(ffsfls); 9956d0179bSjruoho ATF_TC_HEAD(ffsfls, tc) 10056d0179bSjruoho { 10156d0179bSjruoho atf_tc_set_md_var(tc, "descr", "Test ffs32(3)-family for correctness"); 10256d0179bSjruoho } 10356d0179bSjruoho 10456d0179bSjruoho ATF_TC_BODY(ffsfls, tc) 10556d0179bSjruoho { 10656d0179bSjruoho uint8_t i; 10756d0179bSjruoho 10856d0179bSjruoho ATF_REQUIRE(ffs32(0) == 0x00); 10956d0179bSjruoho ATF_REQUIRE(fls32(0) == 0x00); 11056d0179bSjruoho ATF_REQUIRE(ffs64(0) == 0x00); 11156d0179bSjruoho ATF_REQUIRE(fls64(0) == 0x00); 11256d0179bSjruoho 11356d0179bSjruoho ATF_REQUIRE(ffs32(UINT32_MAX) == 0x01); 11456d0179bSjruoho ATF_REQUIRE(fls32(UINT32_MAX) == 0x20); 11556d0179bSjruoho ATF_REQUIRE(ffs64(UINT64_MAX) == 0x01); 11656d0179bSjruoho ATF_REQUIRE(fls64(UINT64_MAX) == 0x40); 11756d0179bSjruoho 11856d0179bSjruoho for (i = 1; i < __arraycount(bits); i++) { 11956d0179bSjruoho 12056d0179bSjruoho ATF_REQUIRE(ffs32(bits[i].val) == bits[i].ffs); 12156d0179bSjruoho ATF_REQUIRE(fls32(bits[i].val) == bits[i].fls); 12256d0179bSjruoho ATF_REQUIRE(ffs64(bits[i].val) == bits[i].ffs); 12356d0179bSjruoho ATF_REQUIRE(fls64(bits[i].val) == bits[i].fls); 12456d0179bSjruoho 12556d0179bSjruoho ATF_REQUIRE(ffs32(bits[i].val << 1) == bits[i].ffs + 1); 12656d0179bSjruoho ATF_REQUIRE(fls32(bits[i].val << 1) == bits[i].fls + 1); 12756d0179bSjruoho ATF_REQUIRE(ffs64(bits[i].val << 1) == bits[i].ffs + 1); 12856d0179bSjruoho ATF_REQUIRE(fls64(bits[i].val << 1) == bits[i].fls + 1); 12956d0179bSjruoho 13056d0179bSjruoho ATF_REQUIRE(ffs32(bits[i].val << 9) == bits[i].ffs + 9); 13156d0179bSjruoho ATF_REQUIRE(fls32(bits[i].val << 9) == bits[i].fls + 9); 13256d0179bSjruoho ATF_REQUIRE(ffs64(bits[i].val << 9) == bits[i].ffs + 9); 13356d0179bSjruoho ATF_REQUIRE(fls64(bits[i].val << 9) == bits[i].fls + 9); 13456d0179bSjruoho } 13556d0179bSjruoho } 13656d0179bSjruoho 137acf13bc7Sjruoho ATF_TC(ilog2_1); 138acf13bc7Sjruoho ATF_TC_HEAD(ilog2_1, tc) 139acf13bc7Sjruoho { 140acf13bc7Sjruoho atf_tc_set_md_var(tc, "descr", "Test ilog2(3) for correctness"); 141acf13bc7Sjruoho } 142acf13bc7Sjruoho 143acf13bc7Sjruoho ATF_TC_BODY(ilog2_1, tc) 144acf13bc7Sjruoho { 145acf13bc7Sjruoho uint64_t i, x; 146acf13bc7Sjruoho 147acf13bc7Sjruoho for (i = x = 0; i < 64; i++) { 148acf13bc7Sjruoho 149acf13bc7Sjruoho x = (uint64_t)1 << i; 150acf13bc7Sjruoho 151acf13bc7Sjruoho ATF_REQUIRE(i == (uint64_t)ilog2(x)); 152acf13bc7Sjruoho } 153acf13bc7Sjruoho } 154acf13bc7Sjruoho 155acf13bc7Sjruoho ATF_TC(ilog2_2); 156acf13bc7Sjruoho ATF_TC_HEAD(ilog2_2, tc) 157acf13bc7Sjruoho { 158acf13bc7Sjruoho atf_tc_set_md_var(tc, "descr", "Test log2(3) vs. ilog2(3)"); 159acf13bc7Sjruoho } 160acf13bc7Sjruoho 161acf13bc7Sjruoho ATF_TC_BODY(ilog2_2, tc) 162acf13bc7Sjruoho { 163acf13bc7Sjruoho double x, y; 164acf13bc7Sjruoho uint64_t i; 165acf13bc7Sjruoho 166acf13bc7Sjruoho for (i = 1; i < UINT32_MAX; i += UINT16_MAX) { 167acf13bc7Sjruoho 168acf13bc7Sjruoho x = log2(i); 169acf13bc7Sjruoho y = (double)(ilog2(i)); 170acf13bc7Sjruoho 171acf13bc7Sjruoho ATF_REQUIRE(ceil(x) >= y); 172acf13bc7Sjruoho ATF_REQUIRE(fabs(floor(x) - y) < 1.0e-40); 173acf13bc7Sjruoho } 174acf13bc7Sjruoho } 175acf13bc7Sjruoho 176acf13bc7Sjruoho ATF_TP_ADD_TCS(tp) 177acf13bc7Sjruoho { 178acf13bc7Sjruoho 179*5ceeb040Sjruoho ATF_TP_ADD_TC(tp, fast_divide32); 18056d0179bSjruoho ATF_TP_ADD_TC(tp, ffsfls); 181acf13bc7Sjruoho ATF_TP_ADD_TC(tp, ilog2_1); 182acf13bc7Sjruoho ATF_TP_ADD_TC(tp, ilog2_2); 183acf13bc7Sjruoho 184acf13bc7Sjruoho return atf_no_error(); 185acf13bc7Sjruoho } 186