|
|
- /*
- * CS:APP Data Lab
- *
- * <Please put your name and userid here>
- *
- * bits.c - Source file with your solutions to the Lab.
- * This is the file you will hand in to your instructor.
- *
- * WARNING: Do not include the <stdio.h> header; it confuses the dlc
- * compiler. You can still use printf for debugging without including
- * <stdio.h>, although you might get a compiler warning. In general,
- * it's not good practice to ignore compiler warnings, but in this
- * case it's OK.
- */
-
- #if 0
- /*
- * Instructions to Students:
- *
- * STEP 1: Read the following instructions carefully.
- */
-
- You will provide your solution to the Data Lab by
- editing the collection of functions in this source file.
-
- INTEGER CODING RULES:
-
- Replace the "return" statement in each function with one
- or more lines of C code that implements the function. Your code
- must conform to the following style:
-
- int Funct(arg1, arg2, ...) {
- /* brief description of how your implementation works */
- int var1 = Expr1;
- ...
- int varM = ExprM;
-
- varJ = ExprJ;
- ...
- varN = ExprN;
- return ExprR;
- }
-
- Each "Expr" is an expression using ONLY the following:
- 1. Integer constants 0 through 255 (0xFF), inclusive. You are
- not allowed to use big constants such as 0xffffffff.
- 2. Function arguments and local variables (no global variables).
- 3. Unary integer operations ! ~
- 4. Binary integer operations & ^ | + << >>
-
- Some of the problems restrict the set of allowed operators even further.
- Each "Expr" may consist of multiple operators. You are not restricted to
- one operator per line.
-
- You are expressly forbidden to:
- 1. Use any control constructs such as if, do, while, for, switch, etc.
- 2. Define or use any macros.
- 3. Define any additional functions in this file.
- 4. Call any functions.
- 5. Use any other operations, such as &&, ||, -, or ?:
- 6. Use any form of casting.
- 7. Use any data type other than int. This implies that you
- cannot use arrays, structs, or unions.
-
-
- You may assume that your machine:
- 1. Uses 2s complement, 32-bit representations of integers.
- 2. Performs right shifts arithmetically.
- 3. Has unpredictable behavior when shifting if the shift amount
- is less than 0 or greater than 31.
-
-
- EXAMPLES OF ACCEPTABLE CODING STYLE:
- /*
- * pow2plus1 - returns 2^x + 1, where 0 <= x <= 31
- */
- int pow2plus1(int x) {
- /* exploit ability of shifts to compute powers of 2 */
- return (1 << x) + 1;
- }
-
- /*
- * pow2plus4 - returns 2^x + 4, where 0 <= x <= 31
- */
- int pow2plus4(int x) {
- /* exploit ability of shifts to compute powers of 2 */
- int result = (1 << x);
- result += 4;
- return result;
- }
-
- FLOATING POINT CODING RULES
-
- For the problems that require you to implement floating-point operations,
- the coding rules are less strict. You are allowed to use looping and
- conditional control. You are allowed to use both ints and unsigneds.
- You can use arbitrary integer and unsigned constants. You can use any arithmetic,
- logical, or comparison operations on int or unsigned data.
-
- You are expressly forbidden to:
- 1. Define or use any macros.
- 2. Define any additional functions in this file.
- 3. Call any functions.
- 4. Use any form of casting.
- 5. Use any data type other than int or unsigned. This means that you
- cannot use arrays, structs, or unions.
- 6. Use any floating point data types, operations, or constants.
-
-
- NOTES:
- 1. Use the dlc (data lab checker) compiler (described in the handout) to
- check the legality of your solutions.
- 2. Each function has a maximum number of operations (integer, logical,
- or comparison) that you are allowed to use for your implementation
- of the function. The max operator count is checked by dlc.
- Note that assignment ('=') is not counted; you may use as many of
- these as you want without penalty.
- 3. Use the btest test harness to check your functions for correctness.
- 4. Use the BDD checker to formally verify your functions
- 5. The maximum number of ops for each function is given in the
- header comment for each function. If there are any inconsistencies
- between the maximum ops in the writeup and in this file, consider
- this file the authoritative source.
-
- /*
- * STEP 2: Modify the following functions according the coding rules.
- *
- * IMPORTANT. TO AVOID GRADING SURPRISES:
- * 1. Use the dlc compiler to check that your solutions conform
- * to the coding rules.
- * 2. Use the BDD checker to formally verify that your solutions produce
- * the correct answers.
- */
-
-
- #endif
- /* Copyright (C) 1991-2020 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <https://www.gnu.org/licenses/>. */
- /* This header is separate from features.h so that the compiler can
- include it implicitly at the start of every compilation. It must
- not itself include <features.h> or any other header that includes
- <features.h> because the implicit include comes before any feature
- test macros that may be defined in a source file before it first
- explicitly includes a system header. GCC knows the name of this
- header in order to preinclude it. */
- /* glibc's intent is to support the IEC 559 math functionality, real
- and complex. If the GCC (4.9 and later) predefined macros
- specifying compiler intent are available, use them to determine
- whether the overall intent is to support these features; otherwise,
- presume an older compiler has intent to support these features and
- define these macros by default. */
- /* wchar_t uses Unicode 10.0.0. Version 10.0 of the Unicode Standard is
- synchronized with ISO/IEC 10646:2017, fifth edition, plus
- the following additions from Amendment 1 to the fifth edition:
- - 56 emoji characters
- - 285 hentaigana
- - 3 additional Zanabazar Square characters */
- //1
- /*
- * bitXor - x^y using only ~ and &
- * Example: bitXor(4, 5) = 1
- * Legal ops: ~ &
- * Max ops: 14
- * Rating: 1
- */
- int bitXor(int x, int y) {
- return ~(~x&~y)&~(x&y);
- }
- /*
- * tmin - return minimum two's complement integer
- * Legal ops: ! ~ & ^ | + << >>
- * Max ops: 4
- * Rating: 1
- */
- int tmin(void) {
- return 0x1<<31;
- }
- //2
- /*
- * isTmax - returns 1 if x is the maximum, two's complement number,
- * and 0 otherwise
- * Legal ops: ! ~ & ^ | +
- * Max ops: 10
- * Rating: 1
- */
- int isTmax(int x) {
- int i =x+1;
- x = x+i;
- x = ~x;
- i = !i;
- x = x+i;
- return !x;
- }
- /*
- * allOddBits - return 1 if all odd-numbered bits in word set to 1
- * where bits are numbered from 0 (least significant) to 31 (most significant)
- * Examples allOddBits(0xFFFFFFFD) = 0, allOddBits(0xAAAAAAAA) = 1
- * Legal ops: ! ~ & ^ | + << >>
- * Max ops: 12
- * Rating: 2
- */
- int allOddBits(int x) {
- int a = 0xaaaaaaaa;
- return !((a&x)^a);
- }
- /*
- * negate - return -x
- * Example: negate(1) = -1.
- * Legal ops: ! ~ & ^ | + << >>
- * Max ops: 5
- * Rating: 2
- */
- int negate(int x) {
- return ~x+1;
- }
- //3
- /*
- * isAsciiDigit - return 1 if 0x30 <= x <= 0x39 (ASCII codes for characters '0' to '9')
- * Example: isAsciiDigit(0x35) = 1.
- * isAsciiDigit(0x3a) = 0.
- * isAsciiDigit(0x05) = 0.
- * Legal ops: ! ~ & ^ | + << >>
- * Max ops: 15
- * Rating: 3
- */
- int isAsciiDigit(int x) {
- //下边界为加够了就溢出,比这个大
- //上边界为加不够就不溢出
- int downstream = ~0x30+1;
- int upstream = ~0x39;
- int leftside = !((downstream+x)>>31); //超过0x30就符号变为0
- int rightside = !!((upstream+x)>>31); //小于0x39就符号仍然为1
- return leftside&rightside;
- }
- /*
- * conditional - same as x ? y : z
- * Example: conditional(2,4,5) = 4
- * Legal ops: ! ~ & ^ | + << >>
- * Max ops: 16
- * Rating: 3
- */
- int conditional(int x, int y, int z) {
- x = !!(x);
- x = ~x+1;
- return (x&y)|(~x&z);
- }
- /*
- * isLessOrEqual - if x <= y then return 1, else return 0
- * Example: isLessOrEqual(4,5) = 1.
- * Legal ops: ! ~ & ^ | + << >>
- * Max ops: 24
- * Rating: 3
- */
- int isLessOrEqual(int x, int y) {
- int tmp = ~y+1;
- tmp = tmp+x-1;
- tmp = tmp >> 31;//如果比y大,则为0,比y小等于,为1
- return !!tmp;
- }
- //4
- /*
- * logicalNeg - implement the ! operator, using all of
- * the legal operators except !
- * Examples: logicalNeg(3) = 0, logicalNeg(0) = 1
- * Legal ops: ~ & ^ | + << >>
- * Max ops: 12
- * Rating: 4
- */
- int logicalNeg(int x) {
- return ((x|(~x+1))>>31)+1;
- }
- /* howManyBits - return the minimum number of bits required to represent x in
- * two's complement
- * Examples: howManyBits(12) = 5
- * howManyBits(298) = 10
- * howManyBits(-5) = 4
- * howManyBits(0) = 1
- * howManyBits(-1) = 1
- * howManyBits(0x80000000) = 32
- * Legal ops: ! ~ & ^ | + << >>
- * Max ops: 90
- * Rating: 4
- */
- int howManyBits(int x) {
- x = ((~(x>>31))&x)|(x>>31&~x);//左边为如果为正数,则保留;右边为如果为负数,则取反
- //先从最大开始查找
- int tf = !!(x>>16); //如果小于等于16位,则为0,否则为1
- int b16 = tf << 4; //长度超过16位,记录值b16为16,否则为0,代表至少16位
- x = x>>b16; //右移动b16位,超过16位则探讨16位以上的,少于16位则探讨16位以下的
-
- tf = !!(x>>8); //开始探讨剩余部位是否超过8位,超过看超过多少,没超过看余下多少
- int b8 = tf << 3;//长度超过8位,记录值b8为8,否则为0,代表再多至少8位
- x = x>>b8;
-
- tf = !!(x>>4);
- int b4 = tf << 2 ; //8找4,长度超过4位,记录值b4为4,否则为0,代表再多至少4位
- x = x>>b4;
-
- tf = !!(x>>2);
- int b2 = tf << 1; //4找2,长度超过2位,记录值b2为2,否则为0,代表再多至少2位
- x = x>>b2;
-
- tf = !!(x>>1); //2找1,长度超过1位,记录值b1为1,否则为0,代表再多至少1位
- int b1 = tf << 0;
- x = x>>b1;
-
- int b0 = x;//截断到只剩单个数字,这个数字是1就再多一位,是0就不会增加
-
- return b0+b1+b2+b4+b8+b16+1; //正数多一位补码最高位,负数因为取反未+1,理应再加1,故两个输出表达式一致
- }
- //float
- /*
- * floatScale2 - Return bit-level equivalent of expression 2*f for
- * floating point argument f.
- * Both the argument and result are passed as unsigned int's, but
- * they are to be interpreted as the bit-level representation of
- * single-precision floating point values.
- * When argument is NaN, return argument
- * Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
- * Max ops: 30
- * Rating: 4
- */
- unsigned floatScale2(unsigned uf) {
- unsigned sign = (0x80000000)&uf;
- unsigned exp = (0x7f800000)&uf;
- unsigned frac = (0x007fffff)&uf;
- if(exp == 0x7f800000)
- return uf; //如果是exp全为255,frac全是0就是无穷,不是就是NaN,都直接return
- if(exp == 0x00000000){
- if(frac == 0x00000000)
- return uf; //exp全为0,frac全为0,则为0,0*2=0,原样不动
- return (frac<<1)|sign|exp;//exp全为0,frac不全为0,注意到非规格化极小和规格化之间是连续的,即frac第一位为1时,左移会把exp变为非全0,回到规格化
- }
- return (exp+0x00800000)|sign|frac;
-
- }
- /*
- * floatFloat2Int - Return bit-level equivalent of expression (int) f
- * for floating point argument f.
- * Argument is passed as unsigned int, but
- * it is to be interpreted as the bit-level representation of a
- * single-precision floating point value.
- * Anything out of range (including NaN and infinity) should return
- * 0x80000000u.
- * Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
- * Max ops: 30
- * Rating: 4
- */
- int floatFloat2Int(unsigned uf) {
- unsigned sign = ((0x80000000)&uf)>>31;
- unsigned exp = ((0x7f800000)&uf)>>23;
- unsigned frac = (0x007fffff)&uf;
- unsigned base = (frac+0x00800000);//加1后的基底(对于常规数)
- int bias = (exp-127)-23;//真实需要左移的
- if(sign==0)
- sign = 1;
- else
- sign = -1;
- if(exp == 255)
- return 0x80000000u;//足够大
- if(exp == 0)
- return 0;//足够小
- if(bias <=0){
- if(bias<=-24)
- bias = -24;
- return sign*(base>>(-bias));
- }
- else{
- if(bias>=9)
- return 0x80000000u;
- return sign*(base<<bias);
- }
- }
- // #include "floatPower2.c"
|