/* YOUR FILE-HEADER COMMENT HERE */ #include #include #include #include /** * Perform 16-bit unsigned integer multiplication of @a i1 and @a i2, * returning the 32-bit product. * * SPECIAL RESTRICTION: You may only use addition, subtraction, * shifts, rotate, bitmasks, compare, and branch operations. You * may not use any built-in multiplication, division, * nor modulo division instructions for this part. * * @param[in] i1 Multiplicand * @param[in] i2 Multiplier * @return 32-bit product */ static uint32_t uint16_mult(uint16_t i1, uint16_t i2) { /* PART 1: YOUR CODE HERE */ return 0; } /** * Given a 16-bit binary value representing a IEEE-754 half-precision * floating point value, determine if that value is normal or not * (denormal, zero, infinity, NaN). * * @param[in] val 16-bit floating point value to analyze. * @return true if @a val is a normal floating point value, false * otherwise */ static bool is_half_float_normal(uint16_t val) { /* PART 2: YOUR CODE HERE */ return false; } /** * Given two IEEE-754 half-precision floating point normal values, * calculate their product. Assume the product will also be a normal * value. It is your responsibility to re-normalize the product. * * SPECIAL RESTRICTION: You must use your uint16_mult() function when * calculating the significand. * * NOTE: Because of floating point rounding, your calculated LSB may * differ from the native C implementation by one digit. You are not * required to implement rounding. * * @param[in] val1 First 16-bit floating point value to multiply. * @param[in] val2 Second 16-bit floating point value to multiply. * @return 16-bit floating point product */ static uint16_t half_float_mult(uint16_t val1, uint16_t val2) { /* PART 2: YOUR CODE HERE */ return 0; } int main(int argc, char *argv[]) { if (argc < 3) { fprintf(stderr, "Need at least two arguments\n"); exit(EXIT_FAILURE); } char *endptr; unsigned long long arg1 = strtoull(argv[1], &endptr, 0); if (!(*(argv[1])) || *endptr) { fprintf(stderr, "Argument 1 not a number: %s\n", argv[1]); exit(EXIT_FAILURE); } unsigned long long arg2 = strtoull(argv[2], &endptr, 0); if (!*(argv[2]) || *endptr) { fprintf(stderr, "Argument 2 not a number: %s\n", argv[2]); exit(EXIT_FAILURE); } printf("Part 1:\n"); uint16_t i1 = (uint16_t) arg1; uint16_t i2 = (uint16_t) arg2; uint32_t true_prod = i1 * i2; printf(" unsigned integer multiply 0x%04X and 0x%04X:\n", i1, i2); printf(" correct result: 0X%06X\n", true_prod); uint32_t your_prod = uint16_mult(i1, i2); printf(" your result: 0X%06X\n", your_prod); printf("Part 2:\n"); bool is_arg1_normal; bool is_arg2_normal; is_arg1_normal = is_half_float_normal(i1); is_arg2_normal = is_half_float_normal(i2); printf(" 0x%04x is %s\n", i1, (is_arg1_normal ? "normal" : "not normal")); printf(" 0x%04x is %s\n", i2, (is_arg2_normal ? "normal" : "not normal")); if (!is_arg1_normal || !is_arg2_normal) { exit(EXIT_FAILURE); } _Float16 f1 = *((_Float16 *) &i1); _Float16 f2 = *((_Float16 *) &i2); _Float16 true_float_prod = f1 * f2; uint16_t true_float_prod_val = *((uint16_t *) &(true_float_prod)); printf(" half-float multiply %g and %g:\n", (float) f1, (float) f2); printf(" correct result: 0x%04X\n", true_float_prod_val); uint16_t your_float_prod = half_float_mult(i1, i2); printf(" your result: 0x%04X\n", your_float_prod); return 0; }