summaryrefslogtreecommitdiff
path: root/labs/datalab/datalab-handout
diff options
context:
space:
mode:
Diffstat (limited to 'labs/datalab/datalab-handout')
-rw-r--r--labs/datalab/datalab-handout/Driverhdrs.pm12
-rw-r--r--labs/datalab/datalab-handout/Driverlib.pm138
-rw-r--r--labs/datalab/datalab-handout/Makefile24
-rw-r--r--labs/datalab/datalab-handout/README140
-rw-r--r--labs/datalab/datalab-handout/bits.c360
-rw-r--r--labs/datalab/datalab-handout/bits.h31
-rw-r--r--labs/datalab/datalab-handout/btest.c583
-rw-r--r--labs/datalab/datalab-handout/btest.h32
-rw-r--r--labs/datalab/datalab-handout/decl.c57
-rwxr-xr-xlabs/datalab/datalab-handout/driver.pl439
-rw-r--r--labs/datalab/datalab-handout/fshow.c151
-rw-r--r--labs/datalab/datalab-handout/ishow.c75
-rw-r--r--labs/datalab/datalab-handout/tests.c118
13 files changed, 2160 insertions, 0 deletions
diff --git a/labs/datalab/datalab-handout/Driverhdrs.pm b/labs/datalab/datalab-handout/Driverhdrs.pm
new file mode 100644
index 0000000..ecf5e2a
--- /dev/null
+++ b/labs/datalab/datalab-handout/Driverhdrs.pm
@@ -0,0 +1,12 @@
+#
+# This file contains configuration variables for drivers.
+# It was generated by genhdrs.pl. Do not modify it.
+#
+package Driverhdrs;
+
+$LAB = "datalab";
+$SERVER_NAME = "changeme.ics.cs.cmu.edu";
+$SERVER_PORT = 8081;
+$COURSE_NAME = "csapp";
+$AUTOGRADE_TIMEOUT = 0;
+1;
diff --git a/labs/datalab/datalab-handout/Driverlib.pm b/labs/datalab/datalab-handout/Driverlib.pm
new file mode 100644
index 0000000..d7f7da1
--- /dev/null
+++ b/labs/datalab/datalab-handout/Driverlib.pm
@@ -0,0 +1,138 @@
+###############################################################
+# Driverlib.pm - A package of helper functions for Perl drivers
+#
+# Copyright (c) 2005 David R. O'Hallaron, All rights reserved.
+###############################################################
+
+package Driverlib;
+
+use Socket;
+
+# Autogenerated header file with lab-specific constants
+use lib ".";
+use Driverhdrs;
+
+require Exporter;
+@ISA = qw(Exporter);
+@EXPORT = qw(
+ driver_post
+ );
+
+use strict;
+
+#####
+# Public functions
+#
+
+#
+# driver_post - This is the routine that a driver calls when
+# it needs to transmit an autoresult string to the result server.
+#
+sub driver_post ($$) {
+ my $userid = shift; # User id for this submission
+ my $result = shift; # Autoresult string
+ my $autograded = shift; # Set if called by an autograder
+
+ # Echo the autoresult string to stdout if the driver was called
+ # by an autograder
+ if ($autograded) {
+ print "\n";
+ print "AUTORESULT_STRING=$result\n";
+ return;
+ }
+
+ # If the driver was called with a specific userid, then submit
+ # the autoresult string to the result server over the Internet.
+ if ($userid) {
+ my $status = submitr($Driverhdrs::SERVER_NAME,
+ $Driverhdrs::SERVER_PORT,
+ $Driverhdrs::COURSE_NAME,
+ $userid,
+ $Driverhdrs::LAB,
+ $result);
+
+ # Print the status of the transfer
+ if (!($status =~ /OK/)) {
+ print "$status\n";
+ print "Did not send autoresult string to the result server.\n";
+ exit(1);
+ }
+ print "Success: Sent autoresult string for $userid to the result server.\n";
+ }
+}
+
+
+#####
+# Private functions
+#
+
+#
+# submitr - Sends an autoresult string to the result server
+#
+sub submitr ($$$$$$) {
+ my $hostname = shift;
+ my $port = shift;
+ my $course = shift;
+ my $userid = shift;
+ my $lab = shift;
+ my $result = shift;
+
+ my $internet_addr;
+ my $enc_result;
+ my $paddr;
+ my $line;
+ my $http_version;
+ my $errcode;
+ my $errmsg;
+
+ # Establish the connection to the server
+ socket(SERVER, PF_INET, SOCK_STREAM, getprotobyname('tcp'));
+ $internet_addr = inet_aton($hostname)
+ or die "Could not convert $hostname to an internet address: $!\n";
+ $paddr = sockaddr_in($port, $internet_addr);
+ connect(SERVER, $paddr)
+ or die "Could not connect to $hostname:$port:$!\n";
+
+ select((select(SERVER), $| = 1)[0]); # enable command buffering
+
+ # Send HTTP request to server
+ $enc_result = url_encode($result);
+ print SERVER "GET /$course/submitr.pl/?userid=$userid&lab=$lab&result=$enc_result&submit=submit HTTP/1.0\r\n\r\n";
+
+ # Get first HTTP response line
+ $line = <SERVER>;
+ chomp($line);
+ ($http_version, $errcode, $errmsg) = split(/\s+/, $line);
+ if ($errcode != 200) {
+ return "Error: HTTP request failed with error $errcode: $errmsg";
+ }
+
+ # Read the remaining HTTP response header lines
+ while ($line = <SERVER>) {
+ if ($line =~ /^\r\n/) {
+ last;
+ }
+ }
+
+ # Read and return the response from the result server
+ $line = <SERVER>;
+ chomp($line);
+
+ close SERVER;
+ return $line;
+
+}
+
+#
+# url_encode - Encode text string so it can be included in URI of GET request
+#
+sub url_encode ($) {
+ my $value = shift;
+
+ $value =~s/([^a-zA-Z0-9_\-.])/uc sprintf("%%%02x",ord($1))/eg;
+ return $value;
+}
+
+# Always end a module with a 1 so that it returns TRUE
+1;
+
diff --git a/labs/datalab/datalab-handout/Makefile b/labs/datalab/datalab-handout/Makefile
new file mode 100644
index 0000000..ca4bcf0
--- /dev/null
+++ b/labs/datalab/datalab-handout/Makefile
@@ -0,0 +1,24 @@
+#
+# Makefile that builds btest and other helper programs for the CS:APP data lab
+#
+CC = gcc
+CFLAGS = -O -Wall
+LIBS = -lm
+
+all: btest fshow ishow
+
+btest: btest.c bits.c decl.c tests.c btest.h bits.h
+ $(CC) $(CFLAGS) $(LIBS) -o btest bits.c btest.c decl.c tests.c
+
+fshow: fshow.c
+ $(CC) $(CFLAGS) -o fshow fshow.c
+
+ishow: ishow.c
+ $(CC) $(CFLAGS) -o ishow ishow.c
+
+# Forces a recompile. Used by the driver program.
+btestexplicit:
+ $(CC) $(CFLAGS) $(LIBS) -o btest bits.c btest.c decl.c tests.c
+
+clean:
+ rm -f *.o btest fshow ishow *~
diff --git a/labs/datalab/datalab-handout/README b/labs/datalab/datalab-handout/README
new file mode 100644
index 0000000..e73d37f
--- /dev/null
+++ b/labs/datalab/datalab-handout/README
@@ -0,0 +1,140 @@
+***********************
+The CS:APP Data Lab
+Directions to Students
+***********************
+
+Your goal is to modify your copy of bits.c so that it passes all the
+tests in btest without violating any of the coding guidelines.
+
+
+*********
+0. Files:
+*********
+
+Makefile - Makes btest, fshow, and ishow
+README - This file
+bits.c - The file you will be modifying and handing in
+bits.h - Header file
+btest.c - The main btest program
+ btest.h - Used to build btest
+ decl.c - Used to build btest
+ tests.c - Used to build btest
+ tests-header.c- Used to build btest
+dlc* - Rule checking compiler binary (data lab compiler)
+driver.pl* - Driver program that uses btest and dlc to autograde bits.c
+Driverhdrs.pm - Header file for optional "Beat the Prof" contest
+fshow.c - Utility for examining floating-point representations
+ishow.c - Utility for examining integer representations
+
+***********************************************************
+1. Modifying bits.c and checking it for compliance with dlc
+***********************************************************
+
+IMPORTANT: Carefully read the instructions in the bits.c file before
+you start. These give the coding rules that you will need to follow if
+you want full credit.
+
+Use the dlc compiler (./dlc) to automatically check your version of
+bits.c for compliance with the coding guidelines:
+
+ unix> ./dlc bits.c
+
+dlc returns silently if there are no problems with your code.
+Otherwise it prints messages that flag any problems. Running dlc with
+the -e switch:
+
+ unix> ./dlc -e bits.c
+
+causes dlc to print counts of the number of operators used by each function.
+
+Once you have a legal solution, you can test it for correctness using
+the ./btest program.
+
+*********************
+2. Testing with btest
+*********************
+
+The Makefile in this directory compiles your version of bits.c with
+additional code to create a program (or test harness) named btest.
+
+To compile and run the btest program, type:
+
+ unix> make btest
+ unix> ./btest [optional cmd line args]
+
+You will need to recompile btest each time you change your bits.c
+program. When moving from one platform to another, you will want to
+get rid of the old version of btest and generate a new one. Use the
+commands:
+
+ unix> make clean
+ unix> make btest
+
+Btest tests your code for correctness by running millions of test
+cases on each function. It tests wide swaths around well known corner
+cases such as Tmin and zero for integer puzzles, and zero, inf, and
+the boundary between denormalized and normalized numbers for floating
+point puzzles. When btest detects an error in one of your functions,
+it prints out the test that failed, the incorrect result, and the
+expected result, and then terminates the testing for that function.
+
+Here are the command line options for btest:
+
+ unix> ./btest -h
+ Usage: ./btest [-hg] [-r <n>] [-f <name> [-1|-2|-3 <val>]*] [-T <time limit>]
+ -1 <val> Specify first function argument
+ -2 <val> Specify second function argument
+ -3 <val> Specify third function argument
+ -f <name> Test only the named function
+ -g Format output for autograding with no error messages
+ -h Print this message
+ -r <n> Give uniform weight of n for all problems
+ -T <lim> Set timeout limit to lim
+
+Examples:
+
+ Test all functions for correctness and print out error messages:
+ unix> ./btest
+
+ Test all functions in a compact form with no error messages:
+ unix> ./btest -g
+
+ Test function foo for correctness:
+ unix> ./btest -f foo
+
+ Test function foo for correctness with specific arguments:
+ unix> ./btest -f foo -1 27 -2 0xf
+
+Btest does not check your code for compliance with the coding
+guidelines. Use dlc to do that.
+
+*******************
+3. Helper Programs
+*******************
+
+We have included the ishow and fshow programs to help you decipher
+integer and floating point representations respectively. Each takes a
+single decimal or hex number as an argument. To build them type:
+
+ unix> make
+
+Example usages:
+
+ unix> ./ishow 0x27
+ Hex = 0x00000027, Signed = 39, Unsigned = 39
+
+ unix> ./ishow 27
+ Hex = 0x0000001b, Signed = 27, Unsigned = 27
+
+ unix> ./fshow 0x15213243
+ Floating point value 3.255334057e-26
+ Bit Representation 0x15213243, sign = 0, exponent = 0x2a, fraction = 0x213243
+ Normalized. +1.2593463659 X 2^(-85)
+
+ linux> ./fshow 15213243
+ Floating point value 2.131829405e-38
+ Bit Representation 0x00e822bb, sign = 0, exponent = 0x01, fraction = 0x6822bb
+ Normalized. +1.8135598898 X 2^(-126)
+
+
+
diff --git a/labs/datalab/datalab-handout/bits.c b/labs/datalab/datalab-handout/bits.c
new file mode 100644
index 0000000..3cd1d3d
--- /dev/null
+++ b/labs/datalab/datalab-handout/bits.c
@@ -0,0 +1,360 @@
+/*
+ * 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
+//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) {
+ /*
+ (x and not y) or (y and not x) <=>
+ ~(~(x and not y) & ~(y and not x))
+ */
+ int x_and_not_y = x & ~y;
+ int y_and_not_x = y & ~x;
+ int x_not_y_or_y_not_x = ~x_and_not_y & ~y_and_not_x;
+ return ~x_not_y_or_y_not_x;
+}
+/*
+ * tmin - return minimum two's complement integer
+ * Legal ops: ! ~ & ^ | + << >>
+ * Max ops: 4
+ * Rating: 1
+ */
+int tmin(void) {
+ return 1<<(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) {
+ return !!(~0 ^ x) & !(~(x + 1) ^ 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 odd_bits_mask = 0xAA;
+ odd_bits_mask |= odd_bits_mask << 16;
+ odd_bits_mask |= odd_bits_mask << 8;
+ return !((x & odd_bits_mask) ^ odd_bits_mask);
+}
+/*
+ * 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 ret = (x + 6) >> 4;
+ ret &= !(ret ^ 3) & !((x>>4) ^ 3) & !(x>>31);
+ return ret;
+}
+/*
+ * 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) {
+ /* All ones if x is zero, all zeroes otherwise */
+ int mask = (!(x ^ 0) << 31) >> 31;
+ return (y & ~mask) | (z & mask);
+}
+/*
+ * 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 int_min = (1<<31);
+ int x_is_min = !(x ^ int_min);
+ int x_is_pos = !(x & int_min);
+ int y_is_pos = !(y & int_min);
+
+ return (!x_is_pos & y_is_pos)
+ | x_is_min
+ | !((y + (~x + 1)) & int_min);
+}
+//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) {
+ /* Using arithmetic shift */
+ int sign_bit = x >> 31;
+ int neg_sign_bit = (~x + 1) >> 31;
+ return (sign_bit | neg_sign_bit) + 1;
+
+ /* Naive approach */
+ /* x |= x>>16; */
+ /* x |= x>>8; */
+ /* x |= x>>4; */
+ /* x |= x>>2; */
+ /* x |= x>>1; */
+ /* return (x & 1) ^ 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) {
+ /* My original solution was a lot messier */
+ int sign_bit = (x>>31);
+ int b16, b8, b4, b2, b1, b0;
+
+ /* Take the number that is encoded by the positive bits */
+ int u = (x & ~sign_bit) | (~x & sign_bit);
+
+ /* unsigned u = x; */
+ /* any greater than 16? */
+ /*
+ 0000 000C
+ 0000 000C
+ 0000 000C
+ 0000 0003
+ 0000 0001
+
+ */
+ b16 = (!!(u>>16))<<4;
+ u >>= b16;
+
+ b8 = (!!(u>>8))<<3;
+ u >>= b8;
+
+ b4 = (!!(u>>4))<<2;
+ u >>= b4;
+
+ b2 = (!!(u>>2))<<1;
+ u >>= b2;
+
+ b1 = (!!(u>>1));
+ u >>= b1;
+
+ b0 = !!u;
+ return b16 + b8 + b4 + b2 + b1 + b0 + 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) {
+ return 2;
+}
+/*
+ * 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) {
+ return 2;
+}
+/*
+ * floatPower2 - Return bit-level equivalent of the expression 2.0^x
+ * (2.0 raised to the power x) for any 32-bit integer x.
+ *
+ * The unsigned value that is returned should have the identical bit
+ * representation as the single-precision floating-point number 2.0^x.
+ * If the result is too small to be represented as a denorm, return
+ * 0. If too large, return +INF.
+ *
+ * Legal ops: Any integer/unsigned operations incl. ||, &&. Also if, while
+ * Max ops: 30
+ * Rating: 4
+ */
+unsigned floatPower2(int x) {
+ return 2;
+}
diff --git a/labs/datalab/datalab-handout/bits.h b/labs/datalab/datalab-handout/bits.h
new file mode 100644
index 0000000..de2685a
--- /dev/null
+++ b/labs/datalab/datalab-handout/bits.h
@@ -0,0 +1,31 @@
+//1
+int bitXor(int, int);
+int test_bitXor(int, int);
+int tmin();
+int test_tmin();
+//2
+int isTmax(int);
+int test_isTmax(int);
+int allOddBits();
+int test_allOddBits();
+int negate(int);
+int test_negate(int);
+//3
+int isAsciiDigit(int);
+int test_isAsciiDigit(int);
+int conditional(int, int, int);
+int test_conditional(int, int, int);
+int isLessOrEqual(int, int);
+int test_isLessOrEqual(int, int);
+//4
+int logicalNeg(int);
+int test_logicalNeg(int);
+int howManyBits(int);
+int test_howManyBits(int);
+//float
+unsigned floatScale2(unsigned);
+unsigned test_floatScale2(unsigned);
+int floatFloat2Int(unsigned);
+int test_floatFloat2Int(unsigned);
+unsigned floatPower2(int);
+unsigned test_floatPower2(int);
diff --git a/labs/datalab/datalab-handout/btest.c b/labs/datalab/datalab-handout/btest.c
new file mode 100644
index 0000000..660072e
--- /dev/null
+++ b/labs/datalab/datalab-handout/btest.c
@@ -0,0 +1,583 @@
+/*
+ * CS:APP Data Lab
+ *
+ * btest.c - A test harness that checks a student's solution in bits.c
+ * for correctness.
+ *
+ * Copyright (c) 2001-2011, R. Bryant and D. O'Hallaron, All rights
+ * reserved. May not be used, modified, or copied without permission.
+ *
+ * This is an improved version of btest that tests large windows
+ * around zero and tmin and tmax for integer puzzles, and zero, norm,
+ * and denorm boundaries for floating point puzzles.
+ *
+ * Note: not 64-bit safe. Always compile with gcc -m32 option.
+ */
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <math.h>
+#include "btest.h"
+
+/* Not declared in some stdlib.h files, so define here */
+float strtof(const char *nptr, char **endptr);
+
+/*************************
+ * Configuration Constants
+ *************************/
+
+/* Handle infinite loops by setting upper limit on execution time, in
+ seconds */
+#define TIMEOUT_LIMIT 10
+
+/* For functions with a single argument, generate TEST_RANGE values
+ above and below the min and max test values, and above and below
+ zero. Functions with two or three args will use square and cube
+ roots of this value, respectively, to avoid combinatorial
+ explosion */
+#define TEST_RANGE 500000
+
+/* This defines the maximum size of any test value array. The
+ gen_vals() routine creates k test values for each value of
+ TEST_RANGE, thus MAX_TEST_VALS must be at least k*TEST_RANGE */
+#define MAX_TEST_VALS 13*TEST_RANGE
+
+/**********************************
+ * Globals defined in other modules
+ **********************************/
+/* This characterizes the set of puzzles to test.
+ Defined in decl.c and generated from templates in ./puzzles dir */
+extern test_rec test_set[];
+
+/************************************************
+ * Write-once globals defined by command line args
+ ************************************************/
+
+/* Emit results in a format for autograding, without showing
+ and counter-examples */
+static int grade = 0;
+
+/* Time out after this number of seconds */
+static int timeout_limit = TIMEOUT_LIMIT; /* -T */
+
+/* If non-NULL, test only one function (-f) */
+static char* test_fname = NULL;
+
+/* Special case when only use fixed argument(s) (-1, -2, or -3) */
+static int has_arg[3] = {0,0,0};
+static unsigned argval[3] = {0,0,0};
+
+/* Use fixed weight for rating, and if so, what should it be? (-r) */
+static int global_rating = 0;
+
+/******************
+ * Helper functions
+ ******************/
+
+/*
+ * Signal - installs a signal handler
+ */
+typedef void handler_t(int);
+
+handler_t *Signal(int signum, handler_t *handler)
+{
+ struct sigaction action, old_action;
+
+ action.sa_handler = handler;
+ sigemptyset(&action.sa_mask); /* block sigs of type being handled */
+ action.sa_flags = SA_RESTART; /* restart syscalls if possible */
+
+ if (sigaction(signum, &action, &old_action) < 0)
+ perror("Signal error");
+ return (old_action.sa_handler);
+}
+
+/*
+ * timeout_handler - SIGALARM hander
+ */
+sigjmp_buf envbuf;
+void timeout_handler(int sig) {
+ siglongjmp(envbuf, 1);
+}
+
+/*
+ * random_val - Return random integer value between min and max
+ */
+static int random_val(int min, int max)
+{
+ double weight = rand()/(double) RAND_MAX;
+ int result = min * (1-weight) + max * weight;
+ return result;
+}
+
+/*
+ * gen_vals - Generate the integer values we'll use to test a function
+ */
+static int gen_vals(int test_vals[], int min, int max, int test_range, int arg)
+{
+ int i;
+ int test_count = 0;
+
+ /* Special case: If the user has specified a specific function
+ argument using the -1, -2, or -3 flags, then simply use this
+ argument and return */
+ if (has_arg[arg]) {
+ test_vals[0] = argval[arg];
+ return 1;
+ }
+
+ /*
+ * Special case: Generate test vals for floating point functions
+ * where the input argument is an unsigned bit-level
+ * representation of a float. For this case we want to test the
+ * regions around zero, the smallest normalized and largest
+ * denormalized numbers, one, and the largest normalized number,
+ * as well as inf and nan.
+ */
+ if ((min == 1 && max == 1)) {
+ unsigned smallest_norm = 0x00800000;
+ unsigned one = 0x3f800000;
+ unsigned largest_norm = 0x7f000000;
+
+ unsigned inf = 0x7f800000;
+ unsigned nan = 0x7fc00000;
+ unsigned sign = 0x80000000;
+
+ /* Test range should be at most 1/2 the range of one exponent
+ value */
+ if (test_range > (1 << 23)) {
+ test_range = 1 << 23;
+ }
+
+ /* Functions where the input argument is an unsigned bit-level
+ representation of a float. The number of tests generated
+ inside this loop body is the value k referenced in the
+ comment for the global variable MAX_TEST_VALS. */
+
+ for (i = 0; i < test_range; i++) {
+ /* Denorms around zero */
+ test_vals[test_count++] = i;
+ test_vals[test_count++] = sign | i;
+
+ /* Region around norm to denorm transition */
+ test_vals[test_count++] = smallest_norm + i;
+ test_vals[test_count++] = smallest_norm - i;
+ test_vals[test_count++] = sign | (smallest_norm + i);
+ test_vals[test_count++] = sign | (smallest_norm - i);
+
+ /* Region around one */
+ test_vals[test_count++] = one + i;
+ test_vals[test_count++] = one - i;
+ test_vals[test_count++] = sign | (one + i);
+ test_vals[test_count++] = sign | (one - i);
+
+ /* Region below largest norm */
+ test_vals[test_count++] = largest_norm - i;
+ test_vals[test_count++] = sign | (largest_norm - i);
+ }
+
+ /* special vals */
+ test_vals[test_count++] = inf; /* inf */
+ test_vals[test_count++] = sign | inf; /* -inf */
+ test_vals[test_count++] = nan; /* nan */
+ test_vals[test_count++] = sign | nan; /* -nan */
+
+ return test_count;
+ }
+
+
+ /*
+ * Normal case: Generate test vals for integer functions
+ */
+
+ /* If the range is small enough, then do exhaustively */
+ if (max - MAX_TEST_VALS <= min) {
+ for (i = min; i <= max; i++)
+ test_vals[test_count++] = i;
+ return test_count;
+ }
+
+ /* Otherwise, need to sample. Do so near the boundaries, around
+ zero, and for some random cases. */
+ for (i = 0; i < test_range; i++) {
+
+ /* Test around the boundaries */
+ test_vals[test_count++] = min + i;
+ test_vals[test_count++] = max - i;
+
+ /* If zero falls between min and max, then also test around zero */
+ if (i >= min && i <= max)
+ test_vals[test_count++] = i;
+ if (-i >= min && -i <= max)
+ test_vals[test_count++] = -i;
+
+ /* Random case between min and max */
+ test_vals[test_count++] = random_val(min, max);
+
+ }
+ return test_count;
+}
+
+/*
+ * test_0_arg - Test a function with zero arguments
+ */
+static int test_0_arg(funct_t f, funct_t ft, char *name)
+{
+ int r = f();
+ int rt = ft();
+ int error = (r != rt);
+
+ if (error && !grade)
+ printf("ERROR: Test %s() failed...\n...Gives %d[0x%x]. Should be %d[0x%x]\n", name, r, r, rt, rt);
+
+ return error;
+}
+
+/*
+ * test_1_arg - Test a function with one argument
+ */
+static int test_1_arg(funct_t f, funct_t ft, int arg1, char *name)
+{
+ funct1_t f1 = (funct1_t) f;
+ funct1_t f1t = (funct1_t) ft;
+ int r, rt, error;
+
+ r = f1(arg1);
+ rt = f1t(arg1);
+ error = (r != rt);
+ if (error && !grade)
+ printf("ERROR: Test %s(%d[0x%x]) failed...\n...Gives %d[0x%x]. Should be %d[0x%x]\n", name, arg1, arg1, r, r, rt, rt);
+
+ return error;
+}
+
+/*
+ * test_2_arg - Test a function with two arguments
+ */
+static int test_2_arg(funct_t f, funct_t ft, int arg1, int arg2, char *name)
+{
+ funct2_t f2 = (funct2_t) f;
+ funct2_t f2t = (funct2_t) ft;
+ int r = f2(arg1, arg2);
+ int rt = f2t(arg1, arg2);
+ int error = (r != rt);
+
+ if (error && !grade)
+ printf("ERROR: Test %s(%d[0x%x],%d[0x%x]) failed...\n...Gives %d[0x%x]. Should be %d[0x%x]\n", name, arg1, arg1, arg2, arg2, r, r, rt, rt);
+
+ return error;
+}
+
+/*
+ * test_3_arg - Test a function with three arguments
+ */
+static int test_3_arg(funct_t f, funct_t ft,
+ int arg1, int arg2, int arg3, char *name)
+{
+ funct3_t f3 = (funct3_t) f;
+ funct3_t f3t = (funct3_t) ft;
+ int r = f3(arg1, arg2, arg3);
+ int rt = f3t(arg1, arg2, arg3);
+ int error = (r != rt);
+
+ if (error && !grade)
+ printf("ERROR: Test %s(%d[0x%x],%d[0x%x],%d[0x%x]) failed...\n...Gives %d[0x%x]. Should be %d[0x%x]\n", name, arg1, arg1, arg2, arg2, arg3, arg3, r, r, rt, rt);
+
+ return error;
+}
+
+/*
+ * test_function - Test a function. Return number of errors
+ */
+static int test_function(test_ptr t) {
+ int test_counts[3]; /* number of test values for each arg */
+ int args = t->args; /* number of function arguments */
+ int arg_test_range[3]; /* test range for each argument */
+ int i, a1, a2, a3;
+ int errors = 0;
+
+ /* These are the test values for each arg. Declared with the
+ static attribute so that the array will be allocated in bss
+ rather than the stack */
+ static int arg_test_vals[3][MAX_TEST_VALS];
+
+ /* Sanity check on the number of args */
+ if (args < 0 || args > 3) {
+ printf("Configuration error: invalid number of args (%d) for function %s\n", args, t->name);
+ exit(1);
+ }
+
+ /* Assign range of argument test vals so as to conserve the total
+ number of tests, independent of the number of arguments */
+ if (args == 1) {
+ arg_test_range[0] = TEST_RANGE;
+ }
+ else if (args == 2) {
+ arg_test_range[0] = pow((double)TEST_RANGE, 0.5); /* sqrt */
+ arg_test_range[1] = arg_test_range[0];
+ }
+ else {
+ arg_test_range[0] = pow((double)TEST_RANGE, 0.333); /* cbrt */
+ arg_test_range[1] = arg_test_range[0];
+ arg_test_range[2] = arg_test_range[0];
+ }
+
+ /* Sanity check on the ranges */
+ if (arg_test_range[0] < 1)
+ arg_test_range[0] = 1;
+ if (arg_test_range[1] < 1)
+ arg_test_range[1] = 1;
+ if (arg_test_range[2] < 1)
+ arg_test_range[2] = 1;
+
+ /* Create a test set for each argument */
+ for (i = 0; i < args; i++) {
+ test_counts[i] = gen_vals(arg_test_vals[i],
+ t->arg_ranges[i][0], /* min */
+ t->arg_ranges[i][1], /* max */
+ arg_test_range[i],
+ i);
+
+ }
+
+ /* Handle timeouts in the test code */
+ if (timeout_limit > 0) {
+ int rc;
+ rc = sigsetjmp(envbuf, 1);
+ if (rc) {
+ /* control will reach here if there is a timeout */
+ errors = 1;
+ printf("ERROR: Test %s failed.\n Timed out after %d secs (probably infinite loop)\n", t->name, timeout_limit);
+ return errors;
+ }
+ alarm(timeout_limit);
+ }
+
+
+ /* Test function has no arguments */
+ if (args == 0) {
+ errors += test_0_arg(t->solution_funct, t->test_funct, t->name);
+ return errors;
+ }
+
+ /*
+ * Test function has at least one argument
+ */
+
+ /* Iterate over the values for first argument */
+
+ for (a1 = 0; a1 < test_counts[0]; a1++) {
+ if (args == 1) {
+ errors += test_1_arg(t->solution_funct,
+ t->test_funct,
+ arg_test_vals[0][a1],
+ t->name);
+
+ /* Stop testing if there is an error */
+ if (errors)
+ return errors;
+ }
+ else {
+ /* if necessary, iterate over values for second argument */
+ for (a2 = 0; a2 < test_counts[1]; a2++) {
+ if (args == 2) {
+ errors += test_2_arg(t->solution_funct,
+ t->test_funct,
+ arg_test_vals[0][a1],
+ arg_test_vals[1][a2],
+ t->name);
+
+ /* Stop testing if there is an error */
+ if (errors)
+ return errors;
+ }
+ else {
+ /* if necessary, iterate over vals for third arg */
+ for (a3 = 0; a3 < test_counts[2]; a3++) {
+ errors += test_3_arg(t->solution_funct,
+ t->test_funct,
+ arg_test_vals[0][a1],
+ arg_test_vals[1][a2],
+ arg_test_vals[2][a3],
+ t->name);
+
+ /* Stop testing if there is an error */
+ if (errors)
+ return errors;
+ } /* a3 */
+ }
+ } /* a2 */
+ }
+ } /* a1 */
+
+
+ return errors;
+}
+
+/*
+ * run_tests - Run series of tests. Return number of errors
+ */
+static int run_tests()
+{
+ int i;
+ int errors = 0;
+ double points = 0.0;
+ double max_points = 0.0;
+
+ printf("Score\tRating\tErrors\tFunction\n");
+
+ for (i = 0; test_set[i].solution_funct; i++) {
+ int terrors;
+ double tscore;
+ double tpoints;
+ if (!test_fname || strcmp(test_set[i].name,test_fname) == 0) {
+ int rating = global_rating ? global_rating : test_set[i].rating;
+ terrors = test_function(&test_set[i]);
+ errors += terrors;
+ tscore = terrors == 0 ? 1.0 : 0.0;
+ tpoints = rating * tscore;
+ points += tpoints;
+ max_points += rating;
+
+ if (grade || terrors < 1)
+ printf(" %.0f\t%d\t%d\t%s\n",
+ tpoints, rating, terrors, test_set[i].name);
+
+ }
+ }
+
+ printf("Total points: %.0f/%.0f\n", points, max_points);
+ return errors;
+}
+
+/*
+ * get_num_val - Extract hex/decimal/or float value from string
+ */
+static int get_num_val(char *sval, unsigned *valp) {
+ char *endp;
+
+ /* See if it's an integer or floating point */
+ int ishex = 0;
+ int isfloat = 0;
+ int i;
+ for (i = 0; sval[i]; i++) {
+ switch (sval[i]) {
+ case 'x':
+ case 'X':
+ ishex = 1;
+ break;
+ case 'e':
+ case 'E':
+ if (!ishex)
+ isfloat = 1;
+ break;
+ case '.':
+ isfloat = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ if (isfloat) {
+ float fval = strtof(sval, &endp);
+ if (!*endp) {
+ *valp = *(unsigned *) &fval;
+ return 1;
+ }
+ return 0;
+ } else {
+ long long int llval = strtoll(sval, &endp, 0);
+ long long int upperbits = llval >> 31;
+ /* will give -1 for negative, 0 or 1 for positive */
+ if (!*valp && (upperbits == 0 || upperbits == -1 || upperbits == 1)) {
+ *valp = (unsigned) llval;
+ return 1;
+ }
+ return 0;
+ }
+}
+
+
+/*
+ * usage - Display usage info
+ */
+static void usage(char *cmd) {
+ printf("Usage: %s [-hg] [-r <n>] [-f <name> [-1|-2|-3 <val>]*] [-T <time limit>]\n", cmd);
+ printf(" -1 <val> Specify first function argument\n");
+ printf(" -2 <val> Specify second function argument\n");
+ printf(" -3 <val> Specify third function argument\n");
+ printf(" -f <name> Test only the named function\n");
+ printf(" -g Compact output for grading (with no error msgs)\n");
+ printf(" -h Print this message\n");
+ printf(" -r <n> Give uniform weight of n for all problems\n");
+ printf(" -T <lim> Set timeout limit to lim\n");
+ exit(1);
+}
+
+
+/**************
+ * Main routine
+ **************/
+
+int main(int argc, char *argv[])
+{
+ char c;
+
+ /* parse command line args */
+ while ((c = getopt(argc, argv, "hgf:r:T:1:2:3:")) != -1)
+ switch (c) {
+ case 'h': /* help */
+ usage(argv[0]);
+ break;
+ case 'g': /* grading option for autograder */
+ grade = 1;
+ break;
+ case 'f': /* test only one function */
+ test_fname = strdup(optarg);
+ break;
+ case 'r': /* set global rating for each problem */
+ global_rating = atoi(optarg);
+ if (global_rating < 0)
+ usage(argv[0]);
+ break;
+ case '1': /* Get first argument */
+ has_arg[0] = get_num_val(optarg, &argval[0]);
+ if (!has_arg[0]) {
+ printf("Bad argument '%s'\n", optarg);
+ exit(0);
+ }
+ break;
+ case '2': /* Get first argument */
+ has_arg[1] = get_num_val(optarg, &argval[1]);
+ if (!has_arg[1]) {
+ printf("Bad argument '%s'\n", optarg);
+ exit(0);
+ }
+ break;
+ case '3': /* Get first argument */
+ has_arg[2] = get_num_val(optarg, &argval[2]);
+ if (!has_arg[2]) {
+ printf("Bad argument '%s'\n", optarg);
+ exit(0);
+ }
+ break;
+ case 'T': /* Set timeout limit */
+ timeout_limit = atoi(optarg);
+ break;
+ default:
+ usage(argv[0]);
+ }
+
+ if (timeout_limit > 0) {
+ Signal(SIGALRM, timeout_handler);
+ }
+
+ /* test each function */
+ run_tests();
+
+ return 0;
+}
diff --git a/labs/datalab/datalab-handout/btest.h b/labs/datalab/datalab-handout/btest.h
new file mode 100644
index 0000000..a011bc1
--- /dev/null
+++ b/labs/datalab/datalab-handout/btest.h
@@ -0,0 +1,32 @@
+/*
+ * CS:APP Data Lab
+ */
+
+/* Declare different function types */
+typedef int (*funct_t) (void);
+typedef int (*funct1_t)(int);
+typedef int (*funct2_t)(int, int);
+typedef int (*funct3_t)(int, int, int);
+
+/* Combine all the information about a function and its tests as structure */
+typedef struct {
+ char *name; /* String name */
+ funct_t solution_funct; /* Function */
+ funct_t test_funct; /* Test function */
+ int args; /* Number of function arguments */
+ char *ops; /* List of legal operators. Special case: "$" for floating point */
+ int op_limit; /* Max number of ops allowed in solution */
+ int rating; /* Problem rating (1 -- 4) */
+ int arg_ranges[3][2]; /* Argument ranges. Always defined for 3 args, even if */
+ /* the function takes fewer. Special case: First arg */
+ /* must be set to {1,1} for f.p. puzzles */
+} test_rec, *test_ptr;
+
+extern test_rec test_set[];
+
+
+
+
+
+
+
diff --git a/labs/datalab/datalab-handout/decl.c b/labs/datalab/datalab-handout/decl.c
new file mode 100644
index 0000000..11370c7
--- /dev/null
+++ b/labs/datalab/datalab-handout/decl.c
@@ -0,0 +1,57 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+
+#define TMin INT_MIN
+#define TMax INT_MAX
+
+#include "btest.h"
+#include "bits.h"
+
+test_rec test_set[] = {
+//1
+
+
+
+
+ {"bitXor", (funct_t) bitXor, (funct_t) test_bitXor, 2, "& ~", 14, 1,
+ {{TMin, TMax},{TMin,TMax},{TMin,TMax}}},
+ {"tmin", (funct_t) tmin, (funct_t) test_tmin, 0, "! ~ & ^ | + << >>", 4, 1,
+ {{TMin, TMax},{TMin,TMax},{TMin,TMax}}},
+//2
+ {"isTmax", (funct_t) isTmax, (funct_t) test_isTmax, 1, "! ~ & ^ | +", 10, 1,
+ {{TMin, TMax},{TMin,TMax},{TMin,TMax}}},
+ {"allOddBits", (funct_t) allOddBits, (funct_t) test_allOddBits, 1,
+ "! ~ & ^ | + << >>", 12, 2,
+ {{TMin, TMax},{TMin,TMax},{TMin,TMax}}},
+ {"negate", (funct_t) negate, (funct_t) test_negate, 1,
+ "! ~ & ^ | + << >>", 5, 2,
+ {{TMin, TMax},{TMin,TMax},{TMin,TMax}}},
+//3
+ {"isAsciiDigit", (funct_t) isAsciiDigit, (funct_t) test_isAsciiDigit, 1,
+ "! ~ & ^ | + << >>", 15, 3,
+ {{TMin, TMax},{TMin,TMax},{TMin,TMax}}},
+ {"conditional", (funct_t) conditional, (funct_t) test_conditional, 3, "! ~ & ^ | << >>", 16, 3,
+ {{TMin, TMax},{TMin,TMax},{TMin,TMax}}},
+ {"isLessOrEqual", (funct_t) isLessOrEqual, (funct_t) test_isLessOrEqual, 2,
+ "! ~ & ^ | + << >>", 24, 3,
+ {{TMin, TMax},{TMin,TMax},{TMin,TMax}}},
+//4
+ {"logicalNeg", (funct_t) logicalNeg, (funct_t) test_logicalNeg, 1,
+ "~ & ^ | + << >>", 12, 4,
+ {{TMin, TMax},{TMin,TMax},{TMin,TMax}}},
+ {"howManyBits", (funct_t) howManyBits, (funct_t) test_howManyBits, 1, "! ~ & ^ | + << >>", 90, 4,
+ {{TMin, TMax},{TMin,TMax},{TMin,TMax}}},
+//float
+ {"floatScale2", (funct_t) floatScale2, (funct_t) test_floatScale2, 1,
+ "$", 30, 4,
+ {{1, 1},{1,1},{1,1}}},
+ {"floatFloat2Int", (funct_t) floatFloat2Int, (funct_t) test_floatFloat2Int, 1,
+ "$", 30, 4,
+ {{1, 1},{1,1},{1,1}}},
+ {"floatPower2", (funct_t) floatPower2, (funct_t) test_floatPower2, 1,
+ "$", 30, 4,
+ {{1, 1},{1,1},{1,1}}},
+ {"", NULL, NULL, 0, "", 0, 0,
+ {{0, 0},{0,0},{0,0}}}
+};
diff --git a/labs/datalab/datalab-handout/driver.pl b/labs/datalab/datalab-handout/driver.pl
new file mode 100755
index 0000000..143c440
--- /dev/null
+++ b/labs/datalab/datalab-handout/driver.pl
@@ -0,0 +1,439 @@
+#!/usr/bin/perl
+#######################################################################
+# driver.pl - CS:APP Data Lab driver
+#
+# Copyright (c) 2004-2011, R. Bryant and D. O'Hallaron, All rights
+# reserved. May not be used, modified, or copied without permission.
+#
+# Note: The driver can use either btest or the BDD checker to check
+# puzzles for correctness. This version of the lab uses btest, which
+# has been extended to do better testing of both integer and
+# floating-point puzzles.
+#
+#######################################################################
+
+use strict 'vars';
+use Getopt::Std;
+
+use lib ".";
+use Driverlib;
+
+# Set to 1 to use btest, 0 to use the BDD checker.
+my $USE_BTEST = 1;
+
+# Generic settings
+$| = 1; # Flush stdout each time
+umask(0077); # Files created by the user in tmp readable only by that user
+$ENV{PATH} = "/usr/local/bin:/usr/bin:/bin";
+
+#
+# usage - print help message and terminate
+#
+sub usage {
+ printf STDERR "$_[0]\n";
+ printf STDERR "Usage: $0 [-h] [-u \"nickname\"]\n";
+ printf STDERR "Options:\n";
+ printf STDERR " -h Print this message.\n";
+ printf STDERR " -u \"nickname\" Send autoresult to server, using nickname on scoreboard)\n";
+ die "\n";
+}
+
+##############
+# Main routine
+##############
+my $login = getlogin() || (getpwuid($<))[0] || "unknown";
+my $tmpdir = "/var/tmp/datalab.$login.$$";
+my $diemsg = "The files are in $tmpdir.";
+
+my $driverfiles;
+my $infile;
+my $autograded;
+
+my $status;
+my $inpuzzles;
+my $puzzlecnt;
+my $line;
+my $blank;
+my $name;
+my $c_points;
+my $c_rating;
+my $c_errors;
+my $p_points;
+my $p_rating;
+my $p_errors;
+my $total_c_points;
+my $total_c_rating;
+my $total_p_points;
+my $total_p_rating;
+my $tops;
+my $tpoints;
+my $trating;
+my $foo;
+my $name;
+my $msg;
+my $nickname;
+my $autoresult;
+
+my %puzzle_c_points;
+my %puzzle_c_rating;
+my %puzzle_c_errors;
+my %puzzle_p_points;
+my %puzzle_p_ops;
+my %puzzle_p_maxops;
+my %puzzle_number;
+
+
+# Parse the command line arguments
+no strict;
+getopts('hu:f:A');
+if ($opt_h) {
+ usage();
+}
+
+# The default input file is bits.c (change with -f)
+$infile = "bits.c";
+$nickname = "";
+
+#####
+# These are command line args that every driver must support
+#
+
+# Causes the driver to send an autoresult to the server on behalf of user
+if ($opt_u) {
+ $nickname = $opt_u;
+ check_nickname($nickname);
+}
+
+# Hidden flag that indicates that the driver was invoked by an autograder
+if ($opt_A) {
+ $autograded = $opt_A;
+}
+
+#####
+# Drivers can also define an arbitary number of other command line args
+#
+# Optional hidden flag used by the autograder
+if ($opt_f) {
+ $infile = $opt_f;
+}
+
+use strict 'vars';
+
+################################################
+# Compute the correctness and performance scores
+################################################
+
+# Make sure that an executable dlc (data lab compiler) exists
+(-e "./dlc" and -x "./dlc")
+ or die "$0: ERROR: No executable dlc binary.\n";
+
+
+# If using the bdd checker, then make sure it exists
+if (!$USE_BTEST) {
+ (-e "./bddcheck/cbit/cbit" and -x "./bddcheck/cbit/cbit")
+ or die "$0: ERROR: No executable cbit binary.\n";
+}
+
+#
+# Set up the contents of the scratch directory
+#
+system("mkdir $tmpdir") == 0
+ or die "$0: Could not make scratch directory $tmpdir.\n";
+
+# Copy the student's work to the scratch directory
+unless (system("cp $infile $tmpdir/bits.c") == 0) {
+ clean($tmpdir);
+ die "$0: Could not copy file $infile to scratch directory $tmpdir.\n";
+}
+
+# Copy the various autograding files to the scratch directory
+if ($USE_BTEST) {
+ $driverfiles = "Makefile dlc btest.c decl.c tests.c btest.h bits.h";
+ unless (system("cp -r $driverfiles $tmpdir") == 0) {
+ clean($tmpdir);
+ die "$0: Could not copy autogradingfiles to $tmpdir.\n";
+ }
+}
+else {
+ $driverfiles = "dlc tests.c bddcheck";
+ unless (system("cp -r $driverfiles $tmpdir") == 0) {
+ clean($tmpdir);
+ die "$0: Could not copy support files to $tmpdir.\n";
+ }
+}
+
+# Change the current working directory to the scratch directory
+unless (chdir($tmpdir)) {
+ clean($tmpdir);
+ die "$0: Could not change directory to $tmpdir.\n";
+}
+
+#
+# Generate a zapped (for coding rules) version of bits.c. In this
+# zapped version of bits.c, any functions with illegal operators are
+# transformed to have empty function bodies.
+#
+print "1. Running './dlc -z' to identify coding rules violations.\n";
+system("cp bits.c save-bits.c") == 0
+ or die "$0: ERROR: Could not create backup copy of bits.c. $diemsg\n";
+system("./dlc -z -o zap-bits.c bits.c") == 0
+ or die "$0: ERROR: zapped bits.c did not compile. $diemsg\n";
+
+#
+# Run btest or BDD checker to determine correctness score
+#
+if ($USE_BTEST) {
+ print "\n2. Compiling and running './btest -g' to determine correctness score.\n";
+ system("cp zap-bits.c bits.c");
+
+ # Compile btest
+ system("make btestexplicit") == 0
+ or die "$0: Could not make btest in $tmpdir. $diemsg\n";
+
+ # Run btest
+ $status = system("./btest -g > btest-zapped.out 2>&1");
+ if ($status != 0) {
+ die "$0: ERROR: btest check failed. $diemsg\n";
+ }
+}
+else {
+ print "\n2. Running './bddcheck/check.pl -g' to determine correctness score.\n";
+ system("cp zap-bits.c bits.c");
+ $status = system("./bddcheck/check.pl -g > btest-zapped.out 2>&1");
+ if ($status != 0) {
+ die "$0: ERROR: BDD check failed. $diemsg\n";
+ }
+}
+
+#
+# Run dlc to identify operator count violations.
+#
+print "\n3. Running './dlc -Z' to identify operator count violations.\n";
+system("./dlc -Z -o Zap-bits.c save-bits.c") == 0
+ or die "$0: ERROR: dlc unable to generated Zapped bits.c file.\n";
+
+#
+# Run btest or the bdd checker to compute performance score
+#
+if ($USE_BTEST) {
+ print "\n4. Compiling and running './btest -g -r 2' to determine performance score.\n";
+ system("cp Zap-bits.c bits.c");
+
+ # Compile btest
+ system("make btestexplicit") == 0
+ or die "$0: Could not make btest in $tmpdir. $diemsg\n";
+ print "\n";
+
+ # Run btest
+ $status = system("./btest -g -r 2 > btest-Zapped.out 2>&1");
+ if ($status != 0) {
+ die "$0: ERROR: Zapped btest failed. $diemsg\n";
+ }
+}
+else {
+ print "\n4. Running './bddcheck/check.pl -g -r 2' to determine performance score.\n";
+ system("cp Zap-bits.c bits.c");
+ $status = system("./bddcheck/check.pl -g -r 2 > btest-Zapped.out 2>&1");
+ if ($status != 0) {
+ die "$0: ERROR: Zapped bdd checker failed. $diemsg\n";
+ }
+}
+
+#
+# Run dlc to get the operator counts on the zapped input file
+#
+print "\n5. Running './dlc -e' to get operator count of each function.\n";
+$status = system("./dlc -W1 -e zap-bits.c > dlc-opcount.out 2>&1");
+if ($status != 0) {
+ die "$0: ERROR: bits.c did not compile. $diemsg\n";
+}
+
+#################################################################
+# Collect the correctness and performance results for each puzzle
+#################################################################
+
+#
+# Collect the correctness results
+#
+%puzzle_c_points = (); # Correctness score computed by btest
+%puzzle_c_errors = (); # Correctness error discovered by btest
+%puzzle_c_rating = (); # Correctness puzzle rating (max points)
+
+$inpuzzles = 0; # Becomes true when we start reading puzzle results
+$puzzlecnt = 0; # Each puzzle gets a unique number
+$total_c_points = 0;
+$total_c_rating = 0;
+
+open(INFILE, "$tmpdir/btest-zapped.out")
+ or die "$0: ERROR: could not open input file $tmpdir/btest-zapped.out\n";
+
+while ($line = <INFILE>) {
+ chomp($line);
+
+ # Notice that we're ready to read the puzzle scores
+ if ($line =~ /^Score/) {
+ $inpuzzles = 1;
+ next;
+ }
+
+ # Notice that we're through reading the puzzle scores
+ if ($line =~ /^Total/) {
+ $inpuzzles = 0;
+ next;
+ }
+
+ # Read and record a puzzle's name and score
+ if ($inpuzzles) {
+ ($blank, $c_points, $c_rating, $c_errors, $name) = split(/\s+/, $line);
+ $puzzle_c_points{$name} = $c_points;
+ $puzzle_c_errors{$name} = $c_errors;
+ $puzzle_c_rating{$name} = $c_rating;
+ $puzzle_number{$name} = $puzzlecnt++;
+ $total_c_points += $c_points;
+ $total_c_rating += $c_rating;
+ }
+
+}
+close(INFILE);
+
+#
+# Collect the performance results
+#
+%puzzle_p_points = (); # Performance points
+
+$inpuzzles = 0; # Becomes true when we start reading puzzle results
+$total_p_points = 0;
+$total_p_rating = 0;
+
+open(INFILE, "$tmpdir/btest-Zapped.out")
+ or die "$0: ERROR: could not open input file $tmpdir/btest-Zapped.out\n";
+
+while ($line = <INFILE>) {
+ chomp($line);
+
+ # Notice that we're ready to read the puzzle scores
+ if ($line =~ /^Score/) {
+ $inpuzzles = 1;
+ next;
+ }
+
+ # Notice that we're through reading the puzzle scores
+ if ($line =~ /^Total/) {
+ $inpuzzles = 0;
+ next;
+ }
+
+ # Read and record a puzzle's name and score
+ if ($inpuzzles) {
+ ($blank, $p_points, $p_rating, $p_errors, $name) = split(/\s+/, $line);
+ $puzzle_p_points{$name} = $p_points;
+ $total_p_points += $p_points;
+ $total_p_rating += $p_rating;
+ }
+}
+close(INFILE);
+
+#
+# Collect the operator counts generated by dlc
+#
+open(INFILE, "$tmpdir/dlc-opcount.out")
+ or die "$0: ERROR: could not open input file $tmpdir/dlc-opcount.out\n";
+
+$tops = 0;
+while ($line = <INFILE>) {
+ chomp($line);
+
+ if ($line =~ /(\d+) operators/) {
+ ($foo, $foo, $foo, $name, $msg) = split(/:/, $line);
+ $puzzle_p_ops{$name} = $1;
+ $tops += $1;
+ }
+}
+close(INFILE);
+
+#
+# Print a table of results sorted by puzzle number
+#
+print "\n";
+printf("%s\t%s\n", "Correctness Results", "Perf Results");
+printf("%s\t%s\t%s\t%s\t%s\t%s\n", "Points", "Rating", "Errors",
+ "Points", "Ops", "Puzzle");
+foreach $name (sort {$puzzle_number{$a} <=> $puzzle_number{$b}}
+ keys %puzzle_number) {
+ printf("%d\t%d\t%d\t%d\t%d\t\%s\n",
+ $puzzle_c_points{$name},
+ $puzzle_c_rating{$name},
+ $puzzle_c_errors{$name},
+ $puzzle_p_points{$name},
+ $puzzle_p_ops{$name},
+ $name);
+}
+
+$tpoints = $total_c_points + $total_p_points;
+$trating = $total_c_rating + $total_p_rating;
+
+print "\nScore = $tpoints/$trating [$total_c_points/$total_c_rating Corr + $total_p_points/$total_p_rating Perf] ($tops total operators)\n";
+
+#
+# Optionally send the autoresult to the contest server if the driver
+# was called with the -u command line flag.
+#
+if ($nickname) {
+ # Generate the autoresult
+ $autoresult = "$tpoints|$total_c_points|$total_p_points|$tops";
+ foreach $name (sort {$puzzle_number{$a} <=> $puzzle_number{$b}}
+ keys %puzzle_number) {
+ $autoresult .= " |$name:$puzzle_c_points{$name}:$puzzle_c_rating{$name}:$puzzle_p_points{$name}:$puzzle_p_ops{$name}";
+ }
+
+ # Post the autoresult to the server. The Linux login id is
+ # concatenated with the user-supplied nickname for some (very) loose
+ # authentication of submissions.
+ &Driverlib::driver_post("$login:$nickname", $autoresult, $autograded);
+}
+
+# Clean up and exit
+clean ($tmpdir);
+exit;
+
+##################
+# Helper functions
+#
+
+#
+# check_nickname - Check a nickname for legality
+#
+sub check_nickname {
+ my $nickname = shift;
+
+ # Nicknames can't be empty
+ if (length($nickname) < 1) {
+ die "$0: Error: Empty nickname.\n";
+ }
+
+ # Nicknames can't be too long
+ if (length($nickname) > 35) {
+ die "$0: Error: Nickname exceeds 35 characters.\n";
+ }
+
+ # Nicknames can have restricted set of metacharacters (e.g., no #
+ # HTML tags)
+ if (!($nickname =~ /^[_-\w.,'@ ]+$/)) {
+ die "$0: Error: Illegal character in nickname. Only alphanumerics, apostrophes, commas, periods, dashes, underscores, and ampersands are allowed.\n";
+ }
+
+ # Nicknames can't be all whitespace
+ if ($nickname =~ /^\s*$/) {
+ die "$0: Error: Nickname is all whitespace.\n";
+ }
+
+}
+
+#
+# clean - remove the scratch directory
+#
+sub clean {
+ my $tmpdir = shift;
+ system("rm -rf $tmpdir");
+}
+
diff --git a/labs/datalab/datalab-handout/fshow.c b/labs/datalab/datalab-handout/fshow.c
new file mode 100644
index 0000000..fc918f6
--- /dev/null
+++ b/labs/datalab/datalab-handout/fshow.c
@@ -0,0 +1,151 @@
+/* Display structure of floating-point numbers */
+
+#include <stdio.h>
+#include <stdlib.h>
+float strtof(const char *nptr, char **endptr);
+
+#define FLOAT_SIZE 32
+#define FRAC_SIZE 23
+#define EXP_SIZE 8
+#define BIAS ((1<<(EXP_SIZE-1))-1)
+#define FRAC_MASK ((1<<FRAC_SIZE)-1)
+#define EXP_MASK ((1<<EXP_SIZE)-1)
+
+/* Floating point helpers */
+unsigned f2u(float f)
+{
+ union {
+ unsigned u;
+ float f;
+ } v;
+ v.u = 0;
+ v.f = f;
+ return v.u;
+}
+
+static float u2f(unsigned u)
+{
+ union {
+ unsigned u;
+ float f;
+ } v;
+ v.u = u;
+ return v.f;
+}
+
+/* Get exponent */
+unsigned get_exp(unsigned uf)
+{
+ return (uf>>FRAC_SIZE) & EXP_MASK;
+}
+
+/* Get fraction */
+unsigned get_frac(unsigned uf)
+{
+ return uf & FRAC_MASK;
+}
+
+/* Get sign */
+unsigned get_sign(unsigned uf)
+{
+ return (uf>>(FLOAT_SIZE-1)) & 0x1;
+}
+
+void show_float(unsigned uf)
+{
+ float f = u2f(uf);
+ unsigned exp = get_exp(uf);
+ unsigned frac = get_frac(uf);
+ unsigned sign = get_sign(uf);
+
+ printf("\nFloating point value %.10g\n", f);
+ printf("Bit Representation 0x%.8x, sign = %x, exponent = 0x%.2x, fraction = 0x%.6x\n",
+ uf, sign, exp, frac);
+ if (exp == EXP_MASK) {
+ if (frac == 0) {
+ printf("%cInfinity\n", sign ? '-' : '+');
+ } else
+ printf("Not-A-Number\n");
+ } else {
+ int denorm = (exp == 0);
+ int uexp = denorm ? 1-BIAS : exp - BIAS;
+ int mantissa = denorm ? frac : frac + (1<<FRAC_SIZE);
+ float fman = (float) mantissa / (float) (1<<FRAC_SIZE);
+ printf("%s. %c%.10f X 2^(%d)\n",
+ denorm ? "Denormalized" : "Normalized",
+ sign ? '-' : '+',
+ fman, uexp);
+ }
+}
+
+/* Extract hex/decimal/or float value from string */
+static int get_num_val(char *sval, unsigned *valp) {
+ char *endp;
+ /* See if it's an integer or floating point */
+ int ishex = 0;
+ int isfloat = 0;
+ int i;
+ for (i = 0; sval[i]; i++) {
+ switch (sval[i]) {
+ case 'x':
+ case 'X':
+ ishex = 1;
+ break;
+ case 'e':
+ case 'E':
+ if (!ishex)
+ isfloat = 1;
+ break;
+ case '.':
+ isfloat = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ if (isfloat) {
+ float fval = strtof(sval, &endp);
+ if (!*endp) {
+ *valp = *(unsigned *) &fval;
+ return 1;
+ }
+ return 0;
+ } else {
+ long long int llval = strtoll(sval, &endp, 0);
+ long long int upperbits = llval >> 31;
+ /* will give -1 for negative, 0 or 1 for positive */
+ if (valp && (upperbits == 0 || upperbits == -1 || upperbits == 1)) {
+ *valp = (unsigned) llval;
+ return 1;
+ }
+ return 0;
+ }
+}
+
+
+void usage(char *fname) {
+ printf("Usage: %s val1 val2 ...\n", fname);
+ printf("Values may be given as hex patterns or as floating point numbers\n");
+ exit(0);
+}
+
+
+int main(int argc, char *argv[])
+{
+ int i;
+ unsigned uf;
+ if (argc < 2)
+ usage(argv[0]);
+ for (i = 1; i < argc; i++) {
+ char *sval = argv[i];
+ if (get_num_val(sval, &uf)) {
+ show_float(uf);
+ } else {
+ printf("Invalid 32-bit number: '%s'\n", sval);
+ usage(argv[0]);
+ }
+ }
+ return 0;
+}
+
+
diff --git a/labs/datalab/datalab-handout/ishow.c b/labs/datalab/datalab-handout/ishow.c
new file mode 100644
index 0000000..ffb1df7
--- /dev/null
+++ b/labs/datalab/datalab-handout/ishow.c
@@ -0,0 +1,75 @@
+/* Display value of fixed point numbers */
+#include <stdlib.h>
+#include <stdio.h>
+
+/* Extract hex/decimal/or float value from string */
+static int get_num_val(char *sval, unsigned *valp) {
+ char *endp;
+ /* See if it's an integer or floating point */
+ int ishex = 0;
+ int isfloat = 0;
+ int i;
+ for (i = 0; sval[i]; i++) {
+ switch (sval[i]) {
+ case 'x':
+ case 'X':
+ ishex = 1;
+ break;
+ case 'e':
+ case 'E':
+ if (!ishex)
+ isfloat = 1;
+ break;
+ case '.':
+ isfloat = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ if (isfloat) {
+ return 0; /* Not supposed to have a float here */
+ } else {
+ long long int llval = strtoll(sval, &endp, 0);
+ long long int upperbits = llval >> 31;
+ /* will give -1 for negative, 0 or 1 for positive */
+ if (valp && (upperbits == 0 || upperbits == -1 || upperbits == 1)) {
+ *valp = (unsigned) llval;
+ return 1;
+ }
+ return 0;
+ }
+}
+
+void show_int(unsigned uf)
+{
+ printf("Hex = 0x%.8x,\tSigned = %d,\tUnsigned = %u\n",
+ uf, (int) uf, uf);
+}
+
+
+void usage(char *fname) {
+ printf("Usage: %s val1 val2 ...\n", fname);
+ printf("Values may be given in hex or decimal\n");
+ exit(0);
+}
+
+int main(int argc, char *argv[])
+{
+ int i;
+ unsigned uf;
+ if (argc < 2)
+ usage(argv[0]);
+ for (i = 1; i < argc; i++) {
+ char *sval = argv[i];
+ if (get_num_val(sval, &uf)) {
+ show_int(uf);
+ } else {
+ printf("Cannot convert '%s' to 32-bit number\n", sval);
+ }
+ }
+ return 0;
+}
+
+
+
diff --git a/labs/datalab/datalab-handout/tests.c b/labs/datalab/datalab-handout/tests.c
new file mode 100644
index 0000000..38eb9c6
--- /dev/null
+++ b/labs/datalab/datalab-handout/tests.c
@@ -0,0 +1,118 @@
+/* Testing Code */
+
+#include <limits.h>
+#include <math.h>
+
+/* Routines used by floation point test code */
+
+/* Convert from bit level representation to floating point number */
+float u2f(unsigned u) {
+ union {
+ unsigned u;
+ float f;
+ } a;
+ a.u = u;
+ return a.f;
+}
+
+/* Convert from floating point number to bit-level representation */
+unsigned f2u(float f) {
+ union {
+ unsigned u;
+ float f;
+ } a;
+ a.f = f;
+ return a.u;
+}
+
+//1
+int test_bitXor(int x, int y)
+{
+ return x^y;
+}
+int test_tmin(void) {
+ return 0x80000000;
+}
+//2
+int test_isTmax(int x) {
+ return x == 0x7FFFFFFF;
+}
+int test_allOddBits(int x) {
+ int i;
+ for (i = 1; i < 32; i+=2)
+ if ((x & (1<<i)) == 0)
+ return 0;
+ return 1;
+}
+
+
+
+
+
+
+
+int test_negate(int x) {
+ return -x;
+}
+//3
+
+
+int test_isAsciiDigit(int x) {
+ return (0x30 <= x) && (x <= 0x39);
+}
+int test_conditional(int x, int y, int z)
+{
+ return x?y:z;
+}
+int test_isLessOrEqual(int x, int y)
+{
+ return x <= y;
+}
+//4
+int test_logicalNeg(int x)
+{
+ return !x;
+}
+int test_howManyBits(int x) {
+ unsigned int a, cnt;
+ x = x<0 ? -x-1 : x;
+ a = (unsigned int)x;
+ for (cnt=0; a; a>>=1, cnt++)
+ ;
+
+ return (int)(cnt + 1);
+}
+//float
+unsigned test_floatScale2(unsigned uf) {
+ float f = u2f(uf);
+ float tf = 2*f;
+ if (isnan(f))
+ return uf;
+ else
+ return f2u(tf);
+}
+int test_floatFloat2Int(unsigned uf) {
+ float f = u2f(uf);
+ int x = (int) f;
+ return x;
+}
+unsigned test_floatPower2(int x) {
+ float result = 1.0;
+ float p2 = 2.0;
+ int recip = (x < 0);
+ /* treat tmin specially */
+ if ((unsigned)x == 0x80000000) {
+ return 0;
+ }
+ if (recip) {
+ x = -x;
+ p2 = 0.5;
+ }
+ while (x > 0) {
+ if (x & 0x1)
+ result = result * p2;
+ p2 = p2 * p2;
+ x >>= 1;
+ }
+ return f2u(result);
+}