Finished LAB2 bitAnd
This commit is contained in:
parent
599da2ed23
commit
bf5acaaeb8
|
@ -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;
|
|
@ -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;
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
#
|
||||
# Makefile that builds btest and other helper programs for the CS:APP data lab
|
||||
#
|
||||
CC = gcc
|
||||
CFLAGS = -O -Wall -m32
|
||||
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 *~
|
||||
|
||||
|
|
@ -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)
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,306 @@
|
|||
/*
|
||||
* 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 an integer by more
|
||||
than the word size.
|
||||
|
||||
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 implent 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 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 operators (! ~ & ^ | + << >>)
|
||||
that you are allowed to use for your implementation of the function.
|
||||
The max operator count is checked by dlc. Note that '=' 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
|
||||
/*
|
||||
* bitAnd - x&y using only ~ and |
|
||||
* Example: bitAnd(6, 5) = 4
|
||||
* Legal ops: ~ |
|
||||
* Max ops: 8
|
||||
* Rating: 1
|
||||
*/
|
||||
int bitAnd(int x, int y) {
|
||||
//Just discrete mathematics. XY=\overline{X+Y}.
|
||||
return ~(x|y);
|
||||
}
|
||||
/*
|
||||
* getByte - Extract byte n from word x
|
||||
* Bytes numbered from 0 (LSB) to 3 (MSB)
|
||||
* Examples: getByte(0x12345678,1) = 0x56
|
||||
* Legal ops: ! ~ & ^ | + << >>
|
||||
* Max ops: 6
|
||||
* Rating: 2
|
||||
*/
|
||||
int getByte(int x, int n) {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return 2;
|
||||
|
||||
}
|
||||
/*
|
||||
* logicalShift - shift x to the right by n, using a logical shift
|
||||
* Can assume that 0 <= n <= 31
|
||||
* Examples: logicalShift(0x87654321,4) = 0x08765432
|
||||
* Legal ops: ! ~ & ^ | + << >>
|
||||
* Max ops: 20
|
||||
* Rating: 3
|
||||
*/
|
||||
int logicalShift(int x, int n) {
|
||||
return 2;
|
||||
}
|
||||
/*
|
||||
* bitCount - returns count of number of 1's in word
|
||||
* Examples: bitCount(5) = 2, bitCount(7) = 3
|
||||
* Legal ops: ! ~ & ^ | + << >>
|
||||
* Max ops: 40
|
||||
* Rating: 4
|
||||
*/
|
||||
int bitCount(int x) {
|
||||
return 2;
|
||||
}
|
||||
/*
|
||||
* bang - Compute !x without using !
|
||||
* Examples: bang(3) = 0, bang(0) = 1
|
||||
* Legal ops: ~ & ^ | + << >>
|
||||
* Max ops: 12
|
||||
* Rating: 4
|
||||
*/
|
||||
int bang(int x) {
|
||||
return 2;
|
||||
}
|
||||
/*
|
||||
* tmin - return minimum two's complement integer
|
||||
* Legal ops: ! ~ & ^ | + << >>
|
||||
* Max ops: 4
|
||||
* Rating: 1
|
||||
*/
|
||||
int tmin(void) {
|
||||
return 2;
|
||||
}
|
||||
/*
|
||||
* fitsBits - return 1 if x can be represented as an
|
||||
* n-bit, two's complement integer.
|
||||
* 1 <= n <= 32
|
||||
* Examples: fitsBits(5,3) = 0, fitsBits(-4,3) = 1
|
||||
* Legal ops: ! ~ & ^ | + << >>
|
||||
* Max ops: 15
|
||||
* Rating: 2
|
||||
*/
|
||||
int fitsBits(int x, int n) {
|
||||
return 2;
|
||||
}
|
||||
/*
|
||||
* divpwr2 - Compute x/(2^n), for 0 <= n <= 30
|
||||
* Round toward zero
|
||||
* Examples: divpwr2(15,1) = 7, divpwr2(-33,4) = -2
|
||||
* Legal ops: ! ~ & ^ | + << >>
|
||||
* Max ops: 15
|
||||
* Rating: 2
|
||||
*/
|
||||
int divpwr2(int x, int n) {
|
||||
return 2;
|
||||
}
|
||||
/*
|
||||
* negate - return -x
|
||||
* Example: negate(1) = -1.
|
||||
* Legal ops: ! ~ & ^ | + << >>
|
||||
* Max ops: 5
|
||||
* Rating: 2
|
||||
*/
|
||||
int negate(int x) {
|
||||
return 2;
|
||||
}
|
||||
/*
|
||||
* isPositive - return 1 if x > 0, return 0 otherwise
|
||||
* Example: isPositive(-1) = 0.
|
||||
* Legal ops: ! ~ & ^ | + << >>
|
||||
* Max ops: 8
|
||||
* Rating: 3
|
||||
*/
|
||||
int isPositive(int x) {
|
||||
return 2;
|
||||
}
|
||||
/*
|
||||
* 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) {
|
||||
return 2;
|
||||
}
|
||||
/*
|
||||
* ilog2 - return floor(log base 2 of x), where x > 0
|
||||
* Example: ilog2(16) = 4
|
||||
* Legal ops: ! ~ & ^ | + << >>
|
||||
* Max ops: 90
|
||||
* Rating: 4
|
||||
*/
|
||||
int ilog2(int x) {
|
||||
return 2;
|
||||
}
|
||||
/*
|
||||
* float_neg - Return bit-level equivalent of expression -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 representations of
|
||||
* single-precision floating point values.
|
||||
* When argument is NaN, return argument.
|
||||
* Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
|
||||
* Max ops: 10
|
||||
* Rating: 2
|
||||
*/
|
||||
unsigned float_neg(unsigned uf) {
|
||||
return 2;
|
||||
}
|
||||
/*
|
||||
* float_i2f - Return bit-level equivalent of expression (float) x
|
||||
* Result is returned as unsigned int, but
|
||||
* it is to be interpreted as the bit-level representation of a
|
||||
* single-precision floating point values.
|
||||
* Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
|
||||
* Max ops: 30
|
||||
* Rating: 4
|
||||
*/
|
||||
unsigned float_i2f(int x) {
|
||||
return 2;
|
||||
}
|
||||
/*
|
||||
* float_twice - 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 float_twice(unsigned uf) {
|
||||
return 2;
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
|
||||
int bitAnd(int, int);
|
||||
int test_bitAnd(int, int);
|
||||
int getByte(int, int);
|
||||
int test_getByte(int, int);
|
||||
int logicalShift(int, int);
|
||||
int test_logicalShift(int, int);
|
||||
int bitCount(int);
|
||||
int test_bitCount(int);
|
||||
int bang(int);
|
||||
int test_bang(int);
|
||||
int tmin();
|
||||
int test_tmin();
|
||||
int fitsBits(int, int);
|
||||
int test_fitsBits(int, int);
|
||||
int divpwr2(int, int);
|
||||
int test_divpwr2(int, int);
|
||||
int negate(int);
|
||||
int test_negate(int);
|
||||
int isPositive(int);
|
||||
int test_isPositive(int);
|
||||
int isLessOrEqual(int, int);
|
||||
int test_isLessOrEqual(int, int);
|
||||
int ilog2(int);
|
||||
int test_ilog2(int);
|
||||
unsigned float_neg(unsigned);
|
||||
unsigned test_float_neg(unsigned);
|
||||
unsigned float_i2f(int);
|
||||
unsigned test_float_i2f(int);
|
||||
unsigned float_twice(unsigned);
|
||||
unsigned test_float_twice(unsigned);
|
|
@ -0,0 +1,584 @@
|
|||
/*
|
||||
* 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[])
|
||||
{
|
||||
int errors;
|
||||
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 */
|
||||
errors = run_tests();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -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[];
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
#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[] = {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{"bitAnd", (funct_t) bitAnd, (funct_t) test_bitAnd, 2, "| ~", 8, 1,
|
||||
{{TMin, TMax},{TMin,TMax},{TMin,TMax}}},
|
||||
{"getByte", (funct_t) getByte, (funct_t) test_getByte, 2,
|
||||
"! ~ & ^ | + << >>", 6, 2,
|
||||
{{TMin, TMax},{0,3},{TMin,TMax}}},
|
||||
{"logicalShift", (funct_t) logicalShift, (funct_t) test_logicalShift,
|
||||
2, "! ~ & ^ | + << >>", 20, 3,
|
||||
{{TMin, TMax},{0,31},{TMin,TMax}}},
|
||||
{"bitCount", (funct_t) bitCount, (funct_t) test_bitCount, 1, "! ~ & ^ | + << >>", 40, 4,
|
||||
{{TMin, TMax},{TMin,TMax},{TMin,TMax}}},
|
||||
{"bang", (funct_t) bang, (funct_t) test_bang, 1,
|
||||
"~ & ^ | + << >>", 12, 4,
|
||||
{{TMin, TMax},{TMin,TMax},{TMin,TMax}}},
|
||||
{"tmin", (funct_t) tmin, (funct_t) test_tmin, 0, "! ~ & ^ | + << >>", 4, 1,
|
||||
{{TMin, TMax},{TMin,TMax},{TMin,TMax}}},
|
||||
{"fitsBits", (funct_t) fitsBits, (funct_t) test_fitsBits, 2,
|
||||
"! ~ & ^ | + << >>", 15, 2,
|
||||
{{TMin, TMax},{1,32},{TMin,TMax}}},
|
||||
{"divpwr2", (funct_t) divpwr2, (funct_t) test_divpwr2, 2,
|
||||
"! ~ & ^ | + << >>", 15, 2,
|
||||
{{TMin, TMax},{0,30},{TMin,TMax}}},
|
||||
{"negate", (funct_t) negate, (funct_t) test_negate, 1,
|
||||
"! ~ & ^ | + << >>", 5, 2,
|
||||
{{TMin, TMax},{TMin,TMax},{TMin,TMax}}},
|
||||
{"isPositive", (funct_t) isPositive, (funct_t) test_isPositive, 1,
|
||||
"! ~ & ^ | + << >>", 8, 3,
|
||||
{{TMin, TMax},{TMin,TMax},{TMin,TMax}}},
|
||||
{"isLessOrEqual", (funct_t) isLessOrEqual, (funct_t) test_isLessOrEqual, 2,
|
||||
"! ~ & ^ | + << >>", 24, 3,
|
||||
{{TMin, TMax},{TMin,TMax},{TMin,TMax}}},
|
||||
{"ilog2", (funct_t) ilog2, (funct_t) test_ilog2, 1, "! ~ & ^ | + << >>", 90, 4,
|
||||
{{1, TMax},{TMin,TMax},{TMin,TMax}}},
|
||||
{"float_neg", (funct_t) float_neg, (funct_t) test_float_neg, 1,
|
||||
"$", 10, 2,
|
||||
{{1, 1},{1,1},{1,1}}},
|
||||
{"float_i2f", (funct_t) float_i2f, (funct_t) test_float_i2f, 1,
|
||||
"$", 30, 4,
|
||||
{{1, 1},{1,1},{1,1}}},
|
||||
{"float_twice", (funct_t) float_twice, (funct_t) test_float_twice, 1,
|
||||
"$", 30, 4,
|
||||
{{1, 1},{1,1},{1,1}}},
|
||||
{"", NULL, NULL, 0, "", 0, 0,
|
||||
{{0, 0},{0,0},{0,0}}}
|
||||
};
|
Binary file not shown.
|
@ -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");
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
/* 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;
|
||||
}
|
||||
|
||||
int test_bitAnd(int x, int y)
|
||||
{
|
||||
return x&y;
|
||||
}
|
||||
int test_getByte(int x, int n)
|
||||
{
|
||||
unsigned char byte;
|
||||
switch(n) {
|
||||
case 0:
|
||||
byte = x;
|
||||
break;
|
||||
case 1:
|
||||
byte = x >> 8;
|
||||
break;
|
||||
case 2:
|
||||
byte = x >> 16;
|
||||
break;
|
||||
default:
|
||||
byte = x >> 24;
|
||||
break;
|
||||
}
|
||||
return (int) (unsigned) byte;
|
||||
}
|
||||
int test_logicalShift(int x, int n) {
|
||||
unsigned u = (unsigned) x;
|
||||
unsigned shifted = u >> n;
|
||||
return (int) shifted;
|
||||
}
|
||||
int test_bitCount(int x) {
|
||||
int result = 0;
|
||||
int i;
|
||||
for (i = 0; i < 32; i++)
|
||||
result += (x >> i) & 0x1;
|
||||
return result;
|
||||
}
|
||||
int test_bang(int x)
|
||||
{
|
||||
return !x;
|
||||
}
|
||||
int test_tmin(void) {
|
||||
return 0x80000000;
|
||||
}
|
||||
int test_fitsBits(int x, int n)
|
||||
{
|
||||
int TMin_n = -(1 << (n-1));
|
||||
int TMax_n = (1 << (n-1)) - 1;
|
||||
return x >= TMin_n && x <= TMax_n;
|
||||
}
|
||||
int test_divpwr2(int x, int n)
|
||||
{
|
||||
int p2n = 1<<n;
|
||||
return x/p2n;
|
||||
}
|
||||
int test_negate(int x) {
|
||||
return -x;
|
||||
}
|
||||
int test_isPositive(int x) {
|
||||
return x > 0;
|
||||
}
|
||||
int test_isLessOrEqual(int x, int y)
|
||||
{
|
||||
return x <= y;
|
||||
}
|
||||
int test_ilog2(int x) {
|
||||
int mask, result;
|
||||
/* find the leftmost bit */
|
||||
result = 31;
|
||||
mask = 1 << result;
|
||||
while (!(x & mask)) {
|
||||
result--;
|
||||
mask = 1 << result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
unsigned test_float_neg(unsigned uf) {
|
||||
float f = u2f(uf);
|
||||
float nf = -f;
|
||||
if (isnan(f))
|
||||
return uf;
|
||||
else
|
||||
return f2u(nf);
|
||||
}
|
||||
unsigned test_float_i2f(int x) {
|
||||
float f = (float) x;
|
||||
return f2u(f);
|
||||
}
|
||||
unsigned test_float_twice(unsigned uf) {
|
||||
float f = u2f(uf);
|
||||
float tf = 2*f;
|
||||
if (isnan(f))
|
||||
return uf;
|
||||
else
|
||||
return f2u(tf);
|
||||
}
|
Loading…
Reference in New Issue