Implement floating point size conversions (with help from BitVector).

Interface changed slightly (only affects symrec.c right now).  Tests committed
to check a single case (pi) with all three size conversion functions.
Still need to write to/from ASCII string functions (the hard part).

svn path=/trunk/yasm/; revision=247
0.3
Peter Johnson 23 years ago
parent 0baab0debd
commit 279abb1b37
  1. 230
      libyasm/floatnum.c
  2. 36
      libyasm/floatnum.h
  3. 4
      libyasm/symrec.c
  4. 9
      libyasm/tests/Makefile.am
  5. 122
      libyasm/tests/floatnum_test.c
  6. 230
      src/floatnum.c
  7. 36
      src/floatnum.h
  8. 4
      src/symrec.c
  9. 9
      src/tests/Makefile.am
  10. 122
      src/tests/floatnum_test.c

@ -3,6 +3,8 @@
*
* Copyright (C) 2001 Peter Johnson
*
* Based on public-domain x86 assembly code by Randall Hyde (8/28/91).
*
* This file is part of YASM.
*
* YASM is free software; you can redistribute it and/or modify
@ -29,8 +31,20 @@
#ifdef STDC_HEADERS
# include <stdlib.h>
# include <string.h>
#endif
#include <libintl.h>
#define _(String) gettext(String)
#ifdef gettext_noop
#define N_(String) gettext_noop(String)
#else
#define N_(String) (String)
#endif
#include "bitvect.h"
#include "file.h"
#include "errwarn.h"
#include "floatnum.h"
@ -42,36 +56,224 @@ floatnum_new(char *str)
floatnum *flt = malloc(sizeof(floatnum));
if (!flt)
Fatal(FATAL_NOMEM);
/* TODO */
flt->mantissa = BitVector_Create(64, TRUE);
if (!flt->mantissa)
Fatal(FATAL_NOMEM);
/* check for + or - character and skip */
if (*str == '-') {
flt->sign = 1;
str++;
} else if (*str == '+') {
flt->sign = 0;
str++;
} else
flt->sign = 0;
return flt;
}
unsigned long
floatnum_get_int(floatnum *flt)
int
floatnum_get_int(unsigned long *ret_val, const floatnum *flt)
{
return 0; /* TODO */
unsigned char t[4];
if (floatnum_get_single(t, flt))
return 1;
LOAD_LONG(*ret_val, &t[0]);
return 0;
}
unsigned char *
floatnum_get_single(unsigned char *ptr, floatnum *flt)
/* IEEE-754 (Intel) "single precision" format:
* 32 bits:
* Bit 31 Bit 22 Bit 0
* | | |
* seeeeeee emmmmmmm mmmmmmmm mmmmmmmm
*
* e = bias 127 exponent
* s = sign bit
* m = mantissa bits, bit 23 is an implied one bit.
*/
int
floatnum_get_single(unsigned char *ptr, const floatnum *flt)
{
return ptr; /* TODO */
unsigned long exponent = flt->exponent;
unsigned int *output;
unsigned char *buf;
unsigned int len;
output = BitVector_Create(32, TRUE);
if (!output)
Fatal(FATAL_NOMEM);
/* copy mantissa */
BitVector_Interval_Copy(output, flt->mantissa, 0, 40, 23);
/* round mantissa */
BitVector_increment(output);
if (BitVector_bit_test(output, 23)) {
/* overflowed, so divide mantissa by 2 (shift right) */
BitVector_shift_right(output, 0);
/* and up the exponent (checking for overflow) */
if (exponent+1 >= 0x10000) {
BitVector_Destroy(output);
return 1; /* exponent too large */
}
exponent++;
}
/* adjust the exponent to bias 127 */
exponent -= 32767-127;
if (exponent >= 256) {
BitVector_Destroy(output);
return 1; /* exponent too large */
}
/* move exponent into place */
BitVector_Chunk_Store(output, 8, 23, exponent);
/* merge in sign bit */
BitVector_Bit_Copy(output, 31, flt->sign);
/* get little-endian bytes */
buf = BitVector_Block_Read(output, &len);
if (!buf)
Fatal(FATAL_NOMEM);
if (len != 4)
InternalError(__LINE__, __FILE__,
_("Length of 32-bit BitVector not 4"));
/* copy to output */
memcpy(ptr, buf, 4*sizeof(unsigned char));
/* free allocated resources */
free(buf);
BitVector_Destroy(output);
return 0;
}
unsigned char *
floatnum_get_double(unsigned char *ptr, floatnum *flt)
/* IEEE-754 (Intel) "double precision" format:
* 64 bits:
* bit 63 bit 51 bit 0
* | | |
* seeeeeee eeeemmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm
*
* e = bias 1023 exponent.
* s = sign bit.
* m = mantissa bits. Bit 52 is an implied one bit.
*/
int
floatnum_get_double(unsigned char *ptr, const floatnum *flt)
{
return ptr; /* TODO */
unsigned long exponent = flt->exponent;
unsigned int *output;
unsigned char *buf;
unsigned int len;
output = BitVector_Create(64, TRUE);
if (!output)
Fatal(FATAL_NOMEM);
/* copy mantissa */
BitVector_Interval_Copy(output, flt->mantissa, 0, 11, 52);
/* round mantissa */
BitVector_increment(output);
if (BitVector_bit_test(output, 52)) {
/* overflowed, so divide mantissa by 2 (shift right) */
BitVector_shift_right(output, 0);
/* and up the exponent (checking for overflow) */
if (exponent+1 >= 0x10000) {
BitVector_Destroy(output);
return 1; /* exponent too large */
}
exponent++;
}
/* adjust the exponent to bias 1023 */
exponent -= 32767-1023;
if (exponent >= 2048) {
BitVector_Destroy(output);
return 1; /* exponent too large */
}
/* move exponent into place */
BitVector_Chunk_Store(output, 11, 52, exponent);
/* merge in sign bit */
BitVector_Bit_Copy(output, 63, flt->sign);
/* get little-endian bytes */
buf = BitVector_Block_Read(output, &len);
if (!buf)
Fatal(FATAL_NOMEM);
if (len != 8)
InternalError(__LINE__, __FILE__,
_("Length of 64-bit BitVector not 8"));
/* copy to output */
memcpy(ptr, buf, 8*sizeof(unsigned char));
/* free allocated resources */
free(buf);
BitVector_Destroy(output);
return 0;
}
unsigned char *
floatnum_get_extended(unsigned char *ptr, floatnum *flt)
/* IEEE-754 (Intel) "extended precision" format:
* 80 bits:
* bit 79 bit 63 bit 0
* | | |
* seeeeeee eeeeeeee mmmmmmmm m...m m...m m...m m...m m...m
*
* e = bias 16384 exponent
* m = 64 bit mantissa with NO implied bit!
* s = sign (for mantissa)
*/
int
floatnum_get_extended(unsigned char *ptr, const floatnum *flt)
{
return ptr; /* TODO */
unsigned short exponent = flt->exponent;
unsigned char *buf;
unsigned int len;
/* Adjust the exponent to bias 16384 */
exponent -= 0x4000;
if (exponent >= 0x8000)
return 1; /* exponent too large */
/* get little-endian bytes */
buf = BitVector_Block_Read(flt->mantissa, &len);
if (!buf)
Fatal(FATAL_NOMEM);
if (len != 8)
InternalError(__LINE__, __FILE__,
_("Length of 64-bit BitVector not 8"));
/* copy to output */
memcpy(ptr, buf, 8*sizeof(unsigned char));
/* Save exponent and sign in proper location */
SAVE_SHORT(&ptr[8], exponent);
if (flt->sign)
ptr[9] |= 0x80;
/* free allocated resources */
free(buf);
return 0;
}
void
floatnum_print(floatnum *flt)
floatnum_print(const floatnum *flt)
{
/* TODO */
}

@ -3,6 +3,8 @@
*
* Copyright (C) 2001 Peter Johnson
*
* Based on public-domain x86 assembly code by Randall Hyde (8/28/91).
*
* This file is part of YASM.
*
* YASM is free software; you can redistribute it and/or modify
@ -22,16 +24,38 @@
#ifndef YASM_FLOATNUM_H
#define YASM_FLOATNUM_H
/* 88-bit internal floating point format:
* xxxxxxxs eeeeeeee eeeeeeee m..m m..m m..m m..m m..m m..m m..m m..m
* Sign exponent mantissa (64 bits)
* | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0|
* 63 55 47 39 31 23 15 7 0
*
* Only L.O. bit of Sign byte is significant. The rest is garbage.
* Exponent is bias 32767 exponent.
* Mantissa does NOT have an implied one bit (it's explicit).
*/
typedef struct floatnum_s {
unsigned char extval[10]; /* float stored in extended precision */
unsigned int *mantissa; /* Allocated to 64 bits */
unsigned short exponent;
unsigned char sign;
} floatnum;
floatnum *floatnum_new(char *str);
unsigned long floatnum_get_int(floatnum *flt);
unsigned char *floatnum_get_single(unsigned char *ptr, floatnum *flt);
unsigned char *floatnum_get_double(unsigned char *ptr, floatnum *flt);
unsigned char *floatnum_get_extended(unsigned char *ptr, floatnum *flt);
void floatnum_print(floatnum *flt);
/* The get functions return nonzero if flt can't fit into that size format. */
/* Essentially a convert to single-precision and return as 32-bit value.
* The 32-bit value is a "standard" C value (eg, of unknown endian).
*/
int floatnum_get_int(unsigned long *ret_val, const floatnum *flt);
/* ptr will point to the Intel-format little-endian byte string after a
* successful call (eg, [0] should be the first byte output to the file).
*/
int floatnum_get_single(unsigned char *ptr, const floatnum *flt);
int floatnum_get_double(unsigned char *ptr, const floatnum *flt);
int floatnum_get_extended(unsigned char *ptr, const floatnum *flt);
void floatnum_print(const floatnum *flt);
#endif

@ -173,7 +173,9 @@ symrec_get_int_value(const symrec *sym, unsigned long *ret_val,
*ret_val = sym->value.int_val;
break;
case SYM_CONSTANT_FLOAT:
*ret_val = floatnum_get_int(sym->value.flt);
/* FIXME: Line number on this error will be incorrect. */
if (floatnum_get_int(ret_val, sym->value.flt))
Error(_("Floating point value cannot fit in 32-bit single precision"));
break;
case SYM_LABEL:
if (!bytecode_get_offset(sym->value.label.sect,

@ -4,10 +4,12 @@ CFLAGS = @ANSI_CFLAGS@
if CHECK
TESTS = \
bytecode_test
bytecode_test \
floatnum_test
noinst_PROGRAMS = \
bytecode_test
bytecode_test \
floatnum_test
else
TESTS =
noinst_PROGRAMS =
@ -16,6 +18,9 @@ endif
bytecode_test_SOURCES = \
bytecode_test.c
floatnum_test_SOURCES = \
floatnum_test.c
INCLUDES= -I$(top_srcdir) -I$(top_srcdir)/src -I$(top_srcdir)/check
LDADD = \
$(top_builddir)/check/libcheck.a \

@ -0,0 +1,122 @@
/* $IdPath$
*
*/
#include <stdlib.h>
#include "check.h"
#include "bitvect.h"
#include "floatnum.h"
floatnum *flt;
void get_family_setup(void)
{
flt = malloc(sizeof(floatnum));
flt->mantissa = BitVector_Create(64, TRUE);
}
void get_family_teardown(void)
{
BitVector_Destroy(flt->mantissa);
free(flt);
}
void pi_setup(void)
{
/* test value: 3.141592653589793 */
/* 80-bit little endian hex: E9 BD 68 21 A2 DA 0F C9 00 40 */
unsigned char val[] = {0xE9, 0xBD, 0x68, 0x21, 0xA2, 0xDA, 0x0F, 0xC9};
unsigned char sign = 0;
unsigned short exp = 32767 + 1;
BitVector_Block_Store(flt->mantissa, val, 8);
flt->sign = sign;
flt->exponent = exp;
}
START_TEST(test_get_single_pi)
{
unsigned char outval[] = {0x00, 0x00, 0x00, 0x00};
unsigned char correct[] = {0xDB, 0x0F, 0x49, 0x40};
int i;
pi_setup();
fail_unless(floatnum_get_single(outval, flt) == 0,
"Should not fail on this value");
/* Compare result with what we should get. */
for (i=0;i<4;i++)
fail_unless(outval[i] == correct[i], "Invalid result generated");
}
END_TEST
START_TEST(test_get_double_pi)
{
unsigned char outval[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
unsigned char correct[] = {0x18, 0x2D, 0x44, 0x54, 0xFB, 0x21, 0x09, 0x40};
int i;
pi_setup();
fail_unless(floatnum_get_double(outval, flt) == 0,
"Should not fail on this value");
/* Compare result with what we should get. */
for (i=0;i<8;i++)
fail_unless(outval[i] == correct[i], "Invalid result generated");
}
END_TEST
START_TEST(test_get_extended_pi)
{
unsigned char outval[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
unsigned char correct[] = {0xE9, 0xBD, 0x68, 0x21, 0xA2, 0xDA, 0x0F, 0xC9, 0x00, 0x40};
int i;
pi_setup();
fail_unless(floatnum_get_extended(outval, flt) == 0,
"Should not fail on this value");
/* Compare result with what we should get. */
for (i=0;i<10;i++)
fail_unless(outval[i] == correct[i], "Invalid result generated");
}
END_TEST
Suite *bytecode_suite(void)
{
Suite *s = suite_create("floatnum");
TCase *tc_get_single = tcase_create("get_single");
TCase *tc_get_double = tcase_create("get_double");
TCase *tc_get_extended = tcase_create("get_extended");
suite_add_tcase(s, tc_get_single);
tcase_add_test(tc_get_single, test_get_single_pi);
tcase_set_fixture(tc_get_single, get_family_setup, get_family_teardown);
suite_add_tcase(s, tc_get_double);
tcase_add_test(tc_get_double, test_get_double_pi);
tcase_set_fixture(tc_get_double, get_family_setup, get_family_teardown);
suite_add_tcase(s, tc_get_extended);
tcase_add_test(tc_get_extended, test_get_extended_pi);
tcase_set_fixture(tc_get_extended, get_family_setup, get_family_teardown);
return s;
}
int main(void)
{
int nf;
Suite *s = bytecode_suite();
SRunner *sr = srunner_create(s);
BitVector_Boot();
srunner_run_all(sr, CRNORMAL);
nf = srunner_ntests_failed(sr);
srunner_free(sr);
suite_free(s);
return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}

@ -3,6 +3,8 @@
*
* Copyright (C) 2001 Peter Johnson
*
* Based on public-domain x86 assembly code by Randall Hyde (8/28/91).
*
* This file is part of YASM.
*
* YASM is free software; you can redistribute it and/or modify
@ -29,8 +31,20 @@
#ifdef STDC_HEADERS
# include <stdlib.h>
# include <string.h>
#endif
#include <libintl.h>
#define _(String) gettext(String)
#ifdef gettext_noop
#define N_(String) gettext_noop(String)
#else
#define N_(String) (String)
#endif
#include "bitvect.h"
#include "file.h"
#include "errwarn.h"
#include "floatnum.h"
@ -42,36 +56,224 @@ floatnum_new(char *str)
floatnum *flt = malloc(sizeof(floatnum));
if (!flt)
Fatal(FATAL_NOMEM);
/* TODO */
flt->mantissa = BitVector_Create(64, TRUE);
if (!flt->mantissa)
Fatal(FATAL_NOMEM);
/* check for + or - character and skip */
if (*str == '-') {
flt->sign = 1;
str++;
} else if (*str == '+') {
flt->sign = 0;
str++;
} else
flt->sign = 0;
return flt;
}
unsigned long
floatnum_get_int(floatnum *flt)
int
floatnum_get_int(unsigned long *ret_val, const floatnum *flt)
{
return 0; /* TODO */
unsigned char t[4];
if (floatnum_get_single(t, flt))
return 1;
LOAD_LONG(*ret_val, &t[0]);
return 0;
}
unsigned char *
floatnum_get_single(unsigned char *ptr, floatnum *flt)
/* IEEE-754 (Intel) "single precision" format:
* 32 bits:
* Bit 31 Bit 22 Bit 0
* | | |
* seeeeeee emmmmmmm mmmmmmmm mmmmmmmm
*
* e = bias 127 exponent
* s = sign bit
* m = mantissa bits, bit 23 is an implied one bit.
*/
int
floatnum_get_single(unsigned char *ptr, const floatnum *flt)
{
return ptr; /* TODO */
unsigned long exponent = flt->exponent;
unsigned int *output;
unsigned char *buf;
unsigned int len;
output = BitVector_Create(32, TRUE);
if (!output)
Fatal(FATAL_NOMEM);
/* copy mantissa */
BitVector_Interval_Copy(output, flt->mantissa, 0, 40, 23);
/* round mantissa */
BitVector_increment(output);
if (BitVector_bit_test(output, 23)) {
/* overflowed, so divide mantissa by 2 (shift right) */
BitVector_shift_right(output, 0);
/* and up the exponent (checking for overflow) */
if (exponent+1 >= 0x10000) {
BitVector_Destroy(output);
return 1; /* exponent too large */
}
exponent++;
}
/* adjust the exponent to bias 127 */
exponent -= 32767-127;
if (exponent >= 256) {
BitVector_Destroy(output);
return 1; /* exponent too large */
}
/* move exponent into place */
BitVector_Chunk_Store(output, 8, 23, exponent);
/* merge in sign bit */
BitVector_Bit_Copy(output, 31, flt->sign);
/* get little-endian bytes */
buf = BitVector_Block_Read(output, &len);
if (!buf)
Fatal(FATAL_NOMEM);
if (len != 4)
InternalError(__LINE__, __FILE__,
_("Length of 32-bit BitVector not 4"));
/* copy to output */
memcpy(ptr, buf, 4*sizeof(unsigned char));
/* free allocated resources */
free(buf);
BitVector_Destroy(output);
return 0;
}
unsigned char *
floatnum_get_double(unsigned char *ptr, floatnum *flt)
/* IEEE-754 (Intel) "double precision" format:
* 64 bits:
* bit 63 bit 51 bit 0
* | | |
* seeeeeee eeeemmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm
*
* e = bias 1023 exponent.
* s = sign bit.
* m = mantissa bits. Bit 52 is an implied one bit.
*/
int
floatnum_get_double(unsigned char *ptr, const floatnum *flt)
{
return ptr; /* TODO */
unsigned long exponent = flt->exponent;
unsigned int *output;
unsigned char *buf;
unsigned int len;
output = BitVector_Create(64, TRUE);
if (!output)
Fatal(FATAL_NOMEM);
/* copy mantissa */
BitVector_Interval_Copy(output, flt->mantissa, 0, 11, 52);
/* round mantissa */
BitVector_increment(output);
if (BitVector_bit_test(output, 52)) {
/* overflowed, so divide mantissa by 2 (shift right) */
BitVector_shift_right(output, 0);
/* and up the exponent (checking for overflow) */
if (exponent+1 >= 0x10000) {
BitVector_Destroy(output);
return 1; /* exponent too large */
}
exponent++;
}
/* adjust the exponent to bias 1023 */
exponent -= 32767-1023;
if (exponent >= 2048) {
BitVector_Destroy(output);
return 1; /* exponent too large */
}
/* move exponent into place */
BitVector_Chunk_Store(output, 11, 52, exponent);
/* merge in sign bit */
BitVector_Bit_Copy(output, 63, flt->sign);
/* get little-endian bytes */
buf = BitVector_Block_Read(output, &len);
if (!buf)
Fatal(FATAL_NOMEM);
if (len != 8)
InternalError(__LINE__, __FILE__,
_("Length of 64-bit BitVector not 8"));
/* copy to output */
memcpy(ptr, buf, 8*sizeof(unsigned char));
/* free allocated resources */
free(buf);
BitVector_Destroy(output);
return 0;
}
unsigned char *
floatnum_get_extended(unsigned char *ptr, floatnum *flt)
/* IEEE-754 (Intel) "extended precision" format:
* 80 bits:
* bit 79 bit 63 bit 0
* | | |
* seeeeeee eeeeeeee mmmmmmmm m...m m...m m...m m...m m...m
*
* e = bias 16384 exponent
* m = 64 bit mantissa with NO implied bit!
* s = sign (for mantissa)
*/
int
floatnum_get_extended(unsigned char *ptr, const floatnum *flt)
{
return ptr; /* TODO */
unsigned short exponent = flt->exponent;
unsigned char *buf;
unsigned int len;
/* Adjust the exponent to bias 16384 */
exponent -= 0x4000;
if (exponent >= 0x8000)
return 1; /* exponent too large */
/* get little-endian bytes */
buf = BitVector_Block_Read(flt->mantissa, &len);
if (!buf)
Fatal(FATAL_NOMEM);
if (len != 8)
InternalError(__LINE__, __FILE__,
_("Length of 64-bit BitVector not 8"));
/* copy to output */
memcpy(ptr, buf, 8*sizeof(unsigned char));
/* Save exponent and sign in proper location */
SAVE_SHORT(&ptr[8], exponent);
if (flt->sign)
ptr[9] |= 0x80;
/* free allocated resources */
free(buf);
return 0;
}
void
floatnum_print(floatnum *flt)
floatnum_print(const floatnum *flt)
{
/* TODO */
}

@ -3,6 +3,8 @@
*
* Copyright (C) 2001 Peter Johnson
*
* Based on public-domain x86 assembly code by Randall Hyde (8/28/91).
*
* This file is part of YASM.
*
* YASM is free software; you can redistribute it and/or modify
@ -22,16 +24,38 @@
#ifndef YASM_FLOATNUM_H
#define YASM_FLOATNUM_H
/* 88-bit internal floating point format:
* xxxxxxxs eeeeeeee eeeeeeee m..m m..m m..m m..m m..m m..m m..m m..m
* Sign exponent mantissa (64 bits)
* | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0|
* 63 55 47 39 31 23 15 7 0
*
* Only L.O. bit of Sign byte is significant. The rest is garbage.
* Exponent is bias 32767 exponent.
* Mantissa does NOT have an implied one bit (it's explicit).
*/
typedef struct floatnum_s {
unsigned char extval[10]; /* float stored in extended precision */
unsigned int *mantissa; /* Allocated to 64 bits */
unsigned short exponent;
unsigned char sign;
} floatnum;
floatnum *floatnum_new(char *str);
unsigned long floatnum_get_int(floatnum *flt);
unsigned char *floatnum_get_single(unsigned char *ptr, floatnum *flt);
unsigned char *floatnum_get_double(unsigned char *ptr, floatnum *flt);
unsigned char *floatnum_get_extended(unsigned char *ptr, floatnum *flt);
void floatnum_print(floatnum *flt);
/* The get functions return nonzero if flt can't fit into that size format. */
/* Essentially a convert to single-precision and return as 32-bit value.
* The 32-bit value is a "standard" C value (eg, of unknown endian).
*/
int floatnum_get_int(unsigned long *ret_val, const floatnum *flt);
/* ptr will point to the Intel-format little-endian byte string after a
* successful call (eg, [0] should be the first byte output to the file).
*/
int floatnum_get_single(unsigned char *ptr, const floatnum *flt);
int floatnum_get_double(unsigned char *ptr, const floatnum *flt);
int floatnum_get_extended(unsigned char *ptr, const floatnum *flt);
void floatnum_print(const floatnum *flt);
#endif

@ -173,7 +173,9 @@ symrec_get_int_value(const symrec *sym, unsigned long *ret_val,
*ret_val = sym->value.int_val;
break;
case SYM_CONSTANT_FLOAT:
*ret_val = floatnum_get_int(sym->value.flt);
/* FIXME: Line number on this error will be incorrect. */
if (floatnum_get_int(ret_val, sym->value.flt))
Error(_("Floating point value cannot fit in 32-bit single precision"));
break;
case SYM_LABEL:
if (!bytecode_get_offset(sym->value.label.sect,

@ -4,10 +4,12 @@ CFLAGS = @ANSI_CFLAGS@
if CHECK
TESTS = \
bytecode_test
bytecode_test \
floatnum_test
noinst_PROGRAMS = \
bytecode_test
bytecode_test \
floatnum_test
else
TESTS =
noinst_PROGRAMS =
@ -16,6 +18,9 @@ endif
bytecode_test_SOURCES = \
bytecode_test.c
floatnum_test_SOURCES = \
floatnum_test.c
INCLUDES= -I$(top_srcdir) -I$(top_srcdir)/src -I$(top_srcdir)/check
LDADD = \
$(top_builddir)/check/libcheck.a \

@ -0,0 +1,122 @@
/* $IdPath$
*
*/
#include <stdlib.h>
#include "check.h"
#include "bitvect.h"
#include "floatnum.h"
floatnum *flt;
void get_family_setup(void)
{
flt = malloc(sizeof(floatnum));
flt->mantissa = BitVector_Create(64, TRUE);
}
void get_family_teardown(void)
{
BitVector_Destroy(flt->mantissa);
free(flt);
}
void pi_setup(void)
{
/* test value: 3.141592653589793 */
/* 80-bit little endian hex: E9 BD 68 21 A2 DA 0F C9 00 40 */
unsigned char val[] = {0xE9, 0xBD, 0x68, 0x21, 0xA2, 0xDA, 0x0F, 0xC9};
unsigned char sign = 0;
unsigned short exp = 32767 + 1;
BitVector_Block_Store(flt->mantissa, val, 8);
flt->sign = sign;
flt->exponent = exp;
}
START_TEST(test_get_single_pi)
{
unsigned char outval[] = {0x00, 0x00, 0x00, 0x00};
unsigned char correct[] = {0xDB, 0x0F, 0x49, 0x40};
int i;
pi_setup();
fail_unless(floatnum_get_single(outval, flt) == 0,
"Should not fail on this value");
/* Compare result with what we should get. */
for (i=0;i<4;i++)
fail_unless(outval[i] == correct[i], "Invalid result generated");
}
END_TEST
START_TEST(test_get_double_pi)
{
unsigned char outval[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
unsigned char correct[] = {0x18, 0x2D, 0x44, 0x54, 0xFB, 0x21, 0x09, 0x40};
int i;
pi_setup();
fail_unless(floatnum_get_double(outval, flt) == 0,
"Should not fail on this value");
/* Compare result with what we should get. */
for (i=0;i<8;i++)
fail_unless(outval[i] == correct[i], "Invalid result generated");
}
END_TEST
START_TEST(test_get_extended_pi)
{
unsigned char outval[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
unsigned char correct[] = {0xE9, 0xBD, 0x68, 0x21, 0xA2, 0xDA, 0x0F, 0xC9, 0x00, 0x40};
int i;
pi_setup();
fail_unless(floatnum_get_extended(outval, flt) == 0,
"Should not fail on this value");
/* Compare result with what we should get. */
for (i=0;i<10;i++)
fail_unless(outval[i] == correct[i], "Invalid result generated");
}
END_TEST
Suite *bytecode_suite(void)
{
Suite *s = suite_create("floatnum");
TCase *tc_get_single = tcase_create("get_single");
TCase *tc_get_double = tcase_create("get_double");
TCase *tc_get_extended = tcase_create("get_extended");
suite_add_tcase(s, tc_get_single);
tcase_add_test(tc_get_single, test_get_single_pi);
tcase_set_fixture(tc_get_single, get_family_setup, get_family_teardown);
suite_add_tcase(s, tc_get_double);
tcase_add_test(tc_get_double, test_get_double_pi);
tcase_set_fixture(tc_get_double, get_family_setup, get_family_teardown);
suite_add_tcase(s, tc_get_extended);
tcase_add_test(tc_get_extended, test_get_extended_pi);
tcase_set_fixture(tc_get_extended, get_family_setup, get_family_teardown);
return s;
}
int main(void)
{
int nf;
Suite *s = bytecode_suite();
SRunner *sr = srunner_create(s);
BitVector_Boot();
srunner_run_all(sr, CRNORMAL);
nf = srunner_ntests_failed(sr);
srunner_free(sr);
suite_free(s);
return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}
Loading…
Cancel
Save