REALCNVT A set of conversion routines to convert between various real number formats provided by C, QuickBasic and Turbo Pascal Information collected and written by David W. Terry 2/4/88 DONATED TO PUBLIC DOMAIN Included in this archive are the following files: ------------------------------------------------- REALCNVT.H = Header file for the realcnvt routines REALCNVT.LIB = Library of the compiled realcnvt routines in the SMALL model REALCNVT.DOC = This document BD_DBLE .C = routine to convert Basic doubles to IEEE doubles BS_DBLE .C = routine to convert Basic singles to IEEE doubles PR_DBLE .C = routine to convert Turbo Pascal reals to IEEE doubles DBLE_BD .C = routine to convert IEEE doubles to Basic doubles DBLE_BS .C = routine to convert IEEE doubles to Basic singles DBLE_PR .C = routine to convert IEEE doubles to Turbo Pascal reals CONVERT .C = an example prog, reads the test files and converts them CONVERT .PRJ = an example project file for convert.c REALBAS4 = test file with Basic single precision value REALBAS8 = test file with Basic double precision value REALPAS6 = test file with Turbo Pascal real value TEST .BAS = program to create REALBAS4 and REALBAS8 TEST .PAS = program to create REALPAS6 Routine Usage ------------- The header file (REALCNVT.H) includes several typedef definitions that can aid in developing your conversions. They are as follows: pasreal = typedef unsigned char pasreal[6]; bassngl = typedef unsigned char bassngl[4]; basdble = typedef unsigned char basdble[8]; You can use these names as your own data types in your program to read and write to your files where necessary. Example: #include "realcnvt.h" struct { pasreal PR; bassngl BS; basdble BD; } mystruct; With "mystruct" you could read and write records to a file that consist of all three types of real numbers at once. While the variables PR, BS and BD are essentially "un-readable" by the standard C library, you can link your program together with the REALCNVT.LIB (or the actual object files if you compile them yourself) and then use the conversion routines to convert between each of the variables and the IEEE real format (8-byte doubles). The conversion routines provided are as follows: double pasrealtodouble(pasreal OldNum); --------------------------------------- Converts a Turbo Pascal Real to an IEEE Double. You pass it a variable of type "pasreal" and it returns a double. Example: pasreal oldvalue; double newvalue; newvalue = pasrealtodouble( oldvalue ); double bassngltodouble(bassngl OldNum); --------------------------------------- Converts a Basic Single to an IEEE Double. You pass it a variable of type "bassngl" and it returns a double. Example: bassngl oldvalue; double newvalue; newvalue = bassngltodouble( oldvalue ); double basdbletodouble(basdble OldNum); --------------------------------------- Converts a Basic Double to an IEEE Double. You pass it a variable of type "basdble" and it returns a double. Example: basdble oldvalue; double newvalue; newvalue = basdbletodouble( oldvalue ); void doubletopasreal(pasreal *New, double Old); ----------------------------------------------- Converts an IEEE Double to a Turbo Pascal Real. You pass it a POINTER to a variable of type "pasreal" and the value of the Double to convert. Example: pasreal newvalue; double oldvalue; doubletopasreal( &newvalue, oldvalue ); void doubletobassngl(bassngl *New, double Old); ----------------------------------------------- Converts an IEEE Double to a Basic Single. You pass it a POINTER to a variable of type "bassngl" and the value of the Double to convert. Example: bassngl newvalue; double oldvalue; doubletobassngl( &newvalue, oldvalue ); void doubletobasdble(basdble *New, double Old); ----------------------------------------------- Converts an IEEE Double to a Basic Double. You pass it a POINTER to a variable of type "basdble" and the value of the Double to convert. Example: basdble newvalue; double oldvalue; doubletobasdble( &newvalue, oldvalue ); See the file CONVERT.C for a more complete example of the above routines. The following are simplified diagrams of the storage formats for each of the real formats discussed in these conversion routines. IEEE 8-byte real format ----------------------- [0] - num [1] - num [2] - num [3] - num [4] - num [5] - num [6] - num plus \ 4 bits of exponent [7] - / 7 bits of exponent, 8th bit is the sign Turbo Pascal 6-byte real format ------------------------------- [0] - exponent [1] - num [2] - num [3] - num [4] - num [5] - num with Sign at 8th bit Basic Single 4-byte real format ------------------------------- [0] - num [1] - num [2] - num with Sign at 8th bit [3] - exponent Basic Double 8-byte real format ------------------------------- [0] - num [1] - num [2] - num [3] - num [4] - num [5] - num [6] - num with Sign at 8th bit [7] - exponent ------------------------------------------------------------------------------- The following information has been added to help those that are converting the basic real values to variables usable by Turbo Pascal. Date: 04-10-95 (17:08) Number: 46405 of 46405 (Refer# 46397) To: MARIO MUELLER From: DAVID TERRY Subj: BASIC SINGLE (4-BYTE REAL Read: NO Status: PUBLIC MESSAGE (Echo) Conf: RIME PCBoard Support (37) Read Type: GENERAL (+) -> What I was looking for was, I guess, code that will convert the BASIC Single -> 4-Byte reals that are used in PCBoard's MSGS.* files to Pascal 6-Byte Reals -> (since Pascal's Single doesn't seem to work) ... OR something that allows me -> to read them through Pascal normally. If you look at the REALCNVT.DOC you'll get a hint as to what you can do (I'm afraid I can't write the code for you). I'm refering to these two items: Turbo Pascal 6-byte real format Basic Single 4-byte real format ------------------------------- ------------------------------- [0] - exponent [0] - num3 [1] - num5 [1] - num2 [2] - num4 [2] - num1 with Sign at 8th bit [3] - num3 [3] - exponent [4] - num2 [5] - num1 with Sign at 8th bit If you look at the byte layout, it becomes obvious that all you really have to do is move the bytes around to make a conversion between the two formats. In other words, take the byte at offset 3 from the basic number, and put it into offset 0 of the pascal number. Fill bytes at offsets 1 and 2 in the pascal number with 0's. Then copy the bytes from offsets 0-2 out of the basic number into the bytes at offsets 3-5 in the pascal number. I've modified the above illustration just slightly to help make the point clearer. In REALCNVT.DOC it just uses the word "num", but up above I have numbered them (num1, num2, num3, etc). By looking at the bytes that way, you can see which ones go where when you copy them across. For the 8-byte basic real number, the same technique works except, instead of filling pascal bytes num4 and num5 with zeroes, you'll copy all of 5 of them from the basic value, and then simply ignore the bytes at offsets 0 and 1 (num6 and num7 in the illustration below): Turbo Pascal 6-byte real format Basic Double 8-byte real format ------------------------------- ------------------------------- [0] - exponent [0] - num7 [1] - num5 [1] - num6 [2] - num4 [2] - num5 [3] - num3 [3] - num4 [4] - num2 [4] - num3 [5] - num1 with Sign at 8th bit [5] - num2 [6] - num1 with Sign at 8th bit [7] - exponent To convert back the other direction, you just copy the bytes in the opposite direction and fill (or ignore) bytes as appropriate.