US 20090083358 A1 Abstract A computer emulates a fixed-point operation that is normally performed on fixed-point operands, by use of a floating-point operation that is normally performed on floating-point operands. Several embodiments emulate a fixed-point operation by: expanding at least one fixed-point operand into a floating-point representation (also called “floating-point equivalent”), performing, on the floating-point equivalent, a floating-point operation that corresponds to the fixed-point operation, and reducing a floating-point result into a fixed-point result. The just-described fixed-point result may have the same representation as the fixed-point operand(s) and/or any user-specified fixed-point representation, depending on the embodiment. Also the operands and the result may be either real or complex, and may be either scalar or vector. The above-described emulation may be performed either with an interpreter or with a compiler, depending on the embodiment. A conventional interpreter for an object-oriented language (such as MATLAB version 6) may be extended to perform the emulation.
Claims(20) 1. In a computer comprising a memory and a floating point unit, a method implemented in a set of instructions executable by said computer, the method comprising:
said computer receiving a program, a portion of said program comprising an operand (hereinafter “fixed-point operand”) represented in a fixed-point representation; said computer expanding said fixed-point operand into a floating-point representation to obtain a floating-point equivalent; said computer storing a precision of the fixed-point operand; said computer further receiving in said portion an instruction comprising an operation to be performed on the fixed-point operand by a fixed point processor; said computer using said floating point unit to perform on the floating-point equivalent, at least one floating-point operation that corresponds to the fixed-point operation, yielding at least one floating-point result; said computer reducing said at least one floating-point result generated by the floating-point operation into a fixed-point result; said computer using the stored precision during reduction of the floating-point result into the fixed-point result; and said computer displaying said fixed-point result to a user. 2. The method of
said fixed-point operand is one of at least two fixed-point operands to be used by said instruction; and said expanding comprises normalization of at least said fixed-point operand if said fixed-point operand has a property of a value different from another value of said property of another operand to be used by said instruction. 3. The method of
said instruction is to use two operands, with said fixed-point operand as a first operand, and another fixed-point operand as a second operand; and said first operand has a property of a first value and the second operand has said property of a second value different from said first value, said expanding comprises normalization of at least one fixed-point operand to have a common value for said property, said common value being one of the first value and the second value. 4. The method of
said computer determining a property value for the fixed-point result, based on said at least one property value of the fixed-point operand, said fixed-point result being displayed to said user based on said property value from said determining. 5. The method of
said computer determining a property value for the corresponding fixed-point result, based on the instruction that was performed on the fixed-point operand. 6. The method of
a warning is displayed by said set of instructions. 7. The method of
said computer using a predetermined storage element to identify a mode of rounding to be performed on the floating-point result, wherein the mode of rounding is one of: round (round-to-nearest), fix (round towards zero), ceil (round towards positive infinity), and floor (round towards negative infinity), and said computer performing said rounding, and said fixed-point result being displayed after said rounding is performed. 8. The method of
said computer using a predetermined storage element to identify a kind of arithmetic to be performed on the floating-point result, wherein the kind of arithmetic is one of: saturation and modulo. 9. The method of
said fixed-point representation is hereinafter “first fixed-point representation”; the fixed-point result is expressed in a second fixed-point representation which is different from the first fixed-point representation; and the method further comprises said computer using a predetermined storage element in said memory to identify a property of the second fixed-point representation, said fixed-point result being displayed to said user in said second fixed-point representation. 10. The method of
said fixed-point operand comprises a plurality of additional floating-point values; and said fixed-point operand is a vector operand. 11. The method of
a number of bits to the left of a point in the fixed-point number; a number of bits to the right of said point in the fixed-point number; and a total number of bits in the fixed-point number. 12. The method of
at least one additional location for holding a complex component of said fixed-point number. 13. The method of
said computer detecting that the operands are invalidly scaled and issuing a warning message displayed to said user based on a predetermined storage element. 14. The method of
said computer using at least the precision of the fixed-point operand, during emulation of another instruction that uses a result of the fixed-point arithmetic operation. 15. The method of
during the act of receiving said floating-point operand, said computer reducing said additional floating-point operand into fixed-point representation, based on the precision of the fixed-point operand. 16. The method of
a value of a scaling factor of said fixed-point number. 17. A storage device comprising a set of instructions executable by a computer that comprises a floating point unit, the storage device comprising:
software to receive a program, at least a portion of said program being written for execution on a fixed point processor, said fixed point processor being not available in said computer for execution of said program, said portion of said program comprising at least one operand represented in fixed-point representation (hereinafter “fixed-point operand; software to expand said fixed-point operand into a floating-point representation to obtain a floating-point equivalent; software to receive an instruction comprising an operation to be performed on the fixed-point operand; software to receive another instruction that indicates a type of said fixed-point operand; wherein said another instruction comprises a call to a function; software to use said floating point unit to perform on the floating-point equivalent, at least one floating-point operation that corresponds to the fixed-point operation, yielding at least one floating-point result; software to reduce, based on a value of said at least one property, said at least one floating-point result generated by the floating-point operation into a fixed-point result; and software to store the fixed point result in said computer, as output of emulation without use of the fixed point processor. 18. The storage device of
said function comprises instantiation of an object of a predetermined class, the object comprising said floating-point equivalent and at least one property of said fixed-point operand. 19. The storage device of
the fixed-point operand is a real number; the storage device further comprises software to receive another indication via another function name that a complex number is to be expressed in fixed-point representation; and on receipt of an imaginary part and a real part of the complex number, software to expand each part into a corresponding floating-point equivalent. 20. A method implemented in a set of instructions executable by a computer that comprises a floating point unit, the method comprising:
said computer receiving a program, at least a portion of said program being written for execution on a fixed point processor, said fixed point processor being not available for execution of said program, said portion of said program comprising at least one operand represented in fixed-point representation (hereinafter “fixed-point operand”), said fixed-point representation having a precision identifying a first plurality of bits on a left side of a point and a second plurality of bits on a right side of said point; said computer expanding said fixed-point operand into a floating-point representation to obtain a floating-point equivalent; said computer receiving in said program an instruction comprising an operation to be performed on the fixed-point operand; wherein said instruction comprises overloading of an operator normally used to denote said corresponding floating-point operation; said computer using said floating point unit to perform on the floating-point equivalent, at least one floating-point operation that corresponds to the fixed-point operation, yielding at least one floating-point result; said computer reducing, based said precision, said at least one floating-point result generated by the floating-point operation into a fixed-point result; and said computer storing in memory the fixed point result as an output of emulation without use of the fixed point processor. Description This application is a continuation application of U.S. application Ser. No. 10/665,999 filed Sep. 17, 2003 by John R. Allen entitled “EMULATION OF A FIXED POINT OPERATION USING A CORRESPONDING FLOATING POINT OPERATION”, Attorney Docket No. CAT004 US to be issued as U.S. Pat. No. 7,461,116. U.S. application Ser. No. 10/665,999 is incorporated by reference herein in its entirety, including Appendices A, B and C therein. Appendix C contains the following files submitted electronically, and is a part of the present disclosure and is incorporated by reference herein in its entirety.
The above files contain source code for a computer program (mostly in the MATLAB language with a couple in C language), for one embodiment of the invention. A portion of the disclosure of this patent document contains material that is subject to copyright protection. The copyright owner has no objection to the facsimile reproduction by anyone of the patent document or the patent disclosure, as it appears in the Patent and Trademark Office patent files or records, but otherwise reserves all copyright rights whatsoever. Computers use two different representations for numbers. “Floating-point” representation (also called “double precision”) is used for variables that require an extremely wide range of numerical values. For instance, a variable that takes on a value of 10^{−308 }at one time in a program, and then takes on a value of 10^{+308 }at a later time would typically be represented in floating-point. “Fixed-point” representation is used for variables that take on values within a reasonably limited range. For instance, a variable that takes on only integer values between −10000 and 10000 would typically be represented in fixed-point. A special case of fixed-point representation is “integer”, which is used for variables that only take on values that have no fractional portion. Integers are represented in computers as a sequence of bits (equivalent to a sequence of digits in human terms) with an implied decimal point (more correctly called “binary point”; both will be used interchangeably) at the right of the bits. The assumption hereinafter is that integers are represented in 2's complement notation, which is the most common representation. For example, the decimal number 13 is represented as 1101, which is interpreted from left to right as 1*2^{3}+1*2^{2}+0*2^{1}+1*2^{0 }(just as decimal 13 is interpreted as 1*10^{1}+3*10^{0}). Fixed-point representation differs from integer representation only in that the decimal point is not required to be at the right of the number. The decimal point may appear anywhere within the number, to the right of the number (with implicit zeros filling in the gap between the rightmost bit in the collection and the decimal point) or to the left of the number (again, with either implicit zeros or possibly ones (depending on signed considerations) filling in the gap between the leftmost bit in the sequence and the binary point). For example, fixed-point binary 11.01 is interpreted from left to right as 1*2^{1}+1*2^{0}+0*2^{−1}+1*2^{−2 }or 3.25 in decimal. The “scale” of a fixed-point number is the number of bit positions between the implied binary point of the equivalent integer and the binary point of the fixed-point number, with positions to the right being positive and positions to the left being negative. For instance, the scale of 11.01 (binary, equal to 3.25 decimal) is negative two (−2), because the equivalent integer is 1101 (binary, equal to 13 decimal) and the binary point in the fixed-point number is 2 positions to the left of its implied location in the equivalent integer. 11.01 is equal to 1101*2^{−2}. An alternative way of viewing the value of a fixed-point number is that it is equal to the value of the equivalent integer times 2 raised to the scale of the number, and that integers are simply fixed-point numbers with a scale of 0. Floating-point numbers are represented in computers as “m*b^{e}”, where “m” (the mantissa) is a fixed-point number, “b” (the base) is almost always 2, and “e” (the exponent) is an integer. In this context, the scale of a fixed-point number is the number of bits to the right of the binary point, and will be referred to as “right” hereafter. A related but slightly different property of a fixed-point number is an implicit “scaling factor” (also referred to as “scale” hereafter; the context will make the distinction clear). In many programming disciplines, the number that a user represents in a computer is very different from the number that represents the quantity that the user is actually measuring. For instance, numbers that represent a physical quantity (such as megahertz) may range from 1,000,000 to 10,000,000. While such numbers could be represented directly in fixed-point notation as numbers with 24 bits to the left of the decimal (and a scale of 0), a more typical representation would be to divide the numbers (which represent the physical quantity) by 2^{24}, giving numbers between 0.059 and 0.59. “Scaling” the physical quantities into numbers between 0 and 1 is often done, as that range simplifies many computations. Note that the scaling almost never results in numbers scattered exactly between 0 and 1; in this case, for instance, the range of 0.059 and 0.59 is used as the largest range that can be obtained by dividing by a power of 2 without exceeding the bounding range of 0 to 1. If 2^{23 }was used to scale the numbers, the range would be 0.108 to 1.08 which exceeds 1. A scale larger than 2^{24 }would reduce the range more than necessary. The numbers presented to the computer are the fixed-point numbers between 0.059 and 0.59 with a “scale” that depends on the precision the programmer desires. The programmer manually remembers (in his mind) that the true numbers are related to the represented numbers by a “scaling factor” of 24; that is, the true numbers are equal to the represented numbers multiplied by 2 raised to the scaling factor. Scaling factor is a property of fixed-point numbers that, to the knowledge of this applicant (John R. Allen), has always been kept in the programmer's head (i.e. a mental step). To the applicant's knowledge, the scale has never been explicitly stored in a memory of a computer and linked to the number's fixed-point representation. As described below in the Detailed Description section, such storage of scale linked to (in any manner) or alternatively as a portion of fixed-point representation of a number provides several advantages in certain embodiments of the invention by the applicant. Fixed-point numbers possess the capability of being “signed” or “unsigned”. Signed numbers can take on both positive and negative values; the leftmost bit (the “sign bit”) of the number is used to indicate whether the value is positive or negative. Unsigned numbers can only take on non-negative values, allowing an extra bit (the sign bit) to be applied to the number's value. Fixed-point numbers can also be characterized by their “size” (the total number of bits in the number), their “right” (the number of bits to the right of the decimal), and their “left” (the number of bits to the left of the decimal, excluding the sign bit for signed values). Fixed-point numbers (and floating-point numbers) can furthermore be characterized as being “real” or “complex”. A complex fixed-point number is one which has a non-zero imaginary component; a real fixed-point number is one where the imaginary component is known to be zero. The property of fixed-point numbers as being “signed” or “unsigned” is hereinafter called the “signedness” property of the number. The property of a fixed-point number as being “real” or “complex” is hereinafter called the “complexness” property of the number. Arithmetic of fixed-point numbers is similar to arithmetic of integers. Two fixed-point numbers that have the same scale can be added or subtracted just as if they were integers; the result has the same scale as the operands. Two fixed-point numbers with differing scales must be adjusted to have the same scale (much as floating-point numbers do) before they can be added or subtracted as integers. Any two fixed-point numbers can be multiplied using integer arithmetic; the scale of the result is equal to the sum of the scales of the operands. Similarly, any two fixed-point numbers can be divided using integer arithmetic; the scale of the result is equal to the scale of the dividend minus the scale of the divisor. Since fixed-point arithmetic is much simpler than floating-point arithmetic, computer applications where possible prefer to use fixed-point variables and arithmetic. Fixed-point arithmetic is faster, easier to implement in hardware, and requires less electrical power to execute. Unlike floating-point arithmetic, fixed-point arithmetic has two common modes of execution, known as “saturation” and “modulo”. In saturation arithmetic (so named because values “saturate” at two boundaries: the largest value and the smallest value) values that exceed the largest representable value for a fixed-point representation are represented as the largest value and values that are smaller than the smallest representable value are represented as the smallest value. As used herein, the term “largest representable value” is the largest number that can be represented in a given fixed-point representation and the term “smallest representable value” is the smallest number that can be represented in a given fixed-point representation. For example, the largest number that can be represented in a signed fixed-point number that contains 4 bits to the left of the binary point and 0 bits to the right of the binary point is 7. If the value 8 (obtained, say by adding 7 and 1) is converted into such a representation when saturation arithmetic is in effect, the resulting fixed-point number is 7, since that is the largest value for a signed 4-bit fixed-point number. Under modulo arithmetic, values that exceed the largest representable value or are smaller than the smallest representable value are “wrapped” into the representable range of the fixed-point number by dropping the most significant bits. Modulo arithmetic wraps the representable numbers into a ring, so that running off the high end of the representable numbers moves back onto the low end. That is, increasing the largest representable number by 1 in the least significant bit results in the smallest (most negative number); similarly, subtracting 1 in the least significant bit from the smallest number results in the largest number. If modulo arithmetic were in effect for the previous example of adding 7 and 1, the resulting 4-bit signed fixed-point number is −8, which is obtained by dropping any extra bits generated to the left. Similarly, the smallest number in a signed 4-bit fixed-point representation is −8. If the true value −9 is obtained from a subtraction of, say 1 from −8, while saturation arithmetic is in effect, the resulting fixed-point number is −8, the smallest representable number. If modulo arithmetic is in effect, the resulting fixed-point number is 7, obtained again by dropping any extra bits generated on the left. A notion central to several higher level programming languages is the concept of the “type” of a variable or constant. A variable's type is a succinct representation of the amount of storage that a variable requires in memory, the operations that may legally be performed on the variable, and the other variables and constants with which the variable may be combined. Typical “primitive” variable types in various languages include integer, double (or double precision), complex, and char. “Primitive” types are so-named because they represent basic arithmetic or computational types. “Derived” types, which are more complex combinations of primitive types, can be built from the basic primitive types. For instance, a “scalar” is typically a single element. A “vector” is a sequence of scalars collected together; individual elements are accessed and set by notation similar to, for instance, “A(i)” to access the i′th element of the vector A. An array is a collection of vectors; individual elements are accessed and set by notation similar to, for instance, “A(i,j)” to access the i′th element of the j′th vector of array A. In other words, scalars are 0 dimensional objects; vectors are 1 dimensional objects, and arrays are 2 (or more) dimensional objects. The “shape” of a type is the number of dimensions it has: 0 for scalars, 1 for vectors, and 2 or more for arrays. Computer programs involve two distinct levels: a “specification level” and an “execution level”. The specification level is the representation that conveys the intent of the user, and is generally a higher level programming language. The execution level is the representation used by the computer to implement that intent. While the execution level is often the instruction set of the computer, it may well be other things, such as another programming language. For instance, a program written in MATLAB™ may be translated into C for execution; in that case, MATLAB is the specification level and C is the execution level. Similarly, interpreters typically translate source programs to an intermediate representation, which they then use to drive execution. In such cases, the original source program is the specification level and the intermediate representation used by the interpreter is the execution level. Note also that the specification level and the execution level can be the same language. For instance, a MATLAB source program may be translated to a different, optimized MATLAB source program. In such a case, the original source program is the specification level and the translated MATLAB program is the execution level. Given that all programs eventually execute on the instruction set of a computer, the assembly or machine level is also an execution level for all of the examples above. Typically, computers have separate functional units and instructions for executing (a) fixed-point arithmetic and (b) floating-point arithmetic. Higher level mathematical constructs at the specification level, such as complex arithmetic or vector operands, are implemented at the execution level by combinations of scalar operations. For example, an addition of two complex fixed-point numbers is usually implemented by two separate fixed-point additions, one for the real portion and one for the imaginary portion. An addition of two 10-element vector floating-point operands is typically effected by using the floating-point functional unit 10 times, once for each element of the vector. Because floating-point variables have a wide dynamic range whereas fixed-point variables have limited dynamic range, high-complexity algorithms such as, for example, signal processing algorithms, are typically developed using floating-point variables and floating-point arithmetic. Floating-point representation allows the user to delay the burden of dealing with practical implementation issues such as computational overflow. Once the algorithm has been proven correct in floating-point and the dynamic ranges of its variables are well-understood, the floating-point program is often manually converted into an equivalent fixed-point program, where variables are represented in fixed-point representation and arithmetic operations are performed using fixed-point instructions. Many computer architectures support only fixed-point operations; on those that support both fixed-point and floating-point, fixed-point operations execute much faster. Correctly converting an initial floating-point program into an equivalent fixed-point program requires a thorough understanding of the dynamic values taken on by variables and expressions in the program. Gathering this information and using it to correctly convert a program is a difficult process, meaning that it is normally done manually. For example, The Mathworks provides a “quantize” function (see Chapter 6, pages 6.1 through 6.10 of “Filter Design Toolbox Users Guide”, June 2001) that must be applied when converting the following original code (in the MATLAB language):
The user needs to manually generate the following code:
where “parms” is a parameter that indicates the desired precision of the fixed-point result. Other examples of the recommended MATLAB quantization using the “quantize” function include the following example (taken from “Automatic RTL Conversion of DSP Algorithms for a Channelized Wideband Receiver” by Mike Groden, http://www.accelchip.com/copy/LNX paper.pdf, also published in International Signal Processing Conference, April, 2003, Dallas, Tx.)
and this example (taken from “An Overview of the AccelFPGA Compiler for Mapping MATLAB Programs onto FPGAS”) by Prith Banerjee, http://bwrc.eecs.berkeley.edu/Seminars/Banerjee-11.6.02/MATCH-AccelFPGA-Berkeley.pdf) where the following MATLAB code
These examples illustrate the significant changes currently required to “quantize” a MATLAB program using the quantize function. Hereinafter, the phrase “quantize” will refer to the act of converting a floating-point program into an equivalent fixed-point program, selecting values for properties such as signedness, complexness, and precision so as to meet various requirements, unless the context specifically indicates the MATLAB function “quantize”. Unfortunately, manual efforts in effecting changes such as addition of the word “quantize” to a line of a software program tend to be inefficient, inflexible, tedious, and error prone. Such efforts typically require so many modifications that the final program's appearance and the logical flow thereof are quite different from that of the original (i.e., floating-point) program. Moreover, a substantial investment in time is usually required to perform the conversion, resulting in both high manpower costs as well as substantial real-time delays. At a very high level, computer languages can be divided into two categories: “statically-typed” languages and “dynamically-typed” languages. In statically-typed languages such as C and C++, programmers must specify the type (that is, whether the variable is fixed-point or floating-point, whether the variable represents a single number or a collection of numbers, etc.) of every variable in the program. In dynamically-typed languages such as MATLAB, programmers do not specify the types of variables. Instead, variables derive their types from the expressions assigned to them. Other patents have dealt with the problem of converting floating-point programs written in statically-typed languages into fixed-point programs. See U.S. Pat. No. 6,460,177 granted to Lee and entitled “Method For Target-Specific Development Of Fixed-Point Algorithms Employing C++ Class Definitions” and also see U.S. Pat. No. 6,173,247 granted to Maurudis et al. entitled “Method and Apparatus for Accurately Modeling Digital Signal Processors”, both of which are incorporated by reference herein in their entirety. The applicant notes that Lee's approach involves changing variable declarations and header files (which implicitly changes variable declarations). As a result, his approach appears to be limited to statically-typed languages and will not work with dynamically-typed languages such as MATLAB, which do not contain declarations. Furthermore, Lee appears to be silent on what process should be effected with implicitly-typed quantities, such as constants. For example, how should the number “1” be interpreted in an expression “a+1” where “a” is a fixed-point variable? Should it be an integer value, a fixed-point value, a floating-point value, or something else? The applicant notes that this question appears to be left both unasked and unanswered in Lee's patent. Note also that Lee describes range capture to identify some small number of statistics about variables' values, such as the maximum and minimum value taken on. Lee's range capture is apparently limited to summary information. Being summary, the range capture (by definition) is not all inclusive, and misses important information such as locations where overflows occur, how significant the overflows are, the original source of overflows versus overflows that are propagated, etc. For instance, if the range capture shows that a variable takes on values between −0.1 and 7.9, then a user can properly determine that a signed, left=3, right=12 representation will hold the values taken on by the variable. However, if “−0.1” minimum value is the only negative value, and that value occurs in only one insignificant computation, it may well be possible to represent the values using an unsigned representation, allowing an extra bit of precision on the right. In other words, an unsigned, left=3, right=13 representation may well work. The applicant notes that this fact cannot be determined by Lee's range capture. A computer that is programmed in accordance with the invention emulates an operation that is written at the specification level (“specification level” is used herein as defined in the Background section above) as occurring on fixed-point operands by use of an operation at the execution level (“execution level” is used herein as described in the Background section above) that is normally performed on floating-point operands. A specification level program is the representation that conveys the intent of the user, but is not necessarily directly executable on a computer, and is generally expressed in a higher level programming language by the user. The execution level program is the representation of the specification level program that is used by the computer to directly (in machine language) or indirectly (in an intermediate language, used as input to an interpreter, for example) perform the functions described in the specification level program. Several embodiments of the just-described computer emulate a fixed-point operation by: expanding at least one fixed-point operand into a floating-point representation (also called “floating-point equivalent”), performing, on the floating-point equivalent, a floating-point operation that corresponds to the fixed-point operation, and reducing the floating-point result into a fixed-point result. Note that all embodiments in accordance with the invention perform the operation of expanding (as just described), followed by the operation of reducing (as just described) in this order, when emulating a fixed-point operation. The just-described fixed-point result may have the same representation as the fixed-point operand(s) and/or any user-specified fixed-point representation, depending on the embodiment. Also depending on the embodiment, the operands and the result may be either real or complex, and may be either scalar or vector. The above-described emulation may be performed either with an interpreter or with a compiler, depending on the embodiment. A conventional interpreter for an interactive array language (such as MATLAB version 6) may be modified in accordance with the invention to perform the above-described emulation. For example in the case of an object-oriented language (such as MATLAB version 6), a class may be created specifically to identify fixed-point values. The class is created as an embodiment, ahead of time (for example, by a software vendor) as a predetermined class that is supplied or sold to a user in the form of a toolbox or library installed in the memory of the user's computer. Fixed-point operands are represented by the user (in the memory of the computer) as objects of that class, and a new fixed-point value may be created by the user (in the memory of the computer) by instantiating a new object of that class via a constructor function included in the toolbox or library. Moreover, in object-oriented languages that support operator overloading (such as MATLAB version 6), one or more fixed-point operations are implemented in such a modified interpreter of some embodiments in accordance with the invention by overloading an operator normally used to denote the corresponding floating-point operation. For example, the symbol “+” is typically used in programming languages to denote addition. In object-oriented languages that support operator overloading, the “+” symbol is overloaded for fixed-point operands to indicate addition to the modified interpreter. Although implemented together in some embodiments, the just-described operator overloading may be implemented independent of the above-described object instantiation in other embodiments. An interpreter (such as MATLAB version 6) is modified, in certain embodiments of the invention, to respond to a request for construction (via a call to the constructor function described above) of a new fixed-point variable in an otherwise type-less polymorphic language as follows: the interpreter executes a function to dynamically allocate a region in memory for holding all information necessary to express that operand in a fixed-point format, including, for example: (a) floating-point equivalent of the operand (e.g. in double precision), (b) one or more properties such as the size of the fixed-point operand, the position of a binary point within the fixed-point operand and/or whether a bit of the fixed-point operand denotes a sign bit (i.e. signed or unsigned). Although certain embodiments of the method are implemented in an interpreter, in other embodiments such a method is implemented by use of at least one compiler that translates (at compile time) all operations from a specification level of a type-less polymorphic language into machine level. After such translation (by a compiler or series of compilers and/or translators), the computer is able to directly execute the translated program. In such embodiments, the compiler has inferencing mechanisms to recognize one or more predetermined indicators (e.g. constructor function calls) of variables as being fixed-point operands. The compiler propagates the indicated type to other operations and assignments that depend on the results as appropriate, and combines such type indications to obtain the type of intermediate expressions. The compiler uses such type information to generate sequences of execution-level instructions appropriate for performing the fixed-point operations. The instruction sequences being generated may be direct fixed-point instructions, corresponding sequences of floating-point instructions, or any other instruction sequence that emulates fixed-point operations. Several embodiments of the invention are implemented as a method of writing a computer program, wherein said method includes using operator overloading and fixed-point objects in dynamically-typed languages as a mechanism for converting working floating-point programs into equivalent fixed-point programs. This method includes inserting a function call to identify a variable as being of fixed-point type, then using said variable in a statement (in a specification level computer program) without any other identifiers of the variable as being of fixed-point type. This method enables a much simpler, more readable, less error prone method of creating programs for fixed-point processors. A user may prepare a program 110 ( Referring to Certain embodiments of the just-described computer 120 use execution-level instructions that are designed to operate on floating-point numbers to execute operations that at the specification level are fixed-point. One critical aspect of some embodiments of the type described herein is the execution of fixed-point arithmetic using at least one floating-point execution-level operation, where execution level includes both the actual computer hardware as well as other intermediate abstraction levels beneath the specification language. For example, a MATLAB program that contains fixed-point operands and operations that the MATLAB interpreter executes (in accordance with the invention) using floating point machine instructions is a simple case. The MATLAB program in that example is the specification level; the machine instruction language is the execution level. However, another way of accomplishing that same task is to translate the original MATLAB program into another language (say, for instance the C programming language), which is then later translated into machine instructions. The C language program may have the fixed-point arithmetic represented as floating-point operations. In that case, the MATLAB program is the specification level and the C program is an execution level. Similarly, the original MATLAB program may be translated into an equivalent MATLAB program that uses floating-point operations; in that case, MATLAB is both the specification level and the execution level. Alternatively, the MATLAB interpreter, may as a first step, translate the MATLAB source program into an intermediate representation which then drives the interpreter, and that intermediate representation may use floating-point operations rather than fixed-point. An execution level in that case is the MATLAB interpreter's intermediate representation. Finally, the specification level may be a graphical language. For instance, the users program may be represented graphically, such as in the embodiment illustrated in In Specification level operation 112 ( The just-described two operations 112 and 122 are similar to one another although they differ in representation of their operands and result (and such operations are referred to herein as “corresponding” to one another). Specifically, operations 112 and 122 have results that may be identical or approximate to one another (depending on precision). For example, a floating-point add operation 122 corresponds to a fixed-point add operation 112; a floating-point absolute value operation 122 corresponds to a fixed-point absolute value operation 112; and so on. Certain embodiments of the just-described computer 120 use hardware (not shown) that is dedicated for performance of floating-point operations. Examples of such hardware are found in Intel Corporation's microprocessor called Pentium Pro, which has two floating point units (and two integer units which are not used in some embodiments). Moreover, Intel's Pentium processor and the Intel486 processor both have one floating point unit. Note that such floating-point hardware may also be included in a computer as a math co-processor that is coupled to and used by a microprocessor. In several embodiments, the floating-point hardware conforms to an industry standard, such as IEEE Std. 854 and/or 754. For a description of such floating-point hardware, see Chapter 31 entitled “Floating Point Unit” in the book Intel Architecture Software Developer's Manual. Such floating-point hardware is used as described herein, to emulate performance of fixed-point operations. For this reason, such a computer 120 ( Several embodiments of the above-described method emulate a fixed-point operation by receiving a real number 111 in a fixed-point representation (hereinafter “fixed-point operand”) as illustrated by act 124 in In some embodiments, in act 125, during the expansion step, a precision of the fixed-point operand is stored prior to performing the floating-point arithmetic operation in act 127 (as described in greater detail in act 556 of Note that, during emulation of a fixed-point operation, the reduction act is performed after the expansion act in all embodiments of the invention (as illustrated by expansion acts 125 and 325 in In an embodiment that uses the language supported by the MATLAB interpreter, the fixed-point representation stores the value of the fixed-point number as a floating-point value. In such embodiments, the process of expanding fixed-point operand 111 into floating-point equivalent 121 is simply a load operation. Fixed-point numbers can be characterized by their “size” (the total number of bits in the number) their “right” (the number of bits to the right of the binary point), and their “left” (the number of bits to the left of the binary point, excluding the sign bit for signed values). Setting any two of these subproperties determines the third subproperty (of the precision property). A fixed-point number's “precision” property is a combination of its size, left, and right, and is determined by any two of these subproperties. In the above-described act 125, if the instruction uses a single operand, then the act 125 is performed without any normalization on the operand. The word “normalization” is used to mean converting multiple operands with differing values of a single property (for example, signed value and unsigned value of the signedness property or real value and complex value of the complexness property) into equivalent operands having a common value of the property. Therefore, in the above-described act 125, if the instruction uses two operands, then the act 125 includes an act of normalization that is performed on at least one of the operands so that the normalized operand has the same property value as the other operand (in case of two operands). In the above-described act 125, if the instruction uses multiple operands having different precisions, then the act 125 includes an act of normalization which can be implemented differently depending on the embodiment as noted next. Specifically, in a first embodiment, only one operand is normalized to have the precision of the other operand, in the case of two operands. In a second embodiment, both operands are normalized to have a common precision different from the precision of each of the two operands. The common precision can be the maximum precision supported by the representation, or alternatively, the common precision can be obtained from the precision of the two operands. In one embodiment, the common precision is obtained by combining the maximum of the two “left” subproperties of the precisions of the operands, and the maximum of the two “right” subproperties, into a single precision for the result. For example, in the case of one operand having the precision left=3, right=5 and another operand have the precision left=6, right=2, the common precision is left=6, right=5. Computer 120 also receives (as per act 126 in Specifically, depending on the embodiment, a method of the type described herein may be performed inside either an interpreter or a compiler. An interpreter of the type described herein translates and executes each specification-level operation before proceeding to the next specification-level operation, regardless of whether the operation and/or operand is floating-point or fixed-point. On the other hand, a compiler translates all specification-level operations into execution-level instructions at one time; after translation the computer executes each translated instruction. The compiler combines static and dynamic inference methods for intrinsic type, shape, rank, and structural inference to generate executable code prior to execution. Depending on the implementation, compiler-generated code may execute several times (e.g. 1000 times) faster than an interpreter for the same code. An existing interpreter or compiler for an interactive array language is modified in certain embodiments to support an operand of fixed-point type by use of floating-point hardware and/or software normally present in the computer. For example, an interpreter and/or compiler is modified to dynamically allocate a region in memory for holding all information necessary to express that operand in a fixed-point format, including, for example: (a) floating-point equivalent of the operand (e.g. in double precision), (b) the size of the fixed-point number, and (c) the left or the right subproperty of the precision of the fixed-point number. In several embodiments, the interpreter and/or compiler is for an object-oriented language and hence an object, for representing a fixed-point operand, is created by instantiation of a predetermined class. Moreover, one or more fixed-point arithmetic operations are implemented by overloading an operator normally used to denote the corresponding floating-point arithmetic operation (e.g. the same symbol “+” denotes an arithmetic operation of adding two operands, regardless of the type of operands). In some embodiments, when a fixed-point arithmetic operation has a constant as one of the operands, the interpreter automatically converts the constant into its fixed-point representation before combining with the other operands. The interpreter uses the size, left, right, etc. of the known fixed-point operands to set the characteristics for the fixed-point conversion of the constant. Thereafter, the interpreter converts (i.e. expands in accordance with the invention) all operands, including the constant, into floating-point representation and performs the floating-point arithmetic operation on the floating-point equivalents. The floating-point equivalent of a fixed-point operand is the value of that operand expressed by some embodiments of this invention in floating-point representation. (Floating-point representation is, for example, the IEEE 754 standard for floating-point arithmetic). In some embodiments, an interpreter and/or compiler supports a dynamically-typed (i.e. polymorphic) language, wherein variables' types are determined by the type of the expressions assigned to them. In such languages, a specification-level variable may be used at one point in the program as though it were typed one way and used again at a different point as though it were typed differently. Specifically, a variable “A” may be used as if it was in a fixed-point representation with binary point in a first position in some instructions of a software program, and in some other instructions of the same program the same variable “A” may be used as if it was fixed-point representation but with the binary point in a second position. In one embodiment, the MATLAB interpreter automatically accommodates such dynamic changes in variables' types, and therefore, no further modification is needed to such an interpreter to perform methods of the type described. As illustrated by the “quantize” examples listed in the Background section, converting a working double-precision program for a polymorphic language such as MATLAB into an equivalent fixed-point program is currently a difficult, tedious, error-prone task. This conversion process is extremely important in many programming applications, particularly for programming digital signal processors. Current art requires manually decomposing large expressions expressed using arithmetic operators into smaller expressions and encapsulating the decomposed, smaller expressions inside calls to the “quantize” function. To be absolutely correct, such large expressions must be decomposed into binary expressions; use of larger expressions is possible, but requires intimate user knowledge of the functioning of the program and can lead to extremely hard-to-find bugs. In one embodiment of this invention, the methods described herein allow a program that has been modified by addition of a few function calls to be automatically converted from double-precision MATLAB programs into equivalent fixed-point programs. Rather than having to break expressions within existing lines of software programs into subexpressions (in the limit, binary subexpressions) encapsulated by calls to a function such as the MATLAB function “quantize”, several embodiments include a method for quantizing programs that involves the insertion of a few constructors at certain lines of code within a working floating-point program, without otherwise changing the program. The certain lines of code where constructors need to be inserted are immediately adjacent to or contain any expressions used to define variables where the expressions contain no variables that are of fixed-point type, or in the cases where it is desired on a special case basis to change the default precision of a fixed-point expression. There are only a few such lines of code in a program, so that fixed-point equivalent of a working floating-point program is extremely similar in function and appearance to the original unquantized program. In fact most lines in the floating-point software program are the same as the corresponding lines in the fixed-point software program. Regardless of the order of acts 125 and 126, computer 120 performs (as illustrated by act 127) on the floating-point equivalent 121 generated by act 125, a floating-point operation 122 that corresponds to the fixed-point operation 112 identified in act 126. The floating-point operation executed in act 122 generates a floating-point result 123 that may be identical or approximate (as noted above) to a result that would have been generated by performance of the fixed-point operation (depending on precision). Thereafter, computer 120 converts (i.e. reduces; see act 128) the floating-point result 123 generated by act 126 into a corresponding fixed-point result 113. As noted above, fixed-point result 113 may be used in any manner, e.g. displayed to the user or used in another operation. In certain embodiments that support functions that do not return fixed-point results, computer 120 may be programmed to skip the reducing act 128. For example, certain functions may supply a Boolean value or an integer as the result, in which case there is no need to reduce the result into a fixed-point number. Furthermore, some embodiments support performance of an arithmetic operation on operands of two types, e.g. a first operand may be of fixed-point type and a second operand may be of floating-point type. In such a case, act 125 performs a conversion (i.e. expansion) of the first operand to its floating-point equivalent and then the floating-point operation is performed on the floating-point equivalent and the second operand (which has remained unchanged so far). When using floating-point equivalents to emulate fixed-point operands and fixed-point operations, the precision of fixed-point operands is inherently limited by the precision of floating-point equivalents. In several embodiments, the floating-point representation conforms to an IEEE Standard for floating-point arithmetic, such as IEEE 754. In such embodiments, the precision of the fixed-point result is limited by the number of bits in the mantissa of the floating-point representation. Although only one real number 111 is illustrated in The number of operations that are performed on floating-point equivalent by computer 220 depends on the fixed-point operation 212. For example, a single floating-point operation 222 (of addition) is performed by computer 220 when the fixed-point operation 212 is a fixed-point addition operation. In a different example, a series of operations 222 (for example, floating-point divisions and subtractions) are performed when performing a remainder operation 212 of two floating-point equivalents 221. Furthermore, a user's program 230 ( The number of execution level operations that are performed on floating-point equivalent by computer 240 depends on the fixed-point operation 232. For example, in an architecture that directly supports addition of complex numbers, a single floating-point operation 242 (of addition) is performed by computer 240 when the fixed-point operation 232 is a fixed-point complex addition operation. In a different example, a series of operations 242 (for example, floating-point multiplications and additions) are performed when performing a complex fixed-point multiplication operation 232 of two floating-point equivalents 241. As shown in The number of execution level operations that are performed on floating-point equivalent by computer 260 depends on the fixed-point operation 252. For example, a single floating-point operation 262 of extracting the real part of a complex number is performed by computer 260 when the fixed-point operation 252 is the MATLAB function “real”. In a different example, a series of operations 262 (for example, floating-point multiplications and divisions) are performed when performing an absolute value operation 252 of two floating-point equivalents 241. As shown in Although the above description of Vector (or array) operands 311A and 311B may have associated properties 311PA and 311PB (such as signedness, complexness, precision, and scaling factor). Associated properties 311PA and 311PB are not explicitly listed in Computer 320 (which operates as a fixed-point emulator) performs a floating-point vector operation 322 on the floating-point vector operands 321A and 321B, as per act 327 in Prior to act 327, floating-point vector operands 321A and 321B are obtained from the corresponding fixed-point vector operands 311A and 311B, by conversion of each element of each vector operand (as per act 325 in Furthermore, each floating-point element of a result vector 323 that is obtained from operation 322 is converted (as per act 328 in In other embodiments, result vector (or array) 313 has a property 313P that depends in some manner on the input properties 311PA and 311PB (for example, if property 311PA has a precision of left=4, right=8 and property 311PB has a precision of left=2, right=6 and the fixed-point vector operation is multiplication, the result property 313P has a precision of left=6, right=14, formed by summing the left and right values, respectively). In the just described example, the precision of the result is dependent on the instruction that is being performed, although in other embodiments, the precision of the result may be independent of the instruction (for instance, in the case of an addition operator). Therefore, as described in the above example, the two fixed-point representations of the operands (also referred to as “first fixed-point representations”) are different from the fixed-point representation of the result (also referred to as “second fixed-point representation”). In such cases, methods of the type described herein use the previously stored precision properties 463A and 463B in state vector 460 of In some embodiments, the value of the signedness property of the result is determined in a similar manner from the signedness properties of the fixed-point operands, using the signedness values from the stored properties 463A and 463B of In some embodiments, the value of the complexness property of the result is determined from the complexness properties of the fixed-point operands, using the complexness values from the stored properties 463A and 463B of In some embodiments, the value of the scaling factor for the result is automatically determined from the scaling factors of the fixed-point operands, using the scaling factors stored in location 485 in In some embodiments, attempts to combine invalidly scaled operands are automatically rescaled by the programmed computer to produce validly scaled operands, as shown in In One or more of the above-described embodiments may be implemented to extend any conventional dynamically-typed language, in which all real numbers are by default assumed to be floating-point double precision numbers. For instance, in one embodiment that uses IEEE standard 754 for double precision numbers, real numbers are stored in a 64 bit word, with 53 bits used for the mantissa and 11 bits used for the exponent. Other embodiments may use different sizes for storing the mantissa and exponent of double-precision numbers. Several such embodiments are illustrated in If a dynamically-typed language is object-oriented, the function being called can be, for example, a constructor function of an object 421 ( As illustrated in Although properties 481-485 are shown in Applicant has recognized that the precision of a fixed-point number is determined by setting any two of the three subproperties: number of bits to the left of the decimal or binary point (left), number of bits to the right of the decimal or binary point (right), and total number of bits in the number (size). While in one embodiment illustrated in In some embodiments, certain advantages are obtained by storing the scaling factor 485 in the fixed-point representation 480 in memory 470 of a computer, as shown in In this embodiment, values representing the numbers are also stored in memory 470, in memory locations 486-489. Note that the values may be stored in memory locations 486-489 in a common format which can be any of several formats, including integer and (in one specific embodiment) floating-point (for example, IEEE standard 754). Note also that memory locations 481-489 together represent a single vector operand 480. In a similar manner, a single scalar operand 490 may be held in memory locations 491-496. The reference numbers 491-496 are obtained by adding 10 to the corresponding reference numbers 481-486. Note that in the case of a scalar operand 490, only one value of the fixed-point number is stored at memory location 496 in floating-point representation. In an embodiment that works with MATLAB, instead of a single value being stored at location 496, a pair of values (real part and imaginary part) is stored in a corresponding pair of memory locations (i.e., at least one additional memory location not shown in Because fixed-point values can only take on values within a limited range of numbers while data values may vary widely according to domain, programmers typically have to scale their data into a range that fits their fixed-point representation. For instance, if a given set of data values vary between 1.0*2^{+100 }and 1.5*2^{+100}, a user will typically represent the data in fixed-point as numbers varying between 1.0 and 1.5, and will remember that the true number is actually the fixed-point number multiplied by 2^{+100}. The scaling property is provided for all fixed-point numbers to enable the user to explicitly track (i.e. store) this scaling factor rather than implicitly tracking it in his memory. Note that this scaling factor is related to, but slightly different from, the scale of a fixed-point number. The scale relates to the value of the number stored in the computer; the scaling factor relates the value of the number stored in the computer to the number that describes the physical quantity being measured. In several embodiments as illustrated in Consider, for instance, the following examples which a skilled artisan will recognize in view of this disclosure to be easily extended into more general cases. In the examples, the notation “fxp(l, r, s)” means a real fixed-point number or vector which has “1” bits of precision to the left of the decimal/binary point, “r” bits of precision to the right, and is signed if “s” is 1 and unsigned if “s” is 0. a) abs(fxp(l,r,s)) can be an fxp(l,r,s) if s is 0 (unsigned). b) abs(fxp(l,r,s)) can be an fxp(l,r,s) if s is 1 (signed), if overflow is permissible in some cases. c) abs(fxp(l,r,s)) can be an fxp(l+1,r,s) if s is 1 (signed) and overflow is not acceptable. d) fxp(l,r,s)+fxp(l,r,s) can be an fxp(l,r,s) if overflow is permissible in some cases. e) fxp(l,r,s)+fxp(l,r,s) can be an fxp(l+1,r,s) if overflow is not acceptable. f) fxp(l,r,s)*fxp(l,r,s) can be an fxp(2*l−1, 2*r+1, s) if s is 1 (signed) and overflow is permissible for one specific case. g) fxp(l,r,s)*fxp(l,r,s) can be an fxp(2*1, 2*r, s) if is unsigned or if overflow is not acceptable in any cases. h) fxp(l,r,s)*fxp(l,r,s) can be an fxp(2*l, r, s) if s is unsigned, extra bits of precision are not important, and a small amount of overflow is acceptable. i) fxp(l,r,s)*fxp(l,r,s) can be an fxp(l,r,s) if the application is such that the extra bits of precision are not significant and overflow is acceptable. Extrapolating from these cases, it should be apparent to a skilled artisan that the properties of the results depend on a) the left subproperty of the input operands, b) the right subproperty of the input operands, c) the signedness property of the input operands, d) the operator, and e) the complexness property of the input operands. The function which maps these input properties to the corresponding result properties is known as the “result characteristic function”. Table A (listed below) gives the defaults for the result characteristic function used in a specific embodiment. Because the result properties are dependent on the input properties listed previously (making the result properties a function of the input properties), some embodiments may determine result properties via any programming mechanism used to implement a function. That is, such embodiments may embed the “function” of the input parameters directly into the code; they may create a table of function pointers which are called for specific input properties; they may embed the function in a table which is read by the code and used to calculate result properties; or they may use any other programming method used to program computational functions. As is indicated by previous examples, users often desire to change the result properties of certain operands based on the application. Some embodiments allow such flexibility by providing the user access to interfaces to set or change precision of operators. An illustration of such functionality is an “fxp_precision” function as used below. Such a function allows the precision of specific operators to be adjusted to the users' requests. For instance, many digital signal processors use a wide accumulator for summing up the results of multiplies (a multiply-and-accumulate or MAC instruction) on vectors. To represent such an architectural feature, users will want to specify that the results of any addition are the width of the accumulator. If, for instance, the accumulator is 40 bits wide, the first statement below would be used to indicate that the results of adding two 8-bit numbers should be a 40-bit number:
In another context within the same program, the users may wish to avoid the accumulator, and do addition within a standard arithmetic unit. The “fxp_precision” functionality can be used in such a case to specify that the result of adding two 8-bit numbers is an 8-bit number:
In other contexts, the user may increase the precision by one bit, to avoid overflow. A typical use for this would be in hardware design, where users are designing full adders.
For this reason in some embodiments, the user sets precision for performance of an operation, and then the computer performs the operation at the set precision. Furthermore, in certain embodiments, a user may specify different properties for the result, e.g. by using a variable having the different properties to hold the result. Depending on the embodiment, a constructor function (e.g. having the name “fxp”) that is used to identify the fixed-point variable 411 in program 410 may be designed to receive an indication of one or more properties of the fixed-point operand, e.g. the size (in bits) of a storage element that is to hold the real number, and the precise location of a binary point within the size. Alternatively, a function may be limited to just identifying an operand as being of the fixed-point type. In such embodiments, all operands may be deemed to have a common type which is previously specified (e.g. via another function or a separate instruction). The fixed-point properties of any particular operand may be alternatively specified via another function call, depending on the embodiment. Several embodiments in accordance with the invention support implicit conversion into fixed-point types caused by propagation of a previously-specified fixed-point type across an operation. Specifically, as illustrated in The above-described features of type propagation and operator overloading allow a program that is specified in floating-point to be converted for a fixed point processor (such as a DSP) by inserting a function call at the first occurrence of a variable or expression that is to be fixed-point or that needs its fixed-point properties changed. No other change is necessary throughout the rest of the program (unless the type of a variable is changed). For example, as illustrated in As illustrated in The just-described type propagation allows a user to (a) develop their algorithm in floating point in the normal manner, (b) insert function calls for variables that are fixed-point and identify their properties, (c) use emulation to test the algorithm's expected behavior on fixed-point hardware, and if not satisfied go back to (b) to change the properties, and eventually when satisfied go to (d) where a compiler is used to generate executable code for the fixed-point hardware. In act (b) above, the user needs to merely insert an “fxp” or “cfxp” (where ‘cfxp’ designates the function used to create complex fixed-point variables) constructor function call as appropriate for each newly-created variable or each variable whose type is being changed from a previously-used type. This novel method of developing fixed-point programs is superior in many ways to the current state of the art: it is simpler to implement; it is less error-prone; and it requires far fewer changes to floating-point source programs, so that the floating-point program and the equivalent fixed-point program are similar in appearance. Note that the above-described act (b) of inserting function calls eliminates the need to use header files of the type described by Lee in U.S. Pat. No. 6,460,177. Another difference over Lee's teachings is that Lee specifically excludes the use of classes and overloading to emulate fixed-point instructions using floating-point arithmetic (see Lee's column 3, line 40). In contrast, several embodiments of the type described herein use classes, overloading and type propagation to eliminate the need for a programmer to change every line of their program where a fixed-point variable occurs. Furthermore, in certain embodiments of the type described herein, the user can dynamically change the type of a variable during execution in the interpreter (e.g. so that at a given moment in time the result of multiplying two 8-bit numbers is stored in a 16-bit word rather than 8-bit word, and then at a later point in time the user may change the type of the result back to 8-bit word). Moreover, Lee also makes no mention in U.S. Pat. No. 6,460,177 of the use of unsigned variables and complex fixed-point operands, whereas some embodiments of the type described herein use either or both of these. Specifically, several embodiments convert unsigned operands to floating-point type (which is signed) for emulation of the fixed-point operation, and thereafter convert a floating-point result back to unsigned type. In contrast, Lee's compiler automatically uses unsigned operands and unsigned operations so that an unsigned value results with no adjustment necessary. Similarly, Lee's compiler may use an integer processor built into the computer to support modulo and saturation arithmetic, and for this reason Lee does not do any thing special for these kinds of arithmetic. In contrast, several embodiments of the type described herein have functions to implement the appropriate arithmetic operation, depending on the value of a user-accessible flag which indicates ‘modulo’ or ‘saturation’. Furthermore Lee fails to disclose or suggest certain embodiments of the invention that use classes to emulate fixed-point operations based on floating-point operations. As illustrated in Similar execution level instructions 434C are performed in response to the specification level 434B (which is obtained from the corresponding instruction 434A with no change thereof). One difference between 433C and 434C is that 434C includes a execution level instruction to convert the operand B. Certain embodiments of the just-described computer 120 use execution-level instructions that are designed to operate on floating-point numbers to execute operations that at the specification level are fixed-point. One critical aspect of this patent is the execution of fixed-point arithmetic using at least one floating-point execution-level operation, where execution level includes both the actual computer hardware as well as other intermediate abstraction levels beneath the specification language. Although specified as integer in 432A, operand B is recognized by MATLAB as a floating-point number, because MATLAB contains no direct support for integers, and therefore operand B is converted from floating-point to fixed-point in execution level instructions 434C. The normalization step in execution level instruction 434C gives the fixed-point equivalent of operand B the same property values as the fixed-point operand C. To set up a computer to perform emulation in certain embodiments, the user installs software of the type described herein in a path (where “path” describes an ordered set of directories that an operating system or program searchs when hunting for programs or functions) that is searched by an interpreter or compiler when program 410 in In a dynamically-typed language in which program 430 ( While inserting the call to the “fxp” constructor function in statement 436B guarantees that further uses of the variable ‘A’ will access a fixed-point representation, it is not necessary in embodiments that support implicit conversion of double-precision operands. In such embodiments, when a binary operator is encountered in which one operand is fixed-point and the other is double precision, the computer is programmed to implicitly and automatically convert the double precision operand into fixed-point. As a result, the fact that the variable ‘B’ is converted to fixed-point via an “fxp” constructor call in statement 437B means that the use of variable ‘B’ in 438B is real fixed-point. Hence, the computer will automatically convert the use of ‘A’ in statement 438B into real fixed-point, if it is of a type other than real fixed-point. For this reason, the “fxp” constructor call for ‘A’ is not strictly required in statement 436B in all embodiments. One example of a dynamically-typed language that is extended in some embodiments as described above in reference to Certain embodiments implement a compiler of the type described herein to parse programs written in the MATLAB language, recognize and infer fixed-point operations and operands, and generate machine instructions that directly execute the fixed-point operations. Specifically, when using several embodiments of the type described herein, the user does not need to statically define classes and interactions between classes in the manner described by Maurudis in U.S. Pat. No. 6,173,247. Instead, the dynamic typing features of MATLAB allow the user to specify the initial types of input variables using constructor functions such as “fxp” and “cfxp”; the language (not the user) then propagates these type definitions from the variables to their uses. Compilers for such programs must statically infer these variable types using static analysis techniques, such as data-flow analysis. Interpreters such as the MATLAB interpreter automatically handle object definitions and interactions at run time. Regardless, in no case does the user have to directly specify fixed-point classes and interactions between fixed-point classes. As illustrated in Furthermore, the static classes described by Maurudis require that class interactions be statically declared at compile-time. For instance, the class definitions in support of overloading the addition operator will specify (in conversion of programs as described by Maurudis) at compile-time the result of adding two 8-bit operands (for example, the result may be an 8-bit result with overflow, it may be a 9-bit result with no possibility of overflow, or it may be a 16-bit result that flows into an accumulator). Regardless of the choice of result, the type of the result will be fixed statically for the entire program as per Maurudis. In contrast to Maurudis, in embodiments in accordance with this invention that support dynamically-typed languages, the results of overloaded operators may be changed while the program is running (without the user having to specify the changes ahead of time). Thus, it is possible for the addition operator to be overloaded at one point of a program (in embodiments of the invention) with a function that causes the addition of two 8-bit operands to produce an 8-bit result, and at a later time in the program, the overloading function changed so that the addition of two 8-bit operands then produces a 9-bit result. Specifically, classes for the objects are provided to the MATLAB version 6 interpreter by software prepared in the manner described herein. Such software is called a “toolkit” and serves to extend and/or modify the MATLAB interpreter to support fixed-point arithmetic. Depending on the embodiment, the fixed-point type of variables is either dynamically recognized or statically inferred. In the case of interpreters, the interpreter's engine must retain type information for variables (in addition to other information). Whenever it encounters an expression, the interpreter then has the types of the expression's operands, so that it can dynamically recognize the type of the expression. In the case of compilers, the compiler must effect some form of static analysis to determine the types of variables involved in an expression, in order to statically infer the expression type. One possible form of static analysis used in some embodiments is data-flow analysis, as described in Chapter 4.4 of a book entitled Optimizing Compilers for Modern Architectures by Randy Allen and Ken Kennedy (and this chapter is incorporated by reference herein in its entirety). In embodiments wherein a conventional interpreter (such as MATLAB version 6) automatically propagates type information of operands beyond an arithmetic operation (also called “first operation”) that is being performed on the operands, the following modification is made to the interpreter. Specifically, a result of the first operation (for example, the result of statement 433B in In certain embodiments, wherein the conventional interpreter (such as MATLAB 6) supports a dynamically-typed language, the following modification is made to the interpreter to support “mixed-mode” operations (i.e., multi-operand operations where the types of the operands differ). Specifically, for acceptable cases of conversion, the interpreter is modified to automatically convert an operand from its naturally-derived type to a type that is suitable for the operator and other operands. For instance, when presented with a binary operation between a fixed-point value and a double precision value (e.g. “A+1” where A is a fixed-point variable), the interpreter in these embodiments automatically converts the double precision value to the corresponding fixed-point value before effecting the operation (e.g. convert “1” to a fixed-point value with the same precision as “A”). A skilled artisan will easily recognize that this form of implicit conversion can be extended in the modified interpreter of the type described above to many properties and data types, including conversions between signed and unsigned values, conversions between real and complex values, conversions between fixed-point values with different precisions, and conversions between variables with different types. This implicit mixed-mode conversion simplifies the process of reducing a double precision program to fixed-point by automatically handling constants. Polymorphism is supported in embodiments that extend the polymorphic languages that support operator overloading (e.g. MATLAB). Embodiments that overload all operators used within a function and that do not directly insert fixed-point constructors within the function enable a function to be polymorphically applied to fixed-point operands as well as all other operands. Moreover, although a call to a single function is illustrated in The real fixed-point and complex fixed-point objects may be represented in memory 470 using the data structures in In act 407F, it adjusts the two operands to have the same scaling factor by dividing the value of the operand with the smaller scaling factor (the second operand) by two raised to the power of the difference (essentially shifting the value to the right) while increasing its scaling factor by the difference. While either operand can be adjusted to obtain equal scaling factors (the first operand can be adjusted by multiplying its value by two raised to the power of the difference and reducing its scaling factor by the difference) the correct one to adjust for fixed-point operands is the second one. Because its value is being shifted to the right, it is losing precision in the least significant digits, causing the smallest loss of precision. Adjusting the first operand shifts value to the left, causing the most significant digits to disappear. If the operator in Certain embodiments of the invention implement the acts illustrated in Adjustment may be necessary, for example, if one operand is signed and the other is unsigned. Adjustment may also be necessary, for example, if the operands do not have the same precision, left, or right. Such adjustment is also referred to as normalization of the operands. Exemplary implementations of such adjustment are described below in greater detail, in reference to Referring back to After normalization, the operands are converted into a floating-point number (having a mantissa and an exponent) in act 555. During conversion, one or more fixed-point properties, such as signedness (in memory location 481 as shown in Next, as illustrated by act 560, a floating-point arithmetic operation that corresponds to the identified fixed-point arithmetic operation is then performed. In certain embodiments, only one kind of operation may be supported in act 560 e.g. only modulo arithmetic operation or only saturation arithmetic operation. In other embodiments, both kinds of arithmetic are supported, and the user may indicate the type of operation to be used ahead of time, via an instruction which sets a flag indicating the kind of operation to be used in act 560. In such embodiments, the flag is checked in an act 561, and based on the value of the flag; a previously-indicated kind of operation is performed in act 560. Next, in act 570 the floating-point result from act 560 is converted into a fixed-point result. Conversion in act 570 may include determining the fixed-point properties of the results (as per act 571) followed by normalization of the results (as per act 572). Specifically, in act 571, the programmed computer determines, for the result, the precision, the signedness, the complexness and the scaling factor. In one embodiment during conversion in act 571, the stored precisions of each of the operands from the respective memory locations 483 and 484 (as shown in Depending on the embodiment, during conversion in act 571, the other properties (complexness, signedness, scaling factor) of the result may also be determined based on the corresponding stored properties of the operands and/or the operation. Specifically, in certain embodiments, during act 571 the complexness and signedness of the result is determined by the following table (Table A):
The table may be more detailed in other embodiments, as illustrated in the attached software. A table such as Table A is only one way of specifying a result characteristic function in accordance with the invention. Other embodiments may use other methods of specifying this function. During act 572, if a floating-point result has more precision than the fixed-point result to be generated, the floating-point result is adjusted, based on, for example, a rounding mode (i.e. round up or round down) previously specified by the user and/or fixed-point properties of the result. Note that MATLAB contains built-in operations for doing all of these on vector operands, and such operations are used in some embodiments. Furthermore, many operations do not create more bits of precision than the precision in the result and therefore rounding is used only in certain operations (such as divide). In one exemplary embodiment, the rounding mode currently in effect is stored in a state vector (for example, in location 461 of state vector 460 in As another example, if the floating-point result represents a fixed-point number which is unsigned (which may be required when the operand is also unsigned) then any negative floating-point result is converted into its positive equivalent in act 572. Such conversion may be automatic, or alternatively under user control, based on flags that may be written by the user and read by the computer. As yet another example, if the result after rounding overflows the largest positive number or the smallest negative number allowed by the fixed-point representation, the floating-point result is adjusted depending on whether modulo or saturation arithmetic is in effect. Then the fixed-point result is set equal to the floating-point result. In one exemplary embodiment, the kind of arithmetic currently in effect is stored in a state vector (for example, in location 462 of state vector 460 in As used herein, the term “largest representable value” is the largest number that can be represented in a given fixed-point representation and the term “smallest representable value” is the smallest number that can be represented in a given fixed-point representation. For example, the largest number that can be represented in a signed fixed-point number that contains 4 bits to the left of the binary point and 0 bits to the right of the binary point is 7. If the value 8 is stored into such a representation when saturation arithmetic is in effect, the resulting fixed-point number is 7, since that is the largest value for a signed 4-bit fixed-point number. If modulo arithmetic is in effect, the resulting fixed-point number is −8, which is obtained by dropping any extra bits generated to the left. Similarly, the smallest number in a signed 4-bit fixed-point representation is −8. If the value −9 is stored while saturation arithmetic is in effect, the resulting fixed-point number is −8, the smallest representable number. If modulo arithmetic is in effect, the resulting fixed-point number is 7, obtained again by dropping any extra bits generated on the left. In some embodiments, if location 462 of the vector 460 in Depending on the operation, a fixed-point result can have different fixed-point properties than the operand: e.g. the result of multiplying two single precision fixed-point operands can be either a single precision or a double precision fixed-point result. Multiplying two 8-bit fixed-point numbers can, in some embodiments, result in a 16-bit fixed-point product. An exemplary implementation of such adjustment is described below in greater detail, in reference to The fixed-point result from act 570 is thereafter stored in act 580. Specifically, in an act 581, a new fixed-point object is created to hold the result, e.g. by instantiating a predetermined class that is declared for fixed-point objects. Moreover, in another act 582, the value of the object is loaded from the floating-point result, and furthermore the properties of the object are set, e.g. based on the properties determined in act 571 (described above). In another embodiment, acts similar to those described above in reference to At this stage after completion of act 541A, all operands that were received in act 540A are in fixed-point representation, thereafter, acts 550A-580A of Following this conversion into fixed-point, act 550A will convert the fixed-point constant back into floating-point representation. In some cases, such as the example given of combining “8” with an unsigned fixed-point number with precision left=4, right=0, the result converted into fixed-point then back into floating-point will be identical to the original floating-point constant (i.e. “8”). In other cases, it may differ, however. For instance, if the constant “8” is combined with a signed fixed-point number with precision left=3, right=0, the initial conversion (act 541A) into fixed-point produces the constant “3”, assuming saturation arithmetic is in effect, since the largest representable value for a signed left=3, right=0 number is “3”. The conversion back into floating-point (act 555A) will then produce a floating-point value “3”. In another example of change, if the constant is negative and the first operand is unsigned, the constant will be converted into a nonnegative number when it is converted into an unsigned. Alternative embodiments convert the floating-point constant or variable into the minimally-sized fixed-point variable that will hold it, rather than the size and precision of other operands. The conversion of floating-point constants and variables in acts 540A and 541A is novel, and is counter to normal programming language semantics. Variable types in programming languages form a lattice, with the most specific type (e.g. a fixed-point type) at the bottom of the lattice, more general types (e.g. integer) in the middle) and the most general types (e.g. floating-point) at the top. Operations involving types at the bottom of the lattice are the fastest and most efficient to implement; operations involving types at the top of the lattice are the slowest and most complex to implement. Accordingly, when speed and efficiency are the primary concern, the correct choice when combining two operands of different types is to convert both to the lowest type above them that contains both of them—the lowest common type. In the case of combining a fixed-point type with a floating-point type, this rule would call for both variables to be converted to the floating-point type before combining. Acts 540A and 541A instead call for the types to be converted to the lowest common type below them in the lattice—in the specified case, to the fixed-point type. This conversion may cause some loss of precision in the more general type—in the specified case, to the floating-point type. This novelty is an aspect that is critical in the development of DSP applications. Floating-point arithmetic is slow relative to fixed-point arithmetic, and most applications that are developed for fixed-point DSPs are time-critical (that is, they have to complete a certain amount of work within a given time). In many cases, the targeted fixed-point DSP architecture may not support floating-point arithmetic instructions. The methods of some embodiments described herein provide solutions to two problems: a) the development and simulation of fixed-point DSP programs in emulation environments that do not fully or directly support fixed-point arithmetic instructions, and b) providing a mechanism for compiling developed programs for a targeted fixed-point DSP (which will support fixed-point arithmetic instructions but may not support floating-point instructions), and have the resulting target code running on the target DSP produce results that are bitwise identical to the results produced in the simulation of (a). In the absence of acts 540A and 541A, the defined semantics for combining a fixed-point variable and a floating-point variable or constant would be equivalent to that of expanding the fixed-point variable to floating-point, then doing the resulting arithmetic in floating-point. These semantics would be slow, or even impossible to implement on a fixed-point DSP, and would thereby defeat goal (b). By inverting the type lattice in acts 540A and acts 541A, the methods described herein provide a more natural semantics for mixed operations, as well as a mechanism for expressing and naturally reducing constants in languages that do not support fixed-point constants (such as MATLAB) into fixed-point form. These methods also allow both goals (a) and (b). As noted above, a computer that is programmed to implement the interpreter or compiler for the language MATLAB is modified in certain embodiments of the invention to recognize with a user's program 410 ( Also at this time of setting up the programmed computer, a table indicative of the relationship of the fixed-point type to all types native to the interpreter is appropriately initialized in the computer. For example, a default relationship is that fixed-point type dominates all other types. The just-described table is used by the computer to determine the type of the operation to be performed (i.e. a fixed-point operation is performed (or emulated) if even one of the two operands is of fixed-point type). Such a table is accessible to the user via commands of the interpreter, so that the user can dynamically change any such relationship between any two types supported by the programmed computer. When processing program 410, the programmed computer (which may be implementing either an interpreter or a compiler) initially scans and parses a statement, e.g. statement 431B which is “A=fxp (3.717);”. The scanning and parsing is done in the normal manner of any compiler or interpreter. After parsing this statement, the programmed computer (in embodiments that support the MATLAB language) determines that symbol “fxp” must be either a function or an array, and checks if the symbol “fxp” is defined in its internal symbol table. The programmed computer also uses the left and right parenthesis in the above statement 431B to decide that the symbol “fxp” represents a function and not an array. Then, the programmed computer searches in a predetermined path to its local storage device (e.g. a directory path in a hard disk) for a file that has the same name as function “fxp”. If the file is found, the programmed computer (in embodiments supporting the MATLAB language), following the procedures of standard interpreters, identifies formal arguments to be passed to function “fxp”, creates a new workspace, creates variables for formal arguments, assigns values from the actual parameters, and passes control to the first statement in function “fxp”. The just-described last two acts of assigning values and passing control are performed only in case of an interpreter and furthermore on completion of function “fxp” control returns to the interpreter which then scans and parses the next statement, e.g. statement 432B in program 410 ( At some point during the scanning and parsing of statements in program 410, the programmed computer scans and parses a statement that contains an operation, such as statement 433B in Then the programmed computer checks if the two operands are of the same type (e.g. both may be fixed-point type). If so, the programmed computer for embodiments that support operator overloading checks to see if there is a function designated to perform the operation specified by the operator. For instance, in embodiments that support the MATLAB language, the programmed computer, when performing the “multiply” operation for a real fixed-point object, will check if a file named “mtimes.m” is located in a directory named “@fxp” (created by concatentating “@” with the constructor name). Other languages support operator overloading in different fashions, and embodiments supporting those languages will obviously behave slightly differently. For embodiments supporting MATLAB, if such a file is found in the appropriate directory (specifically in the above example, a file named “mtimes.m” must be found in a directory named “@fxp”, and that directory must be contained in the path), then the programmed computer identifies formal arguments to be passed to function “mtimes”, creates a new workspace, creates variables for formal arguments, assigns values from actuals, and passes control to the first statement in function “mtimes” (all in the fashion of standard interpreters). If the file is not found, an error message is generated. If the two operands differ in type in embodiments supporting MATLAB, then the interpreter checks to see if the type of the first operand is inferior to the type of the second operand. Note that superiority of the fixed-point type over all types native to the interpreter is initially set up. Due to superiority of the fixed-point type, the computer performs a search similar or identical to that described above. Specifically, the programmed computer checks if a file named “mtimes.m” is located in a directory named “@firsttype”, wherein “firsttype” is the type of the first operand. In one exemplary embodiment, “firstttype” may take on the values “fxp” or “cfxp” for real fixed-point and complex fixed-point types, respectively. If “firsttype” has the value “fxp”, and if the “mtimes” function is again found in the directory “@fxp”, and the same actions (described above) are performed to pass control to the function. As would be apparent to the skilled artisan, a corresponding set of acts are performed for the second side operand being of fixed-point type. Specifically, if the first operand happened to be inferior (e.g. a single precision floating point number) and the second operand happened to be superior, eventually the ‘mtimes’ function is again found in the directory with a name derived from the variable's type, and the same actions (described above) are performed to pass control to the function. Each of various functions for fixed-point operations (such as multiply, divide, add, subtract) that are defined for use with one or more fixed-point operands may be implemented to have logic of the type as illustrated in When control is first passed to a function for a fixed-point operation, a programmed computer normalizes the two operands (to be operated on by the instruction) depending on whether or not they are of the same fixed-point type, e.g. as illustrated by acts in In some embodiments, the functions which implement the acts in The embodiments described in Referring to If in act 610 the first operand's type storage element contains the predetermined value, then the programmed computer goes to act 620 ( Note that the type test in act 620 (or any of the type checks in Note also that the type test in act 620 (or any of the type checks in In some embodiments, the conversion of a real fixed-point object into a complex fixed-point object as called for in act 621 is performed by the “cfxp” constructor function. One such embodiment is detailed in If the second operand is not a complex floating-point number (in act 620), then the programmed computer goes to act 630 to check if the second operand is of type double precision floating-point or if it is of type logical. If so, then the programmed computer goes to act 631, and converts the second operand into a real fixed-point object, and having the same properties as the first operand. In some embodiments, this conversion is effected by the “fxp” constructor function, which is detailed in In act 630 ( If the second operand is not a complex fixed-point object (in act 640), the programmed computer goes to act 650 to check if the second operand is a real fixed-point object. If so, the programmed computer goes to act 651. In act 651, the programmed computer determines normalized properties for the operands and thereafter uses them in conversion of the first operand and the second operand. Note that acts 651 and 652 are similar to acts 641 and 642 described above, with the exception that acts 651 and 652 are reducing the inputs into real fixed-point objects while acts 641 and 642 are reducing the inputs into complex fixed-point objects. In act 611, the programmed computer performs a series of acts as illustrated in In act 720 the programmed computer checks if the second operand is a complex floating-point number. If so, then the programmed computer performs act 721 to convert the second operand to a complex fixed-point object that has the same properties as the first operand. This results in two complex fixed-point objects with equivalent property values. These objects are easy to combine with arithmetic operations. Note that while act 721 and act 622 have similar descriptions, they occur in different contexts and produce different results. Act 721 is invoked by the programmed computer when the first operand is a complex fixed-point object and the second operand is a complex floating-point number. In that context, it converts the second operand into a complex fixed-point object, resulting in two complex fixed-point objects. Act 622 is invoked by the programmed computer when the first operand is a real fixed-point object and the second operand is a complex floating-point number. In order not to lose the imaginary part of the complex number, the programmed computer in that case converts the real fixed-point object into a complex fixed-point object (act 621, assuming an imaginary portion of 0), then converts the complex floating-point number into a complex fixed-point object, resulting in two complex fixed-point objects. In In act 711, the programmed computer performs a series of acts as illustrated in In act 820, if the second operand is a complex floating-point number, then the programmed computer performs act 821 in which an error is reported (because both operands are complex numbers and the operation should have been directly handled by a MATLAB interpreter or compiler in the conventional manner). If the answer is no in act 820, then the programmed computer goes to act 830 to check if the second operand is of type double precision floating-point or if it is of type logical. If so, then the programmed computer goes to act 831, and reports error (because neither operand is a fixed-point object; here too the operation should have been directly handled by a MATLAB interpreter or compiler in the conventional manner). In act 830 if the answer is no, the programmed computer goes to act 840 ( If the second operand is not a complex fixed-point object (in act 840), the programmed computer goes to act 850 to check if the second operand is a real fixed-point object. If so, then the programmed computer goes to acts 851 and 852. Acts 851 and 852 are similar or identical to the corresponding acts 651 and 652 described above wherein the programmed computer converts the two operands to the same type, namely complex fixed-point and having the same properties. If the answer is no in act 850, an error is reported in act 860 (because the second operand appears to have an undefined type which is not any of: complex floating-point, double precision floating-point, logical, complex fixed-point and fixed-point). Note that this embodiment supports the limited number of types that are supported by MATLAB. A skilled artisan, in view of this disclosure, can easily extend this flowchart to support languages with richer type systems. In act 811, the programmed computer performs a series of acts as illustrated in In When emulating a user-specified fixed-point instruction, a programmed computer normalizes the result obtained from performance of a floating-point operation, e.g. as illustrated by the acts in
After acts 1002 and 1003, the variable “max_value” holds the floating-point value for the bit pattern for the largest representable value in the fixed-point precision determined by “left” and “right”, but with the binary point set at the right of the value rather than as determined by the precision. Similarly, “min_value” holds the floating-point value for the bit pattern for the smallest representable value in the fixed-point precision determined by “left” and “right”, but again with the binary point set at the right of the value. Next, in act 1004, the just-described max_value and min_value are adjusted to set the binary point in the correct position for the precision by moving the binary point left into the pattern as follows:
At this point, “max_value” and “min_value” are floating-point variables that hold the values for the largest and smallest representable values, respectively, in the precision “left” and “right”. Thereafter, an act 1005 checks if the result is unsigned. If so, the programmed computer goes to act 1006 to set two variables, “positives” and “negatives” based on the floating-point representation of the result value (“value”):
The variable “negatives” is a logical object that has identical shape to “value” (that is, if “value” is a 2-dimensional array, “negatives” is a 2-dimensional array; if “value” is a length-10 vector, “negatives” is a length-10 vector) which is equal to 1 in all positions where “value” is less than zero and is equal to 0 in all other positions. The variable “positives” is the complement to “negatives”; it is a logical object which is equal to 1 in all positions where “value” is greater than or equal to 0 and is equal to 0 in all other positions. The negatives and positives variables are used later as discussed below. Next, in act 1007, the programmed computer checks if the arithmetic operation being performed is for saturation arithmetic. If so, the programmed computer goes to act 1008 and checks whether any values in the negatives are not equal to zero. If so, the programmed computer goes to act 1009 and generates a warning to the user that he is creating unsigned variables from negative values. Since unsigned variables can only represent values that are greater than or equal to 0, creating a negative value for an unsigned variable often indicates an error in the user's program, and a warning can save valuable debugging time. After act 1009 and also if the answer is no in act 1008, the programmed computer goes to act 1010. In act 1010, the programmed computer sets two variables as follows, again based on the assumption that the variable “value” holds the floating-point representation of the unconverted result:
Since unsigned variables can only take on values that are greater than or equal to 0, under saturation arithmetic results that are to be unsigned saturate in the negative direction at 0. Accordingly, any floating-point results that are to be converted to unsigned and that are negative need to be changed to 0. The variable “cancel” is used to effect that change. “Cancel” is a floating-point object that has the same shape as “value”, that is identical to “value” in all positions where “value” is negative, and that is 0 in all other positions. Subtracting “cancel” from “value” then sets “value” to 0 in all positions where it is originally negative (performing the act of saturating the unsigned variable at 0) and leaves all other positions unaffected. Thereafter, the programmed computer goes to act 1020 ( If in act 1011, the answer is yes, then the user is attempting to assign negative values into an unsigned variable. The programmed computer goes to act 1012 and issues a warning on assigning negative values into an unsigned variable. Act 1012 makes the first step towards converting the negative values into unsigned under the assumption of modulo arithmetic. If the negative values have overflowed into only one bit position, that bit can be corrected by adding a positive number to that value. That positive number is equal to 2 raised to a power equal to the position of the incorrect bit. This transformation is effected in act 1012:
The variable “upper” is a floating-point object identical in shape to “value” (which holds the floating-point representation of the results). In every position where “value” is less than zero, “upper” holds a value equal to 2 raised to the power equal to the position of the incorrect bit. In all other positions, “upper” is equal to 0. Adding “upper” to “value” correctly converts all negative values that are incorrect in only one bit position into the correct unsigned value assuming modulo arithmetic, leaves all nonnegative positions unaffected, and sets all negative values that are incorrect in more than one position as negative In some cases, there may still be some negatives in the result even after performing the above described act 1012, and if so, the result was incorrect in more than one bit position. Such cases require a more expensive method for generating the correct result of modulo arithmetic. The existence of additional negatives is determined in act 1012 as follows:
Next, the programmed computer goes to act 1013 and checks if any values in negatives are not equal to 0. If so, the programmed computer goes to act 1014 and initializes the following variables:
The objective of this sequence of steps is to eliminate the excess bits on the left (most significant position) of negative numbers in “value”. The resulting numbers are still negative, but now are now larger in value than the smallest negative number representable in the signed fixed-point presentation left=“left” and right=“right”, with the same bit pattern in the significant positions as the original numbers. Note that this is not the final result, as the numbers are still negative. However, a simple later step will yield the final result. The variable “bad_ones” has the same shape as the floating-point variable “value”, and has zeros in all positions where “value” is non-negative and is equal to “value” in all positions where “value” is negative. In other words, “bad_ones” is equal to “value” in all bad (i.e. negative) locations and is 0 in all other positions. The programmed computer then eliminates the extraneous bits to the left by shifting “bad_ones” to the right by “left” number of bits (effected by the divide by 2̂“left” to yield the variable “bad_ones_f”). At this point, “bad_ones_f” is a floating-point variable that has all the correct bits of the result to the right of the decimal or binary point, and all the extraneous bits that need to be removed to the left of the decimal or binary point. The programmed computer removes the extraneous bits to the left by computing the truncated version of “bad_-ones_f” (obtained by “fix(bad_-ones_f)”−“fix” is a MATLAB function that truncates a floating-point number at the decimal point), then subtracting that result from the complete version of “bad_ones_f”. This leaves only the bits to the right of the binary point. The correct values to be substituted (“bad_-ones”) are then obtained by shifting “bad_ones_f” to the left by “left” number of bits (again, effected by a multiply, since the representation at this time is floating-point). The correct values are then inserted back into the “value” variable by multiplying “value” element wise by the identically-shaped variable “positives” (which has a one in every location where “value” is non-negative and a zero in every location where “value” is negative, so that only the non-negative values pass through) and then adding the variable “bad_-ones” (which is zero in every location where “value” is non-negative and has the correct bit pattern for every location where “value” is negative). To illustrate with an example, assume that we have obtained the result value −15.0 (which in binary is “10001” for an operation done in modulo arithmetic where the result precision is left=3, right=0. Since −15.0 contains 5 bits to the left of the decimal, the 2 leftmost bits need to be eliminated. These bits are eliminated by first computing “bad_-ones_f”, which for this scalar quantity is a floating-point variable equal to −15.0/8, or −1.875, which is equivalent to shifting the bit pattern 10001 to the right 3 bits (giving 10.001). The extraneous bits to the left of the decimal are removed from “bad_ones_f” by subtracting the truncated version from it from the original value (10.001−10.000==0.001, or in floating point, −1.875−(−1)==−0.875). This value is then shifted back to the left 3 bits (done by a multiply, since this is floating-point form) to make it have the scaling that it started with: the easiest way to remove the bits on the left is to shift all the bits that we desire to keep to the right of the binary point, remove all integer bits, then shift the bits back into their original position. With the example we have, shifting −0.875 to the left 3 bits yields −0.875*8 which is equal to −7. In binary, this is 1001.00 (the sign bit is necessary on the left to indicate that the number is negative). Later steps will convert this value into a positive 1, which is the correct modulo result. Next, the programmed computer goes to act 1020 (described above) to set “value_i”, the value obtained by shifting all the significant digits (where “significant digits” will be defined below) in the floating point input to the left of the decimal point. The objective of acts 1021 through 1061 is to “round the floating-point result” to the nearest fixed-point equivalent. A fixed-point number has a limited number of bits (as indicated by the precision property. For example, the floating-point number (expressed in binary) 1.010101*2̂0 contains more bits than can be represented in an unsigned fixed-point number that has 1 bit to the left of the binary point and 3 bits to the right of the binary point. If this floating-point value needs to be converted into such a fixed-point number, then it will need to be adjusted (“rounding the floating-point result”) so that it has the floating-point representation corresponding to the nearest fixed-point equivalent with the specified precision properties. The objective of acts 1021 through 1061 is to find the fixed-point number with the specified precision that is closest in value to the floating-point input. Because there can be two fixed-point numbers that are equally close to a floating-point number (for instance, the floating point number 1.0101*2̂0 is equally near to 1.010 and 1.011 when the specified precision is unsigned, left=1, right=3), a rounding mode, specified by the user, is used to break ties. Standard rounding modes include normal rounding (also called “round”, a 1 in the next significant bit rounds up; a 0 truncates), ceil (always round toward positive infinity), floor (always round toward negative infinity), and fix (always round toward 0). Using rounding modes of round and ceil, 1.0101 would become 1.011 for the example of left=1, right=3; it would become 1.010 for rounding modes of floor and fix. Acts 1021 through 1061 find the fixed-point number closest to the input floating-point number (using a user-specified rounding mode to break ties) and specifies the value of that fixed-point number in floating-point form. Acts 1021 through 1061 in this embodiment work by utilizing 4 MATLAB functions that are provided to users: “round” (that rounds floating-point numbers to the nearest integer values based on whether the next significant bit contains a 1), “ceil” (that rounds floating-point numbers to the nearest integer by rounding towards positive infinity), “floor” (that rounds floating-point numbers to the nearest integer by rounding towards negative infinity), and “fix” (that rounds floating-point numbers to the nearest integer by rounding towards 0). In view of this disclosure, a skilled artisan can easily extend the concepts herein to languages that do not contain such builtin functions. Act 1020 through 1061 takes the floating-point input, performs a left shift on its value (by multiplying the value by 2̂right) to get all the bits that will be contained in the fixed-point equivalent (the ‘significant bits’) to the left of the decimal. This resulting value is the variable “value_i”, for “value as an integer”. These acts then effect the appropriate rounding functionality, based on the user-specified rounding mode, by calling the corresponding MATLAB function. The result is an integer value, represented as a floating-point number that has the floating-point value corresponding to the fixed-point equivalent, shifted to the left by the number of bits specified in the “right” property. The exact floating-point value for the fixed-point equivalent is then obtained by dividing by 2̂right, effectively shifting the value to the right “right” number of bits. This is the objective of acts 1020 through 1062; the following paragraphs provide more detail on the exact operation of these acts. After performing act 1020, the programmed computer goes to act 1021 and checks if the rounding mode is currently set to ‘round’ and if so, goes to act 1022 to invoke the function “round” with “value_i” as a parameter and then goes to act 1062 (described below). In act 1021 if the answer is no, the programmed computer goes to act 1031 and checks if the rounding mode is ‘ceil’ and if so goes to act 1032 and invokes the function “ceil” with “value_i” as a parameter and then goes to act 1062. If the answer in act 1031 was “no”, the programmed computer proceeds to act 1041. In act 1041 the programmed computer checks if the rounding mode is set to “floor” and if so goes to act 1042 to invoke the function “floor” with “value_i” as a parameter and thereafter goes to act 1062. In act 1041 if the answer is no, the programmed computer goes to act 1051 and checks if the rounding mode is ‘fix’ and if so goes to act 1052 and invokes the function “fix” with “value_i” as the parameter, and then goes to act 1062. If the answer is no in act 1051, the programmed computer goes to act 1061 to display an error message about use of an invalid rounding mode. Then the computer goes to act 1062. In act 1062, the programmed computer sets the “value_i” to be equal to the “value_i*2^{right}”. Thereafter, the programmed computer goes to act 1070 to check if the arithmetic is to be of the saturation kind, and if so goes to act 1071 and otherwise goes to act 1074. In act 1071, the programmed computer computes the following values:
After “value” is calculated above, the programmed computer goes to act 1072 to check if there are any non-zero values in overflow, and if so goes to act 1073 to warn about overflow and then goes to act 1080. If the answer is no in act 1072, the programmed computer goes to act 1080 directly (i.e. without warning). In act 1074, the programmed computer sets value_f=value/2^{left }and thereafter goes to act 1075 to check if the result is to be signed and if so goes to act 1077 to calculate negatives as follows:
Thereafter, the programmed computer goes to act 1078, where the following values are calculated:
Next, the programmed computer goes to act 1080. In one embodiment, act 1080 is repeated, and the repetition happens because of evolution of the code during development of this embodiment. Note, however, that in other embodiments, such repetition of act 1081 is not required and act 1081 could follow 1072/1073 directly. If the answer was no in act 1075 then the programmed computer goes to act 1076 and sets negatives=zeros(size(value_f)) and thereafter goes to act 1078 discussed above. If in act 1080 the programmed computer finds that the arithmetic is to be saturation, the programmed computer goes to act 1081 and computes the following values:
Next, the programmed computer goes to act 1082 which is identical to the above-described act 1072, and goes (either via act 1083 or directly) to act 1084. In act 1084, the programmed computer computes the value as follows:
Note that if the answer is no in act 1080, the programmed computer goes directly to act 1084. After act 1084, control is returned to the context that initiated the call to function “fixsize”. In some embodiments, function “fixsize” is called primarily from the real and complex fixed-point constructor functions (e.g. “fxp” and “cfxp” in one embodiment) described below. The embodiments described in The “fxp” constructor in this embodiment in addition to constructing new real fixed-point objects (such as vector operand 480 and scalar operand 490 illustrated in Act 1101A of If the answer to act 1101A is “no”, meaning that there is at least one input argument, the programmed computer executes act 1103A, testing whether there is only one input argument (“value”). If the answer is “yes”, the programmed computer executes act 1104A, which sets y to be a real fixed-point object containing that value via the actions in If the answer to act 1103A is “no”, meaning that there are at least two input arguments, the programmed computer executes act 1105A, testing whether there are exactly two input arguments (“value” and “left”). If the answer is “yes”, the programmed computer executes act 1106A, which processes the two input arguments (“value” and “left”) via the actions in If the answer to act 1105A is “no”, meaning that there are at least three input arguments, the programmed computer executes act 1107A, testing whether there are exactly three input arguments (“value”, “left”, and “right”). If the answer is “yes”, the programmed computer executes act 1108A, which processes three input arguments (“value”, “left”, and “right”) via the actions in If the answer to act 1107A is “no”, meaning that there are at least four input arguments, the programmed computer executes act 1109A, testing whether there are exactly four input arguments (“value”, “left”, “right”, and “signed”). If the answer is “yes”, the programmed computer executes act 1110A, which processes four input arguments via the actions illustrated in If the answer to act 1109A is “no”, meaning that there are at least five input arguments, the programmed computer executes act 1111A, testing whether there are exactly five input arguments (“value”, “left”, “right”, “signed”, and “rounding”). If the answer is “yes”, the programmed computer executes act 1112A, which processes five input arguments via the actions illustrated in If the answer to act 1111A is “no”, meaning that there are at least six input arguments, the programmed computer executes act 1113A, testing whether there are exactly six input arguments (“value”, “left”, “right”, “signed”, “rounding”, and “scaling”). If the answer is “no”, there are too many input arguments, which the programmed computer reports as an error via act 1115A. Otherwise, the programmed computer executes act 1114A, which processes six input arguments via the actions illustrated in While this embodiment assumes six arguments to the fxp constructor, a skilled artisan will easily recognize in view of this disclosure that the number, order, and default values for the arguments are details which are easily changed. Other embodiments have separate constructors for (for instance) signed and unsigned fixed-point objects, reducing the number of arguments required. Other embodiments have different ways of expressing precision. Similarly, having separate constructors for real fixed-point objects and complex fixed-point objects is again an arbitrary choice of embodiment; alternative embodiments use a single constructor with an argument or value-test to construct both real and complex fixed-point quantities. If the answer to act 1101B is “no”, the programmed computer then tests whether “value” is a double in act 1103B. In this embodiment, the term “double” includes both “double-precision” and “complex double-precision”. If the answer is “yes”, the programmed computer recursively invokes the fxp constructor function on the first argument (“value”) via act 1104B, passing in the default values for the rest of the arguments of left=8, right=0, signed=1, rounding=[ ] (“[ ]” in MATLAB denotes an “empty” object, which is a special object that has no elements in it; references to an “empty” variable are references to a variable that has the value of [ ]), and scaling=0. These choices of default values are arbitrary, and take on different values in other embodiments. For instance, another embodiment computes the minimum number of bits required to the left and the right of the binary point to correctly hold the double precision number in the first argument (“value”) and uses those values for “left” and “right” rather than 8 and 0. The newly-created fixed-point object “y” is returned after a jump to “wrapup” (act 1110B). Again, both “value” and “y” may be a scalar, a vector, or an array. If the answer to act 1103B is “no”, the programmed computer then tests whether “value” is a logical in act 1105B. If the answer is “yes”, the programmed computer recursively invokes the fxp constructor function on the first argument (“value”) converted to a double. The recursive invocation is via act 1106B, with default values passed in for the rest of the arguments of left=8, right=0, signed=1, rounding=[ ], and scaling=0. These choices of default values are arbitrary, and take on different values in other embodiments. The newly-created real fixed-point object “y” is returned after a jump to “wrapup” (act 1110B). Again, both “value” and “y” may be a scalar, a vector, or an array. If the answer to act 1105B is “no”, the programmed computer then tests whether “value” is a character or character array in act 1107B. If the answer is “yes”, the programmed computer assumes that the input is in the form of a character string expressing the value in hexadecimal form. It calls “parse_hex” (a function which converts numbers in hexadecimal string format into doubles) on the first argument (“value”) to convert it into floating-point in act 1108B, then converts that floating-point result into a real fixed-point object “y” via a recursive call to the fxp constructor function. The other parameters passed to that recursive invocation are the default values of left=8, right=0, signed=1, rounding=[ ], and scaling=0. The newly created real fixed-point object “y” is returned after a jump to “wrapup” (act 1110B). If the answer to act 1107B is “no”, then an unknown or invalid argument has been passed as the first argument, and the programmed computer issues an error message via act 1109B. Note that this embodiment has chosen to deal only with the relatively few types available in MATLAB; a skilled artisan, in view of this disclosure, can easily extend the number of types handled by cascading tests in acts 1101B, 1103B, 1105B, and 1107B. Note also that since MATLAB does not distinguish between vector, scalar, and array types (operators work transparently and polymorphically regardless of shape) that shape and size are not components of the test in this embodiment. A skilled artisan, in view of this disclosure, can easily extend the tests to accommodate languages with richer or stricter typing systems. If the answer to act 1102C is “no”, then the program has received two arguments, the first of which (“value”) is a real fixed-point object and the second of which (“left”) is not. In that case, the programmed computer executes act 1104C, creating a temporary variable “t” which has all the property values of the input fixed-point object. The programmed computer then sets the precision property of “t”; the subproperty left is set to the second input argument (“left”) while the subproperty right is set to 0. Its signedness is set to the default “signed”, and its scaling is set to 0. The function “fixsize” (which for one embodiment is flowcharted in If the answer to act 1101C is “no”, the programmed computer next checks in act 1105C whether the first input argument (“value”) is a double. If “yes”, the programmed computer then checks in act 1106C whether the second argument (“left”) is a fixed-point object (real or complex). If the answer is again “yes”, then the programmer has specified a double and a fixed-point object (either real or complex) as the two input arguments. In this embodiment, the fxp constructor function supports a convention such that when only two arguments are passed to the constructor and the first is a double and the second is a fixed-point object (real or complex), the constructor creates a real fixed-point object that has the value of the first argument (“value”) combined with the property values of the second argument (“left”). Act 1107C implements this convention. It recursively calls the fxp constructor function, passing as arguments the first parameter (“value”) and the property values of the second parameter (“left”) (“left_of_decimal” is a function that returns the number of bits to the left of the binary point for a fixed-point object; “right_of_decimal” is a function that returns the number of bits to the right of the binary point for a fixed-point object; “is_signed” returns 1 if a fixed-point object is signed and 0 if it is unsigned; and “scaling” returns the scaling factor for a fixed-point object). The result real fixed-point object “y” is then returned via a jump to “wrapup” (act 1118C). Again, the input arguments and results may be scalars, vectors, or arrays. If the answer to act 1106C is “no”, then the constructor function has received two doubles as parameters. It converts the first argument into a real fixed-point object and sets the resulting fixed-point objects left subproperty to be the second argument (“left”). This is done by recursively calling the fxp constructor in act 1108C, passing down the received parameters followed by default values of right=0, signed=1, rounding=[ ], and scaling=0. The result real fixed-point object “y” is then returned via a jump to “wrapup” (act 1118C). Again, the input arguments and results may be scalars, vectors, or arrays. If the answer to act 1105C is “no”, the programmed computer next checks via act 1109C whether the first argument is a logical. If the answer to act 1109C is “yes”, then the programmed computer repeats the logic of acts 1106C, 1107C, and 1108C in acts 1110C, 1111C, and 1112C, respectively, but converting the logical “value” to a double before converting it to a fixed-point object. If the answer to act 1109C is “no”, the programmed computer checks via act 1113C whether the first argument is a character string. If the answer to act 1113C is “yes”, then the programmed computer repeats the logic of acts 1106C, 1107C, and 1108C in acts 1114C, 1115C, and 1116C, respectively, but converting the string “value” into a double via the “parse_hex” function before converting it to a real fixed-point object. If the answer to act 1113C is “no”, then the fxp constructor has received a set of invalid arguments and it reports an error via act 1117C. Note that this embodiment has chosen to deal only with the relatively few types available in MATLAB; a skilled artisan, in view of this disclosure, can easily extend the number of types handled by cascading tests in acts 1101C, 1105C, 1109C, and 1113C. Note also that since MATLAB does not distinguish between vector, scalar, and array types (operators work transparently and polymorphically regardless of shape) that shape and size are not components of the test in this embodiment. A skilled artisan, in view of this disclosure, can easily extend the tests to accommodate languages with richer or stricter typing systems. If the answer to act 1001D is “no”, the programmed computer next checks in act 1103D whether the first argument (“value”) is of type double. If the answer is “yes”, then the programmed computer recursively invokes the fxp constructor function in act 1104D, passing in default values of signed=1, rounding=[ ], and scaling=0 for the missing inputs. The result real fixed-point object “y” is then returned via a jump to “wrapup” (act 110D). “Value” and “y” may be scalars, vectors, or arrays. If the answer to act 1103D is “no”, the programmed computer checks in act 1105D whether the first argument (“value”) is of type logical. If so, it repeats the logic of act 1104D in act 1106D after first converting the logical value to a double. Likewise, if the answer to act 1105D is “no”, the computer checks in act 1107D whether the first argument (“value”) is of type char. If so, it repeats the logic of act 1104D in act 1108D, but converting the hexadecimal string into a double. If the answer to act 1107D is “no”, then the fxp constructor has been provided an invalid set of arguments, and it reports an error in act 1109D. Note that this embodiment has chosen to deal only with the relatively few types available in MATLAB; a skilled artisan, in view of this disclosure, can easily extend the number of types handled by cascading tests in acts 1101D, 1103D, 1105D, and 1107D. Note also that since MATLAB does not distinguish between vector, scalar, and array types (operators work transparently and polymorphically regardless of shape), shape and size are not components of the test in this embodiment. A skilled artisan, in view of this disclosure, can easily extend the tests to accommodate languages with richer or stricter typing systems. The programmed computer next checks the type of the first argument (“value”) in act 1106E. If the argument is a real fixed-point object, the programmed computer executes act 1107E to create a temporary variable “t”. The computer creates “t” as an identical copy of the first argument (“value”), then sets the left, right, and signed property values to corresponding parameters. It then calls fixsize (which is flowcharted in If the answer to act 1106E is “no”, the programmed computer next checks in act 1108E whether the first argument (“value”) is of type double or logical. If so, the programmed computer then separates out logicals from doubles in act 1109E, and creates a temporary fixed-point object “t” whose value is set to either the first argument (if it is a double) or to the first argument converted to a double (if the first argument is a logical) via act 11E. Act 1112E completes the fixed-point object by setting the left, right, and signed property values to the corresponding input parameters, setting the scaling to 0 (the default value), setting the object's class to be ‘fxp’ (which in this embodiment is the way of setting the complexness property to be ‘real’), and invoking the function fixsize (which is flowcharted in If the answer to act 1108E is “no”, the programmed computer checks in act 1113E whether the first argument (“value”) is of type char. If so, it recursively invokes the fxp constructor function in act 1114E, passing the first argument (“value”) converted to a double (via the function call “parse_hex” which converts strings in hexadecimal format into doubles), the user-provided arguments of “left”, “right”, and “signed”, and the default values for rounding of [ ] and for scaling of 0. The result real fixed-point object “y” is then returned via a jump to “wrapup” (act 1116E). If the answer to act 1113E is “no”, then the fxp constructor has been called with an invalid set of arguments, and an error is reported via act 1115E. Note that this embodiment has chosen to deal only with the relatively few types available in MATLAB; a skilled artisan, in view of this disclosure, can easily extend the number of types handled by cascading tests in acts 1101E, 1103E, 1106E, 1108E, and 1113E. Note also that since MATLAB does not distinguish between vector, scalar, and array types (operators work transparently and polymorphically regardless of shape) that shape and size are not components of the test in this embodiment. A skilled artisan, in view of this disclosure, can easily extend the tests to accommodate languages with richer or stricter typing systems. Acts 1108F through acts 1117F are identical in function to acts 1106E through acts 1115E in The ‘cfxp’ constructor in this embodiment also provides for changing properties of existing complex fixed-point objects and for converting fixed-point objects and other entities into complex fixed-point objects. This extra functionality is supported through variable calling conventions. For instance, when the first argument to the cfxp constructor is an existing complex fixed-point object, the constructor sets the property values of the existing object to the corresponding passed-in parameters. Thus, if the first argument (“value”) is a complex fixed-point object and only the second (“left”) parameter is passed, the constructor creates a complex fixed-point object whose property values are identical to those of the first parameter (“value”) with the exception of the left subproperty, which is set to the second parameter (“left”). Similarly, if only two arguments are passed to the constructor and the second argument is a fixed-point object (real or complex), the constructor “copies” the properties of the second object other than its value when creating the new complex fixed-point object. That is, it uses the values of left, right, signed, and scaling that are present for the second (“left”) parameter combined with the value of the first (“value”) parameter to construct the new complex fixed-point object. This convention supercedes the first convention, so if the cfxp constructor is called with two complex fixed-point objects as parameters, the result complex fixed-point object has all the property values of the second rather than the property values of the first. Also, if the cfxp constructor is called with two real fixed-point objects having identical property values and with no other parameters, the constructor creates a new complex fixed-point object equal to the “value”+“left”*i (the first parameter becomes the real component of the complex object and the second parameter becomes the imaginary component). In other words, the two real fixed-point objects are treated as components of a complex number, and the new complex fixed-point object has the same properties as both, with one real fixed-point object serving as the real component and the other as the imaginary. This convention supercedes the previous two. In describing the functionality of the cfxp constructor, note that all references to function “fixsize” in Act 1201A of If the answer to act 1201A is “no”, meaning that there is at least one input argument, the programmed computer executes act 1203A, testing whether there is only one input argument (“value”). If the answer is “yes”, the programmed computer executes act 1204A, which sets y to be a complex fixed-point object containing that value via the actions in If the answer to act 1203A is “no”, meaning that there are at least two input arguments, the programmed computer executes act 1205A, testing whether there are exactly two input arguments (“value” and “left”). If the answer is “yes”, the programmed computer executes act 1206A, which processes the two input arguments via the actions in If the answer to act 1205A is “no”, meaning that there are at least three input arguments, the programmed computer executes act 1207A, testing whether there are exactly three input arguments (“value”, “left”, and “right”). If the answer is “yes”, the programmed computer executes act 1208A, which processes three input arguments via the actions in If the answer to act 1207A is “no”, meaning that there are at least four input arguments, the programmed computer executes act 1209A, testing whether there are exactly four input arguments (“value”, “left”, “right”, and “signed”). If the answer is “yes”, the programmed computer executes act 1210A, which processes four input arguments via the actions in If the answer to act 1209A is “no”, meaning that there are at least five input arguments, the programmed computer executes act 1211A, testing whether there are exactly five input arguments (“value”, “left”, “right”, “signed”, and “rounding”). If the answer is “yes”, the programmed computer executes act 1212A, which processes five input arguments via the actions in If the answer to act 1211A is “no”, meaning that there are at least six input arguments, the programmed computer executes act 1213A, testing whether there are exactly six input arguments (“value”, “left”, “right”, “signed”, “rounding”, and “scaling”). If the answer is “no”, there are too many input arguments, which the programmed computer reports as an error via act 1215A. Otherwise, the programmed computer executes act 1214A, which processes six input arguments via the actions in While this embodiment assumes six arguments to the cfxp constructor function, a skilled artisan will easily recognize in view of this disclosure that the number, order, and default values for the arguments are details which are easily changed. Other embodiments have separate constructors for (for instance) signed and unsigned complex fixed-point objects, reducing the number of arguments required. Other embodiments have different ways of expressing precision. Similarly, having separate constructor functions for real fixed-point objects and complex fixed-point objects is again an arbitrary choice of embodiment; alternative embodiments use a single constructor with an argument or value-test to construct both real and complex fixed-point objects. If the answer to act 1201B is “no”, the programmed computer then tests whether the argument (“value”) is a double in act 1203B. In this embodiment, the term “double” includes both “double-precision” and “complex double-precision”. If the answer is “yes”, the programmed computer recursively invokes the cfxp constructor function on input argument via act 1204B, passing in the default values for the remainder of the arguments of left=8, right=0, signed=1, rounding=[ ], and scaling=0. These default choices are arbitrary, and are different in other embodiments. For instance, another embodiment computes the minimum number of bits required to the left and the right of the binary point to correctly hold the “value” argument, and uses those computed minimums for the left and right subproperties, rather than 8 and 0. The newly-created complex fixed-point object “y” is returned after a jump to “wrapup” (act 1210B). Again, both “value” and “y” may be a scalar, a vector, or an array. If the answer to act 1203B is “no”, the programmed computer then tests whether the input argument (“value”) is a logical in act 1205B. If the answer is “yes”, the programmed computer recursively invokes the cfxp constructor function via act 1206B on the double equivalent to the input argument (“value”), with default values passed in for the remainder of the arguments of left=8, right=0, signed=1, rounding=[ ], and scaling=0. These default choices are arbitrary, and are strictly a choice of embodiment. The newly created complex fixed-point object “y” is returned after a jump to “wrapup” (act 1210B). Again, both “value” and “y” may be a scalar, a vector, or an array. If the answer to act 1205B is “no”, the programmed computer then tests whether “value” is a fixed-point object in act 1207B. If “yes”, the programmed computer in act 1208B converts the real fixed-point object into a complex fixed-point object with the same property values by adding an imaginary part of 0. The newly-created complex fixed-point object “y” is returned after a jump to “wrapup” (act 1210B). If the answer to act 1207B is “no”, then an unknown or invalid argument has been passed, and the programmed computer issues an error message via act 1209B. If the answer to act 1201C is “no”, the programmed computer next checks in act 1205C whether the first input argument (“value”) is a double. If “yes”, the programmed computer then checks in act 1206C whether the second argument (“left”) is a fixed-point object (real or complex). If the answer is again “yes”, then the programmer has specified a double and a fixed-point object as the two input arguments. In this embodiment, the cfxp constructor function supports a convention for this argument set of creating a new complex fixed-point object by applying the property values of the second argument to the value of the first. Act 1207C implements this convention. It recursively calls the cfxp constructor function, passing as parameters: the first input argument (“value”) to the current invocation, followed by the property values of the second input argument (“left”) to the current invocation, much as was done in act 1203C. The result complex fixed-point object “y” is then returned via a jump to “wrapup” (act 1224C). Again, the input arguments and results may be scalars, vectors, or arrays. If the answer to act 1206C is “no”, the constructor function has received two doubles as parameters. The constructor converts the first argument into a complex fixed-point object that has the second argument as the value for its left subproperty, and default property values of right=0, signed=1, rounding=[ ], and scaling=0. This conversion is effected by a recursive call to the cfxp constructor function in act 1208C. The default choices for property values that the user did not provide are arbitrary, and differ in other embodiments. The result complex fixed-point object “y” is then returned via a jump to “wrapup” (act 1224C). Again, the input arguments and results may be scalars, vectors, or arrays. If the answer to act 1205C is “no”, the programmed computer next checks via act 1209C whether the first argument is a logical. If the answer to act 1209C is “yes”, then the programmed computer repeats the logic of acts 1206C, 1207C, and 1208C in acts 1210C, 1211C, and 1212C, respectively, but only after converting the logical-typed first argument (“value”) into a double. If the answer to act 1209C is “no”, the programmed computer checks via act 1213C whether the first argument is a real fixed-point object. There is no analogous check in If the answer to act 1213C is “yes”, then the programmed computer tests in act 1214C whether the second argument (“left”) is also a real fixed-point object. If so, then the cfxp constructor function has received two real fixed-point objects as arguments. This embodiment supports the convention whereby the cfxp constructor function creates a new complex fixed-point object equal to “first argument+second argument*i” when passed to real fixed-point objects with identical property values. The property values of the result (other than complexness) are set to be the same as the property values of the input arguments. Before constructing such a complex fixed-point object, the programmed computer checks in act 1215C that the two real fixed-point objects have identical property values (left, right, signedness). If not, then the conditions for the construction of “value+i*left” are not met, and the programmed computer proceeds to act 1216C, where it issues a warning and implements the convention of converting the real fixed-point first argument into a complex fixed-point result by applying the property values of the second. The warning is issued because the resulting complex fixed-point object is known to have an imaginary component of 0. The resulting complex fixed-point object is returned via a jump to “wrapup” (act 1224C). If after act 1215C the two real fixed-point arguments have the same property values, the programmed computer performs another check on the scaling in 1217C. If the scalings of the two fixed-point objects are inconsistent, the computer issues a warning in act 1218C, and sets the scaling for the second argument (“left”) to be non-existent (the floating-point value “NaN” is used to representing a non-provided scaling in this embodiment). “Consistent” scalings in act 1217C are tested by a conjunction of clauses. First, if the scaling factor of either argument is a NaN (as determined by the built-in MATLAB function “isnan”), then no scaling has been provided and there can be no conflict. If both scalings are not NaNs, there is no conflict if they are equal (there is a single scaling factor that can be used for the resulting complex fixed-point number) and there is a conflict if they are not (there is no obvious choice of which one to use for the result). The choice of equal scalings is one particular to this embodiment; other embodiments can adjust the two fixed-point objects so as to obtain an equal scaling. Once scaling has been checked and warnings (if necessary) issued, the programmed computer constructs the complex fixed-point object by a recursively calling the cfxp constructor function in act 1219C, passing down as the first argument the complex combination (“first arg+second arg*i”) for the value and a sample fixed-point object (the second input argument) to provide needed property values. The resulting complex fixed-point object is returned via a jump to “wrapup” (act 1224C). If the second argument (“left”) is not a real fixed-point object in act 1214C, the programmed computer checks whether it is a complex fixed-point object in act 1220C. If “yes”, then the cfxp constructor function has been passed a real fixed-point object (“value”) and a complex fixed-point object (“left”). Following the conventions described earlier, the programmed computer will create a new complex fixed-point object that is a combination of the value of the first argument (with an added imaginary component of 0) and the property values of the second argument. This creation is effected in act 1222C by a recursively invoking the cfxp construction passing as parameters the value of the first argument converted to double precision followed by the property values of the second argument. It returns the newly constructed complex fixed-point object via a jump to “wrapup” (act 1224C). If the second argument (“left”) is not a complex fixed-point object in act 1220C, the programmed computer issues a warning in act 1221C and constructs a complex fixed-point object from the first argument (“value”), using the numerical value of the second argument (“left”) as the left subproperty value. The remaining properties are taken as the standard defaults of right=0, signed=1, and scaling factor equal to that of the first argument. The newly constructed cfxp object is returned in act 1224C. If act 1213C reveals the first argument (“value”) not to be a fixed-point object, the programmed computer issues an error message in act 1223C, indicating that it does not know how to deal with the type of the input argument. Note that this embodiment has chosen to deal only with the relatively few types available in MATLAB; a skilled artisan, in view of this disclosure, can easily extend the number of types handled by cascading tests in acts 1201C, 1205C, 1209C, and 1213C. Note also that since MATLAB does not distinguish between vector, scalar, and array types (operators work transparently and polymorphically regardless of shape) that shape and size are not components of the test in this embodiment. A skilled artisan, in view of this disclosure, can easily extend the tests to accommodate languages with richer or stricter typing systems. If the answer to act 1201D is “no”, the programmed computer checks in act 1203D whether the first argument (“value”) is of type double. If “yes”, then the programmed computer recursively invokes the cfxp constructor function in act 1204D, passing default values of signed=1, rounding=[ ], and scaling=0 for the missing inputs. The result complex fixed-point object “y” is then returned via a jump to “wrapup” (act 1210D). “Value” and “y” may be scalars, vectors, or arrays. If the answer to act 1203D is “no”, the programmed computer checks in act 1205D whether the first argument (“value”) is of type logical. If so, it repeats the logic of act 1204D in act 1206D after converting the logical first argument into a double. If the answer to act 1205D is “no”, the computer checks in act 1207D whether the first argument is a real fixed-point object. If so, the programmed computer recursively calls the cfxp construction function in act 1208D to convert the fixed-point object into a complex fixed-point object. The property values that were not provided in the original constructor call (signedness and scaling) are taken from the property values for the fixed-point object. The resulting complex fixed-point object “y” is returned via a jump to “wrapup” (act 1210D). If the answer to act 1207D is “no”, then the cfxp constructor has been provided an invalid set of arguments, and it reports an error in act 1209D. Note that this embodiment has chosen to deal only with the relatively few types available in MATLAB; a skilled artisan, in view of this disclosure, can easily extend the number of types handled by cascading tests in acts 1201D, 1203D, 1205D, and 1207D. Note also that since MATLAB does not distinguish between vector, scalar, and array types (operators work transparently and polymorphically regardless of shape) that shape and size are not components of the test in this embodiment. A skilled artisan, in view of this disclosure, can easily extend the tests to accommodate languages with richer or stricter typing systems. The programmed computer next checks the type of the first argument (“value”) in act 1206E. If it is a complex fixed-point object, the programmed computer in act 1207E creates a temporary complex fixed-point object “t” identical in value and properties to the first argument. The programmed computer then sets the left, right, and signed property values of “t” to the corresponding arguments passed to the constructor. It then calls “fixsize” (which in one embodiment is flowcharted in If the answer to act 1206E is “no”, the programmed computer next checks in act 1208E whether the first argument (“value”) is of type double or logical. If so, the programmed computer separates out logicals from doubles in act 1209E, creating a double precision temporary variable “t” whose value is that of the first argument converted to double precision. If the first argument is a double, the conversion is trivial (act 1211E); if it is a logical, the conversion is effected in act 1210E. Act 1212E completes the complex fixed-point object by setting the left, right, and signed property values according to the input parameters, by setting the scaling to the default 0, by setting the object's class to be ‘cfxp’ (thereby setting its complexness property value to be complex, marking it as a complex fixed-point object), and invoking the function “fixsize” (which in one embodiment is flowcharted in If the answer to act 1208E is “no”, the programmed computer checks in act 1213E whether the first argument (“value”) is a real fixed-point object. If so, act 1214E creates a new complex fixed-point object by directly assigning the appropriate property values to a new variable “y”. The value of “y” comes from the first argument (converted to a double). Its left and right subproperties come from the second and third arguments, respectively (again, converted to double), and its signedness property comes from the fourth argument. The scaling property value is taken from the corresponding property value of the first argument (“value”). It then sets the class to be ‘cfxp’ (setting the complexness property and marking the object as a complex fixed-point object) and invokes the function “fixsize” (which in one embodiment is flowcharted in If the answer to act 1213E is “no”, then the cfxp constructor function has been called with an invalid set of arguments, and an error is reported via act 1215E. Note that this embodiment has chosen to deal only with the relatively few types available in MATLAB; a skilled artisan, in view of this disclosure, can easily extend the number of types handled by cascading tests in acts 1201E, 1206E, 1208E, and 1213E. Note also that since MATLAB does not distinguish between vector, scalar, and array types (operators work transparently and polymorphically regardless of shape) that shape and size are not components of the test in this embodiment. A skilled artisan, in view of this disclosure, can easily extend the tests to accommodate languages with richer or stricter typing systems. Acts 1208F through acts 1217F are identical in function to acts 1206E through acts 1215E in In certain embodiments, the language MATLAB is extended with software of the type illustrated in the attached files of appendix C which is also called ‘toolbox.’ Such a toolbox enables users to write programs using fixed-point arithmetic rather than the default double precision floating point arithmetic provided in MATLAB. More precise embodiments of this invention execute fixed-point operations precisely. This means that arithmetic results are identical in precision and accuracy to equivalent operations executed on typical fixed-point hardware such as that found on a Digital Signal Processor (DSP). Depending on the embodiment, signed and unsigned operands are supported, as are modulo and saturation arithmetic. Certain embodiments of the fixed-point toolbox for MATLAB as described herein provide both real and complex fixed-point numbers. Even though real fixed-point numbers are a subset of complex fixed-point numbers, there is an execution-speed advantage to having a separate representation. Since the imaginary component of a real fixed-point object is known to be zero, fewer operations are required to implement arithmetic for real fixed-point objects than for complex fixed-point objects. Rounding modes for results can be selected from round to nearest, round towards zero, round toward positive infinity, and round toward negative infinity. Certain embodiments of the toolbox simplify the conversion of programs that have already been written using default, double precision MATLAB, into fixed-point arithmetic. By using the class and operator-overloading features of MATLAB, those embodiments enable the conversion of a working double precision program into fixed-point arithmetic by the insertion of a small number of constructors and assignment statements. Because they are working on fixed-point hardware which has a limited dynamic range, DSP programmers typically have to scale operands to keep values within a reasonable range. The scaling factor is often kept only in the programmer's head, creating troublesome bugs when a scaling is not carried through an operation correctly. Several embodiments of the toolbox described herein provide for implicit scalings to be carried along with fixed-point operations and correctly maintains these scalings through most arithmetic operations. Warnings are issued when an invalid arithmetic operation is attempted on differently-scaled operands (for instance, when adding two fixed-point objects with different scalings). Mathematical functions, and in particular, transcendental functions, are widely used in DSP and fixed-point applications. Certain embodiments of the invention support mathematical and transcendental functions for fixed-point objects by expanding the fixed-point objects to floating-point, calling the equivalent double precision function, and then reducing the floating-point results back to fixed-point. While these embodiments provide a high degree of precision, they do not generally provide results that are bitwise identical to the results produced on fixed-point hardware and DSPs. The reason is that fixed-point hardware typically uses a coarse approximation to true function values, often (but not always) implemented via a set of lookup tables and polynomials. Other embodiments of this invention enable the emulation to get bitwise identical results to fixed-point hardware for transcendental functions. This accuracy is achieved by allowing the high level program to directly call the functions used on the fixed-point hardware. Such a toolbox provides a facility that allows transcendental functions written in C to be easily plugged into an application. In addition to providing MATLAB applications with the exact precision that a final application will have, this facility also permits early prototyping and exploration of DSP transcendental and mathematical functions. Therefore, a toolbox as described herein allows users to write their own functions using fixed-point operations and call a large number of basic MATLAB functions with fixed-point arguments, obtaining fixed-point results. Furthermore, a toolbox as described herein also allows users to directly make use of existing libraries (or toolboxes) of functions that are provided in source form, and to write fixed-point source form representations for functions in libraries (or toolboxes) that are not provided in source form. For instance, some embodiments of the toolbox extend fixed-point support to include both the Signal Processing and Communications toolboxes of MATLAB. Various embodiments will execute the package in different ways, depending on the details of the supported language. One embodiment for MATLAB, for instance, places the functions for the overloaded operators in some number of directories, which are added to the MATLAB search path using either the MATLAB command “pathtool” or the command “addpath”. One embodiment of a fixed-point toolbox of the type described herein may support fixed-point programming by adding two new data types to MATLAB using the class and operator overloading facilities: “fxp” to support real fixed-point objects and “cfxp” to support complex fixed-point objects. These two types of operands have the same basic properties and are similar in functionality. Fxps are cfxps whose imaginary part is known to be zero. While this embodiment could have been implemented with just cfxps (and any skilled practitioner will recognize that such embodiments are covered by the invention), separating real and imaginary fixed-point data types provides several computational efficiencies. The two data types are identical in their properties (other than the fact that fxps have no imaginary component), so the two types may be considered interchangeable in this discussion, although they certainly cannot be considered interchangeable in implementation. Numerous modifications and adaptations of the embodiments, implementations and examples described herein will be apparent to the skilled artisan in view of the disclosure For example; although some embodiments are implemented as a toolbox that extend MATLAB version 6, other embodiments may extend other MATLAB versions. Still other embodiments may extend other interpreters, such as GNU Octave which is described at, for example, http://www.octave.org/doc/octave_toc.html. Moreover, depending on the embodiment, a binary point's position in a fixed-point operand can be expressed as follows: (a) number of bits to the left of binary point and number of bits to right of binary point, (b) number of bits to left of binary point and total number of bits, and (c) number of bits to the right of binary point and total number of bits. The specific manner in which the binary point's position is stored in such an object is not a critical aspect of several embodiments of the invention. In some embodiments, the above-described emulation is performed only on receiving an explicit indication from the user that an operand is to be expressed in a fixed-point representation (e.g. by invocation of a function in case of an interpreter or by declaration of a variable as being of fixed-point type in case of a compiler). Note that in certain embodiments, operands may simply default to a predetermined fixed-point representation (e.g. in case of a language that is known to be a fixed-point language), and hence such embodiments do not require an explicit indication to perform the above-described emulation. In some embodiments, methods of the type described herein perform the same or similar operations for vector operands as for scalar operands. For example, such methods include receiving a set of instructions executable by a computer that supports floating-point arithmetic; receiving at least one operand (hereinafter “fixed-point vector”) that is comprised of a vector, array, or other collection of elements, the first element of which is a fixed-point object, and the collection has at least a second element that is another fixed-point object; expanding said fixed-point vector into a floating-point representation to obtain a floating-point vector equivalent; receiving an instruction comprising an operation to be performed on the fixed-point vector; performing on the floating-point equivalent, at least one floating-point operation that corresponds to the fixed-point operation, yielding at least one floating-point result; and reducing at least one floating-point result generated by the floating-point operation into a corresponding fixed-point result. In some embodiments, methods of the type described herein that perform operations on fixed-point vector operands have first elements and second elements with identical word length and with binary points at identical positions. In some embodiments, methods of the type described herein that perform operations on fixed-point vector operands have first and second elements with at least one identical property, and the value of that property is stored in one memory location for the entire fixed-point vector. In some embodiments, that property is precision. In some embodiments, that property is the signedness of the fixed-point operand. In some embodiments, that property is complexness. In some embodiments, that property is scaling. In some embodiments, methods of the type described herein that perform operations on fixed-point vector operands produce a scalar fixed-point result. In some embodiments, the scalar fixed-point result has at least one property (signedness, complexness, precision, scaling). In some embodiments, the property of the fixed-point result depends on at least one property of the fixed-point vector operand. In some embodiments, the property of the fixed-point result depends on the instruction that was performed on the fixed-point vector operand. In some embodiments, methods of the type described herein use a representation for the fixed-point vector operand that stores the values of the operand in memory in floating-point format, including such formats as IEEE standard 754 for floating-point representation. In some embodiments, the representation for the fixed-point result stores the values of the result in memory in floating-point format, including such formats as IEEE standard 754 for floating-point representation. In some embodiments, methods of the type described herein use a representation for the fixed-point vector operand that stores a value in memory to distinguish between signed and unsigned numbers. In some embodiments, methods of the type described herein use a representation for the fixed-point result that stores a value in memory to distinguish between signed and unsigned numbers. In some embodiments, methods of the type described herein use a representation for the fixed-point vector operand that stores a value in memory to distinguish between real and complex numbers. In some embodiments, methods of the type described herein use a representation for the fixed-point result that stores a value in memory to distinguish between real and complex numbers. In some embodiments, methods of the type described herein use a representation for the fixed-point vector operand that stores the precision of the vector in memory. In some embodiments, methods of the type described herein use a representation for the fixed-point result that stores the precision of the result in memory. In some embodiments, methods of the type described herein use a representation for the fixed-point vector operand that stores a scaling factor in memory In some embodiments, methods of the type described herein use a representation for the fixed-point result that stores a scaling factor in memory. In some embodiments, methods of the type described herein store the position of the binary point of the fixed-point vector operand, prior to performing floating-point arithmetic operations, and use that stored position during conversion of the floating-point result into the corresponding fixed-point result. In some embodiments, methods of the type described herein use a predetermined storage element to identify a mode of rounding to be used when reducing a floating-point result to a corresponding fixed-point result, where the mode of rounding is one of: round (round-to-nearest), fix (round towards zero), ceil (round towards positive infinity), and floor (round towards negative infinity). In some embodiments, methods of the type described herein use a predetermined storage element to identify a kind of arithmetic to be performed on the floating-point operand, wherein the kind of arithmetic is one of: saturation and modulo. In some embodiments, methods of the type described herein use a predetermined storage element to identify a kind of arithmetic to be applied during conversion of a floating-point result into a corresponding fixed-point result, wherein the kind of arithmetic is one of: saturation and modulo. In some embodiments, methods of the type described herein detect during conversion of the floating-point result into the corresponding fixed-point result whether any values exceed the range of values accepted by the corresponding fixed-point result, and issue a warning message controlled by a predetermined storage element. In some embodiments, methods of the type described herein express the corresponding fixed-point result with properties that are different from the fixed-point vector operand, and use a predetermined storage element to identify a property of the fixed-point result. Said property may be precision, signedness, or complexness. In some embodiments, methods of the type described herein use a predetermined storage element to identify a mode of rounding to be performed when reducing a floating-point result into the corresponding fixed-point result, wherein the mode of rounding is one of: round (round-to-nearest), fix (round towards zero), ceil (round towards positive infinity), and floor (round towards negative infinity). In some embodiments, methods of the type described herein perform the same or similar operations for vector operands as for scalar operands, producing vector results. For example, such methods include receiving a set of instructions executable by a computer that supports floating-point arithmetic; receiving at least one operand (hereinafter “fixed-point vector”) that is comprised of a vector, array, or other collection of elements, the first element of which is a fixed-point object, and the collection has at least a second element that is another fixed-point object; expanding said fixed-point vector into a floating-point representation to obtain a floating-point vector equivalent; receiving an instruction comprising an operation to be performed on the fixed-point vector; performing on the floating-point equivalent, at least one floating-point operation that corresponds to the fixed-point operation, yielding at least one floating-point vector result (where a “vector result” is a vector, array, or other collection of elements); and reducing at least one floating-point vector result generated by the floating-point operation into a corresponding fixed-point vector result, where “fixed-point vector result” is a vector, array, or collection of elements wherein the first element is a fixed-point object, and at least a second element of the collection is another fixed-point object. Furthermore, in some embodiments the methods described herein may have said first element and said second element of the fixed-point vector result having at least one identical property, and the value of that property is stored in one memory location for the entire collection. Said property may be precision, signedness, complexness, or scaling. In some embodiments, the methods described herein have a vector fixed-point result that has at least one property. In some embodiments, said property depends on said at least one property of the fixed-point vector operand. In some embodiments, said property depends on the instruction that was performed on the fixed-point operand. In some embodiments, the computer stores the value of the vector fixed-point result in floating-point format, including the IEEE 754 standard for floating-point numbers. In some embodiments, the computer stores a value in memory to determine the signedness of the vector fixed-point result. In some embodiments, the computer stores a value in memory to determine the complexness of the vector fixed-point result. In some embodiments, the computer stores the precision of the vector fixed-point result in memory. In some embodiments, the computer stores the scaling factor of the vector fixed-point result in memory. In some embodiments, the methods described herein store the position of a binary point of the vector fixed-point operand prior to performing the floating-point arithmetic operation, and use the stored position of the binary point of the vector fixed-point operand when reducing the floating-point result into the corresponding vector fixed-point result. In some embodiments, the methods described herein use a predetermined storage element to identify a mode of rounding to be performed when reducing a vector floating-point result into a vector fixed-point result, wherein the mode of rounding is one of: round (round-to-nearest), fix (round towards zero), ceil (round towards positive infinity), and floor (round towards negative infinity). In some embodiments, the methods described herein use a predetermined storage element to identify a kind of arithmetic to be performed during performance of the floating-point arithmetic operation on the vector floating-point equivalent, wherein the kind of arithmetic is one of: saturation and modulo. In some embodiments, the methods described herein use a predetermined storage element to identify a kind of arithmetic to be performed during conversion of the vector floating-point result into the vector fixed-point result, wherein the kind of arithmetic is one of: saturation and modulo. In some embodiments, methods of the type described herein detect during the conversion of the vector floating-point result into the corresponding vector fixed-point result whether any values of the result exceeds the range of values accepted by the corresponding fixed-point result and issuing a warning message controlled by a predetermined storage element. Exceptions that may occur during floating-point execution include Not a Number (NAN): this can only occur when dividing by 0 in the fixed-point input. Some embodiments trap this error before performing a floating point operation by checking if the divisor is zero. In some embodiments that support complex and real fixed point numbers, no other fixed point operations lead to a floating point operation that can generate a NaN. In embodiments that support only real fixed point numbers, exceptions that can generate complex results are trapped and reported as errors. Fixed-point exceptions that can occur are overflow (which is trapped to implement saturation/modulo arithmetic), divide-by-zero (which is trapped as noted above), and overflow due to exceeding the number of digits in the emulation (which is trapped explicitly e.g. by the 53rd bit in IEEE 754). Numerous such modifications and adaptations are encompassed by the attached claims. Certain embodiments of the invention are described below in APPENDIX A, while one particular implementation is described below in APPENDIX B. APPENDICES A and B are both incorporated by reference herein in their entirety and form integral portions of this disclosure. Embodiments may or may not require an initialization function. One specific embodiment uses a function “fxp_init” for initialization. Fxp_init allows the user to set the way in which arithmetic operations are performed. If the user does not explicitly initialize the fixed-point toolbox by calling fxp_init, the toolbox assumes a set of defaults. In that particular embodiment, fxp_init can take up to 6 parameters:
In this embodiment, once the fixed-point package has been initialized using fxp_init, real fixed-point objects and complex fixed-point objects can be created using the constructors fxp and cfxp, respectively. These constructors return as their result a real fixed-point object or a complex fixed-point object, respectively, and take up to six parameters:
This call uses whatever default rounding is in effect. Assuming ‘r’ rounding, the entering the command to display “a” at the MATLAB prompt yields:
as with any other MATLAB variable. Similarly, assuming saturation arithmetic is in effect, one can type expressions using a
and so on. The first example shows saturation at the maximum value for a 2 bit number; the second example shows that doubles and fixed-point objects can be mixed in expressions. Whole vectors or arrays can be converted to fixed-point representation:
Note that only 3 parameters are passed to the fxp call. The fourth parameter (the signed value) defaults to ‘s’ when not specified, which is why the last 2 values become “7”−“7” is the largest value that can be represented with 3 value bits and 1 sign bit. A complex fixed point number follows the same conventions:
The above example illustrates displaying a value of a variable. The constructor functions fxp and cfxp will convert values other than just doubles to fixed-point representation. Real and complex fixed-point objects can also be passed as the first parameter to the constructors, allowing changes in size or representation. In this embodiment, the constructors also accept hexadecimal notation:
The following example illustrates the use of scaling factors:
This example creates an unsigned real fixed-point object whose value is 0.5 using the default rounding mode. While the value of the fixed-point object proper is 0.5, the value of the real number corresponding to the fixed-point object is actually 0.5*2̂8, or 128. Similarly, a real fixed-point object created by
would also have the value 0.5, but the real number would be 0.5*2̂−8, or 0.001953125. Scaling factors are carried along by the fixed-point toolbox, so that if the computation
the fixed-point toolbox knows that the scaling on c is 0 (8−8), so that the true result is 0.25*2̂0==0.25. Scalings are typically invisible to the user unless debug options are turned on inside the toolbox. In this embodiment, scalings are the most useful to a programmer when the option warn_on_scaling is enabled. With that option, an attempt to combine two invalidly scaled numbers results in a warning message. Continuing the sequence above with scaling warnings enabled:
The above example illustrates displaying a value of a result of evaluation of an operation (subtraction) and a warning. Since a is scaled by 2̂8 and c is scaled by 2̂0, subtracting them is an invalid operation. The correct result is obtained and printed for the fixed-point objects (0.25=0.5-0.25), but that result is not correct for the real numbers represented by the scaling (0.5*2̂8−0.25). Several embodiments of the fixed-point toolbox always compute correct results for numbers ignoring the scaling factors, using the scaling only to issue warnings. Note that no warning would be issued for the product a*b despite their different scaling, since the true result can be computed for products of differently scaled numbers. While the “fxp” and “cfxp” constructor functions are the primary ways of creating fixed-point objects, there are alternative versions that take other number formats for users that desire that. Certain embodiments of the fixed-point toolbox simplify as much as possible the conversion of working double precision programs into fixed-point operation. Ignoring precision issues, the only thing required to convert most double precision programs into fixed-point representation is insertion of constructors at the beginning of the computation; the package takes care of everything else. For example, consider the following simple program obtaining the DCT (Discrete Cosine Transform) of a sequence of numbers (assuming that the Signal Processing Toolbox is installed as part of MATLAB):
Converting this program to fixed point requires only the following change:
The answers come out slightly different because the arithmetic was performed in fixed point rather than double precision. Fixed-point arithmetic can be performed in a number of different ways, as is obvious in the parameters to fxp_init. While most applications generally want to use the same options throughout the entire computation, there are other times when a rounding mode or saturation option needs to be changed for just one operation or a small number of operations. This embodiment contains a number of functions that make that easy to accomplish. The following functions may be called any time after fxp_init to set or uncover current arithmetic options:
This embodiment provides a number of warnings to help in program development and debugging, including detections of things such as overflowing a fixed-point number, converting a negative number into an unsigned, or using a fixed-point number which is an unusual size and may not allow for reasonable code generation. By default, fxp_init starts the fixed-point package will all warnings enabled, but users may turn them on and off at will using the function fxp_warn. In this embodiment, fxp_warn takes a variable number of arguments, which may be taken from the following list:
The embodiment may also contain display options that help in debugging fixed-point programs. While it is useful to have printing routines such as MATLAB's “display” routine for real and complex fixed-point objects use a format string that is identical to MATLAB's display format, it is also useful to have the fixed-point object display routine support an extended format that gives more information specific to fixed-point objects, such as signedness, number of bits, and scaling. In this embodiment, this extended format is enabled and disabled by the routine fxp_debug. The call fxp_debug(‘on’) enables the extended information; the call fxp_debug(‘off’) returns to normal MATLAB display mode. This routine affects only the display of fixed-point numbers. Following is a sample of the information provided:
The above example illustrates displaying a scaling factor and a property, of a result of evaluation of an operation. The toolbox also contains a function fxp_view that permits viewing of fixed-point objects in various formats, including hexadecimal. Fxp_view takes up to 3 parameters: a) the value or vector to be displayed; b) the format for displaying the data, which can be ‘f’ for double precision, ‘x’ for hexadecimal, or ‘b’ for binary; and c) an optional scaling factor by which the value is multiplied before display. Arithmetic operators in this fixed-point toolbox behave much the same way that they do in basic MATLAB. As a result, a fixed-point program looks identical to a double precision computation, other than the initial fxp and cfxp constructors. All operators follow the same rules as MATLAB with respect to operations on scalars, vectors, and arrays. So, for instance, it is legal to add a scalar fixed-point object to a vector fixed-point object. Additions in the fixed-point toolbox not present in basic MATLAB include the notion of signed and unsigned, and the explicit separation of real fixed-point objects from complex fixed-point objects. The package does support mixed operations among these various types. The rules governing such conversions are fairly simple. When an operation is specified between an unsigned operand and a signed operand, the package will first convert the signed operand to unsigned; the result is also unsigned following the rules of C. When an operation is specified between a real and a complex fixed-point object, the real object is promoted to a complex object and the result is a complex fixed-point object. When an operation is specified between a fixed-point object and a double (“double” here means MATLAB “double”, which can be either double precision or complex), the double is converted to the same type as the fixed point object before the operation is performed. When a non-multiplicative operation is specified between a fixed-point object and a logical, the logical is converted to the same type as the fixed-point operand before the operation is performed. For multiplicative operations, the fixed-point operand is converted to double precision before performing the arithmetic, and the result is converted back to the fixed-point type. The reason for this is that multiplicative logical operations are often used to select elements of another matrix. This definition allows that selection to occur without changing the types of the result elements. No other implicit conversions are performed. The toolbox flags such conversions as errors. Certain embodiments of the fixed-point toolbox do not support operations between fixed-point objects that have different right or left properties. However, other embodiments of the fixed-point toolbox do not impose such a restriction. The following table (Table B) lists all operators supported by certain embodiments of the fixed-point toolbox, the behavior and size of the result, and any special notes. The notation “fxp(a,b)+fxp(a,b)->fxp(c,d)” means that the addition of two real fixed-point objects both having values of “a” for the number of bits to the left of the decimal and “b” for the number of bits to the right of the decimal results in a real fixed-point object with “c” bits to the left of the decimal and “d” bits to right. The behavior of signed and unsigned operands is described by the rule above. This table also comprises part of a result characteristic function, providing in this embodiment the details of how the precision of the result is determined from the precision of the operands.
In default mode, the toolbox computes products and quotients exactly (with the exception of the most negative case of signed multiplies and quotients) by doubling the number of bits of output. This level of precision is necessary for many signal processing applications, but it does cause the precision of results to continually increase, leading eventually to an overflow of the fixed-point space if many multiplications are performed and the results not trimmed on the right. The toolbox also supports an alternative mode where the results of multiplications and divisions are the same size as the input operands (that is, fxp(a,b)*fxp(a,b)->fxp(a,b)). This mode tends to be more useful when the extra bits of precision are not necessary for multiplies and divides, as it automatically inserts the conversions that a programmer would have to insert by hand. This mode is enabled by use of the fxp_short routine. Fxp_short takes one parameter. If that parameter is ‘on’, the short multiply mode is enabled; if that parameter is anything else, the short multiply mode is disabled. In addition to the basic arithmetic operators, the fixed-point toolbox also supports many of the primitive functions used by MATLAB. The complete list of supported functions in one embodiment of the fixed-point toolbox is as follows:
The transcendental functions sin, cos, and exp are used in several algorithms in DSP processing. Creating general fixed-point implementations of these functions, however, is a challenging task. Obtaining accurate answers over the entire range of possible inputs requires argument reduction and fairly long series computations. More often than not, particular DSP implementations only need reasonably accurate results over a restricted range of inputs. As a result, a restricted implementation of the transcendentals over expected inputs is usually much faster and better tailored to the particular DSP problem than a general implementation. This creates a two-stage requirement for transcendental implementation in a fixed-point toolbox of the type described herein. Early prototyping stage requires existing general implementations of transcendentals so that users can evaluate algorithms without having to worry about implementing transcendentals. However, at the later stages of implementation, users will want to evaluate their computations using the same hand-tailored function implementations that will be used in the final implementation on the processor, so that they get bit-accurate simulation results identical to the results produced on the processor. This embodiment provides support for both stages of implementation, allowing users to easily plug in their own implementations of sin, cos, and exp. By default, a call to a transcendental on a fixed-point object (real or complex) will result in a call to the appropriate MATLAB double precision routine to obtain a full precision result, followed by a conversion back to a fixed-point number with the same properties as the argument. Thus, by doing nothing a user will obtain highly accurate results for the transcendental functions over all argument ranges. However, if a user provides a version of a transcendental function written in C, the fixed-point package will automatically incorporate it and call it to evaluate transcendentals. This allows users to easily evaluate their own transcendental implementations as well as get totally accurate results from their MATLAB simulations. All the complex fixed-point transcendental functions call various combinations of real fixed-point functions to obtain their results; so there should be no need to replace the complex fixed-point functions with the user's C versions. The fixed-point toolbox currently supports the following mathematical/transcendental functions:
This embodiment provides a number of functions solely for the support of fixed-point objects. These include:
To illustrate the simplicity of converting a working double precision MATLAB program into fixed-point in this embodiment, consider the following general FIR filter:
This generic form of the filter accepts both coefficients and data, and returns the filtered result. For instance, a typical call might be:
Because the function “fir” is written using generic MATLAB operands, it can be invoked directly without change on fixed-point operands. For instance, inserting the conversion:
performs the filter as a fixed point operation, rather than as double precision. Given the choice of input data and coefficients, it's easy to see that the output will be the same, but it's also easily verified as well:
As you can see, the conversion was easy, but the answer in the fixed-point case is 5 times larger than the correct answer—not what we'd expect given the input data and simple coefficients. Turning on the warnings, it's easy to find the answer:
Using the MATLAB debugger to stop on warnings, it's easy to find the problem—the length of x inside the fir function is 4, which overflows and saturates at essentially 1 when converted into an fxp(1, 7), causing the answer to be 4 times too big. This hypothesis can easily be verified by increasing the number of bits on the left:
and we see the expected answer. However, we see we have an odd number of bits in the fixed-point object, which is not desirable, so we see if we can reduce it to a total of 8.
As we expected, we cannot. While the coefficients can be exactly represented with 4 bits to the right of the decimal place, the data (0.1) has too much error:
Given that we need the bits on precision on the right, the simplest fix is to slightly modify our original fir function, eliminating the overflow:
By doing the division in double precision, we keep our number within our scaling, and going back to our original fxps, we will get an exact answer:
One specific embodiment of the fixed-point toolbox described in the attached files of appendix C implements all the operators and functions described above. Any user function or MATLAB function that uses only these operators or functions will convert automatically to fixed-point operation by simply passing in a vector containing fixed point. For instance, the following simple fir function:
will work correctly when passed a vector of fixed-point objects as well as when passed a vector of double precision numbers. The coefficients will automatically be converted to the same precision as the fixed-point objects by the package. This allows for an easy way of minimizing the number of bits required while maintaining required error tolerances. For instance, given the simple input sequence a=[1 2 3 4], the following loop:
showing the increase in error as the number of bits of precision drop off. The coefficients were chosen to be 1/(2̂i) for i=1, 3, 5, 7, showing the error increases across those boundaries. Certain embodiments (this one in particular) of the fixed-point toolbox do not support mixed mode arithmetic. That is, two operands must have the same number of bits to the left of the decimal and the same number of bits to the right of the decimal, or the fixed-point toolbox issues an error. This restriction is not present in other embodiments of the fixed-point toolbox, so that any precision numbers may be combined. Some embodiments of the fixed-point toolbox contain a routine “fxp_precision” which allows the user to specify the desired precision on specific operators or functions. Several embodiments of the type described herein have the following features:
In contrast to conventional range capture of the type described by Lee in U.S. Pat. No. 6,460,177, wherein a user executes a program in floating point using class structures to capture the dynamic range of the variable, several embodiments of the type described herein a) convert to a fixed-point representation that is chosen by the user based on their past experience, b) run that on the sample data, c) if the error is acceptable, keep it, otherwise adjust and go back to b). Range capture can be used in this embodiment, if desired, before step a) in order to obtain information to make a better estimate. However, such range capture would still be very different from Lee's range capture, because dynamically-typed languages such as MATLAB do not support the type of range capture envisioned by Lee. The Catalytic FxP Toolbox is a Matlab package that enables users to write computations using fixed-point arithmetic rather than the default double precision floating point arithmetic provided in Matlab. The toolbox executes fixed-point operations precisely. This means that results are identical in precision and accuracy to operations executed on typical fixed-point hardware such as that found on a Digital Signal Processor (DSP). Signed and unsigned operands are supported, as are modulo and saturation arithmetic. The toolbox provides both real and complex fixed-point numbers. Real fixed-point numbers (also called fxps) execute faster than complex fixed-point numbers (also called cfxps) because the imaginary component is known to be zero. Rounding modes for results can be selected from round to nearest, round towards zero, round toward positive infinity, and round toward negative infinity. One of the major goals of the toolbox is to simplify as much as possible the conversion of computations written using default, double precision Matlab into fixed-point arithmetic. Because the FxP Toolbox uses the class and operator-overloading features of Matlab, converting a working double precision program into fixed-point arithmetic usually requires only the insertion of a small number of constructors and assignment statements. DSP programmers typically scale operands to keep values within a reasonable range. The scaling factor is often kept only in the programmer's head, creating troublesome bugs when a scaling is not carried through an operation correctly. The FxP Toolbox provides for implicit scalings to be carried along with fixed-point operations and correctly maintains these scalings through most arithmetic operations. Warnings are issued when an invalid arithmetic operation is attempted on differently-scaled operands (for instance, when adding two fixed-point operands with different scalings). Transcendental functions are essential to many fixed-point applications but vary widely by application as far as the amount of precision required. Typically these functions are hand-written by applications programmers to provide just the amount of precision required. The only way to exactly match the precision of such functions over their entire domain is to use those functions directly. In order to allow this behavior, the FxP Toolbox provides a mechanism for easily replacing transcendental functions. The default behavior of the toolbox for an fxp transcendental call is to convert the fxp to double-precision, call the appropriate double-precision C math routine, then convert the results back into an appropriate fxp or cfxp. However, the toolbox also provides a facility that allows transcendental functions written in C to be easily plugged into an application. In addition to providing Matlab applications with the exact precision that a final application will have, this facility also permits early prototyping and exploration of DSP transcendental functions. The basic FxP Toolbox allows users to write their own functions using fixed-point operations and call a large number of basic Matlab functions with fixed-point arguments, obtaining fixed-point results. The enhanced FxP Toolbox extends fixed-point support to include both the Signal Processing and Communications toolboxes of Matlab^{1}. ^{1 }In order to use the extended features of the enhanced Catalytic FxP Toolbox, you must be licensed for the appropriate Matlab toolboxes (Signal Processing, Communications, or both) from MathWorks. The Catalytic FxP Toolbox is shipped as a gripped tar file “cfpl.tgz”. All that is necessary to install the package is to unload the tar file in the directory where you wish the package to reside (the “install directory”). Catalytic recommends the install directory “Catalytic/fxp” underneath “My Documents”, but any directory is fine. If you are running a UNIX emulation under Windows (such as the MKS Toolkit or Cygnus Cygwin), the commands “cp cfpl.tgz <install directory>; cd <install directory>; gunzip cfpl.tgz” will execute the install process. If you are not running a UNIX package, the WinZip utility is one of many that can be used to unload the installation file. To execute the package, it is necessary to add the three directories to your Matlab path: the install directory, and the “toolbox” and “support” directories underneath it. The easiest way to do this is to use the Matlab command “pathtool”. Once inside pathtool, you can click on the “Add Folder” button then graphically select and add <install directory>, <install_directory>/toolbox, and <install_directory>/support to add them to your path (Catalytic recommends putting them at the end of your path, but they work correctly at any position). If you make these changes permanently to your path (either by clicking the “Save” button or by replying “Yes” when you exist “pathtool”), you will only need do this change once, and not every time you start Matlab. You can also make the changes by using the commands “addpath ‘<install directory>’;”, “addpath ‘<install directory>/toolbox’;”, “addpath ‘<install_directory>/support’;” inside Matlab. To avoid entering the “addpath” commands every time you start up Matlab, you will most likely want to add these commands to your startup.m file in your base Matlab work directory, which is $matlabroot\work. The Matlab help documentation provides more information on startup.m if you need it. Once the tar file has been unloaded and the Matlab “addpath” command has been executed, the installation can be verified by typing the command “fxp_test”. If the package has been installed correctly, the phrase “Correct installation verified.” will be printed. If the package does not appear to be installed correctly, contact support@catacomp.com for help troubleshooting. The Catalytic FxP Toolbox provides fixed-point by adding two new data types to Matlab:
Cfxps and fxps have the same basic properties and are similar in functionality. Fxps are cfxps whose imaginary part is known to be zero. The package could easily have been implemented with just the complex representation, using cfxp's with imaginary values of 0 for fxp's. The dual representation was motivated by speed; there are several computational efficiencies that can be implemented when the imaginary part is known to be zero. The two data types are identical in their properties (other than the fact that fxps have no imaginary component), so the two types may be considered interchangeable in the remainder of this discussion. The FxP Toolbox must be initialized with the function fxp_init prior to using any fxps or cfxps. Fixed-point operations can be performed in a number of different ways (modulo arithmetic versus saturation on overflow, for instance). Fxp_init allows the user to set the way in which arithmetic operations are performed. If the user does not explicitly initialize the FxP package by calling fxp_init, the toolbox assumes a reasonable set of defaults. Fxp_init can take up to 6 parameters:
Since fxp_init accepts a variable number of arguments, it is necessary to specify only the first arguments where the default values differ from those you desire. Also note that fxp_init is not the only way of requesting arithmetic change, rounding change, or warnings; it is simply a convenient way of starting up with your desired environment. There are other functions that allow you to change these parameters any time during execution. Once the fixed-point package has been initialized using fxp_init, fxps and cfxps can be created using the constructors fxp and cfxp, respectively. These constructors return as their result an fxp or cfxp, and take up to six parameters:
Using the earlier example to convert the double value 1.25 into an unsigned 2 bit fxp, all we need do is make the following call: This call will use whatever default rounding is in effect. Assuming ‘r’ rounding, the entering the command to display “a” at the Matlab prompt yields:
In other words, fxps behave just like other Matlab variables. Similarly, assuming saturation arithmetic is in effect, one can type expressions using “a”
and so on. The first example shows saturation at the maximum value for a 2 bit number; the second example shows that doubles and fxps can be mixed in expressions. Whole vectors or arrays can be converted to fixed-point representation:
Note that only 3 parameters are passed to the fxp call. The fourth parameter (the signed value) defaults to ‘s’ when not specified, which is why the last 2 values become “7”. “7” is the largest value that can be represented with 3 value bits and 1 sign bit. A complex fixed point number follows the same conventions:
The constructor functions fxp and cfxp will convert values other than just doubles to fixed-point representation. Fxps and cfxps can also be passed as the first parameter to the constructors, allowing changes in size or representation. The constructors also accept hexadecimal notation:
The following example illustrates the use of scaling factors:
This example creates an unsigned fxp whose value is 0.5 using the default rounding mode. While the value of the fxp proper is 0.5, the value of the real number corresponding to the fxp is actually 0.5*2̂8, or 128. Similarly, an fxp created by
would also have the value 0.5, but the real number would be 0.5*2̂−8, or 0.001953125. Scaling factors are carried along by the FxP Toolbox, so that if the computation
is requested, the FxP Toolbox knows that the scaling on c is 0 (8−8), so that the true result is 0.25*2̂0==0.25. Scalings are typically invisible to the user unless debug options are turned on inside the toolbox. Scalings are the most useful to a programmer when the option warn_on_scaling is enabled. With that option, an attempt to combine two invalidly scaled numbers results in a warning message. Continuing the sequence above with scaling warnings enabled:
Since a is scaled by 2̂8 and c is scaled by 2̂0, subtracting them is an invalid operation. The correct result is obtained and printed for the fxps (0.25=0.5-0.25), but that result is not correct for the real numbers represented by the scaling (0.5*2̂8−0.25). The FxP Toolbox always computes correct results for numbers ignoring the scaling factors, using the scaling only to issue warnings. Note that no warning would be issued for the product a*b would be issued despite their different scaling, since the true result can be computed for products of differently scaled numbers. One of the major design goals of the Catalytic Fixed-Point Library is to simplify as much as possible the conversion of working double precision programs into fixed-point operation. Ignoring precision issues, the only thing required to convert most double precision programs into fixed-point representation is the insertion of constructors at the beginning of the computation; the package takes care of everything else. For example, consider the following simple program obtaining the DCT of a sequence of numbers (assuming that you have the Signal Processing Toolbox installed):
Converting this program to fixed point requires only the following change:
The answers come out slightly different because the arithmetic was performed in fixed point rather than double precision. Fixed-point arithmetic can be performed in a number of different ways, as is obvious in the parameters to fxp_init. While most applications generally want to use the same options throughout the entire computation, there are other times when a rounding mode or saturation option needs to be changed for just one operation or a small number of operations. The Catalytic Fixed-Point Library contains a number of functions that make that easy to accomplish. The following functions may be called any time after fxp_init to set or uncover current arithmetic options:
The Catalytic Fixed-Point library provides a number of warnings to help in program development and debugging, including detections of things such as overflowing a fixed-point number, converting a negative number into an unsigned, or using a fixed-point number which is an unusual size and may not allow for reasonable code generation. By default, fxp_init starts the fixed-point package will all warnings enabled, but users may turn them on and off at will using the function fxp_warn_mode. Fxp_warn_mode takes a variable number of arguments, which may be taken from the following list:
Arguments may be abbreviated to the shortest unambiguous string. If multiple conflicting arguments are passed to fxp_warn_mode, the conflict is resolved in favor of the argument that appears last in the argument list. Fxp_warn_mode returns a cell array holding the previous setting for the warning flags. That setting can be restored by passing the returned value back into fxp_warn mode as in the following:
The toolbox issues only one warning of a specific type per fxp vector or matrix operation, regardless of the number of elements in the vector or matrix that actually cause the exception. Cfxps may issue two warnings of each specific type: one for the real part and one for the imaginary. The fxp/cfxp sizes which are “good” are set by the routines fxp_good_size and fxp_bad_size. Each routine takes vector of sizes, which is added to the appropriate category. By default the toolbox starts up as though the call fxp_good_size([8, 16, 32]) had been issued. The FxP Toolbox contains a number of facilities in addition to the warnings to help you in debugging your fixed-point problems. These facilities include display routines that provide different formatting outputs for fixed-point numbers as well as the standard Matlab graphical and debugging facilities. The FxP Toolbox contains display options that help in debugging fixed-point programs. By default, the “display” routine for fxps and cfxps use a format string that is identical to Matlab's display format. However, the fxp/cfxp display routine also supports an extended format that gives more information specific to fxps and cfxps, such as signedness, number of bits, and scaling. This extended format is enabled and disabled by the routine fxp_debug_mode. The call fxp_debug_mode(‘on’) enables the extended information; the call fxp_debug_mode(‘off’) returns to normal Matlab display mode. This routine affects only the display of fixed-point numbers. Following is a sample of the information provided:
As is the case with all other mode routines, fxp_debug_mode returns a value which can be used to restore the debug setting that was present prior to the call. The toolbox also contains a function fxp_view that permits viewing of fxp and cfxps in various formats, including hexadecimal. Fxp_view takes up to 3 parameters: a) the value or vector to be displayed; b) the format for displaying the data, which can be ‘f’ for double precision, ‘x’ for hexadecimal, or ‘b’ for binary; and c) an optional scaling factor by which the value is multiplied before display. Arithmetic operators in the FxP Toolbox behave much the same way that they do in basic Matlab. As a result, a fixed-point program looks identical to a double precision computation, other than the initial fxp and cfxp constructors. All operators follow the same rules as Matlab with respect to operations on scalars, vectors, and arrays. So, for instance, it is legal to add a scalar fxp to a vector fxp. Additional features found in the FxP Toolbox not present in basic Matlab include the notion of signed and unsigned, and the explicit separation of real fixed-point objects from complex fixed-point objects. The package does support mixed operations among these various types. The rules governing such conversions are fairly simple. When an operation is specified between an unsigned operand and a signed operand, the package will first convert the signed operand to unsigned; the result is also unsigned following the rules of C. When an operation is specified between an fxp and a cfxp, the fxp is promoted to a cfxp and the result is a cfxp. When an operation is specified between an fxp/cfxp and a double (“double” here means Matlab “double”, which can be either double precision or complex), the double is converted to the same type as the fixed point operand before the operation is performed. When a non-multiplicative operation is specified between an fxp/cfxp and a logical, the logical is converted to the same type as the fixed-point operand before the operation is performed. For multiplicative operations, the fixed-point operand is converted to double precision before performing the arithmetic, and the result is converted back to the fixed-point type.^{2 }No other implicit conversions are performed. The toolbox flags such conversions as errors. ^{2 }The reason for this is that multiplicative logical operations are often used to select elements of another matrix. This definition allows that selection to occur without changing the types of the result elements. For the moment, the package does not support operations between fxps or cfxps with different right or left parameters. This restriction will be lifted in the future. The following table lists all operators supported by the FxP Toolbox, the behavior and size of the result, and any special notes. The notation “fxp(l,r)+fxp(l,r)->fxp(l,r)” means that the addition of two fxps with values of “1” for the number of bits to the left of the decimal and “r” for the number of bits to the right of the decimal results in a fxp with “l” bits to the left of the decimal and “r” bits to right. The behavior of signed and unsigned operands is described by the rule above.
In default mode, the toolbox computes products and quotients exactly^{3 }by doubling the number of bits of output. This level of precision is necessary for many signal processing applications, but it does cause the precision of results to continually increase, leading eventually to an overflow of the fixed-point space if many multiplications are performed and the results not trimmed on the right. The toolbox also supports an alternative mode where the results of multiplications and divisions are the same size as the input operands (that is, fxp(l,r)*fxp(l,r)->fxp(l,r)). This mode tends to be more useful when the extra bits of precision are not necessary for multiplies and divides, as it automatically inserts the conversions that a programmer would have to insert by hand. This mode is enabled by use of the fxp_short_mode routine. Fxp_short_mode takes one parameter. If that parameter is ‘on’ or 1, the short multiply mode is enabled; if that parameter is ‘off’ or 0, the short multiply mode is disabled and multiplies and divides are done in full precision. ^{3}With the exception of the most negative case of signed multiplies and quotients. In addition to the basic arithmetic operators, the FxP Toolbox also supports many of the primitive functions used by Matlab. The compete list of supported functions is as follows:
Because the FxP Toolbox was written using the operator overloading facility in Matlab, it tends to work transparently with most Matlab functions. Matlab functions that are written as “.m” files and that only use the operators and functions listed above (and that call only other functions that meet those restrictions) will execute transparently when invoked with an fxp or cfxp argument. Matlab functions that are implemented as executables or that are built into the Matlab interpreter most likely will not. However, just because a function will execute transparently does not mean that it will execute correctly. Many algorithms are numerically sensitive to the precision of their inputs, and given that most Matlab functions are written with double precision in mind, executing them in fixed-point may produce instabilities. These instabilities generally manifest themselves as error conditions in the Matlab function. The FxP Toolbox has two facilities to help avoid these problems when using Matlab library functions, particularly those in the Signal Processing and Communications Toolboxes. The first is the fxp_short_mode function. Because the library functions were written expecting double precision inputs, their use of multiply operators assumes that the type of the output of the multiply is the same as the type of the input. That assumption is not true with the FxP Toolbox in default mode, when the result of a multiply has twice as many bits as the input. This doubling of bits leads to a blow-up inside loops where multiply-accumulates are done in library functions. Using xp_short mode before library calls to force the output of multiplies to have the same number of bits as the input quickly fixes this problem. The second facility is the fxp_prototype_Mode function. The FxP Toolbox is designed to be used in two different modes: prototyping mode, when you are focusing on exploring the parameters of your functions and code in order to decide the fixed-point characteristics you need, and implementation mode, when you want to produce a real implementation from your program. In prototyping mode, you are not so concerned about having a correct implementation of a Matlab function (a singular value decomposition, for instance) for fixed-point as you are in observing the behavior of your code under different fixed-point scenarios. Accordingly, you usually don't care about how a particular Matlab function obtains its results, so long as it feeds fixed-point operands into your program. In implementation mode, however, when you are focused on getting an implementation of your program, you have to have versions of every routine that work in fixed-point. The FxP Toolbox supports both methods of operation via the fxp_prototype_mode function. When prototype mode is enabled (fxp_prototype_mode(‘on’) or fxp_prototype_mode(1)), the toolbox intercepts calls to Matlab library routines involving fixed-point parameters at the boundaries, converts the fixed-point parameters into double precision, makes the call, then converts the results back into fixed-point. This mode precisely emulates the situation of wanting to get fixed-point results out of a function, but without caring how the results are obtained. When prototype mode is disabled (the default), the toolbox calls Matlab library routines directly with fixed-point parameters, and returns the values that the routines return. While not all routines will work in this situation, if they do work, then you have an implementable version of the library routine. The transcendental functions sin, cos, and exp are extremely important in DSP processing. Creating general fixed-point implementations of these functions, however, is a challenging task. Obtaining accurate answers over the entire range of possible inputs requires argument reduction and fairly long series computations. More often than not, particular DSP implementations only need reasonable accurate results over a restricted range of inputs. As a result, a restricted implementation of the transcendentals over expected inputs is usually much faster and better tailored to the particular DSP problem than a general implementation. This creates a two-stage requirement for transcendental implementation in a fixed-point library. Early prototyping stage requires existing general implementations of transcendentals so that users can evaluate algorithms without having to worry about implementing transcendentals. However, at the later stages of implementation, users will want to evaluate their computations using the same hand-tailored function implementations that will be used in the final implementation on the processor, so that they get bit-accurate simulation results identical to the results produced on the processor. The FxP Toolbox provides support for both stages of implementation, allowing users to easily plug in their own implementations of sin, cos, and exp. By default, a call to a transcendental on an fxp or cfxp will result in a call to the appropriate Matlab double precision routine to obtain a full precision result, followed by a conversion back to a fixed-point number with the same properties as the argument. Thus, by doing nothing a user will obtain highly accurate results for the transcendental functions over all argument ranges. However, if a user provides a version of a transcendental function written in C, the fixed-point package will automatically incorporate it and call it to evaluate transcendentals. This allows users to easily evaluate their own transcendental implementations as well as get totally accurate results from their Matlab simulations. In order for you to substitute your own C version of a transcendental for the fixed-point library all that is necessary for you to do is to copy your routine to a location where the Catalytic Fixed-Point library can recognize it. For fxp routines, that location is <install directory>/@fxp/fxp_<transcendental name>.c; for cfxp routines, that location is <install directory>/@cfxp/cfxp_<transcendental name>.c. As an example, your own version of an fxp sin routine should be copied to the file <install directory>/@fxp/fxp_sin.c. You should also remove the file <install directory>/@fxp/fxp_<transcendental name>.dll; in the case of sin, that file would be fxp_sin.dll. The toolbox will take care of the rest. To reinstate the default, merely remove your version of the transcendental from the @fxp/@cfxp location as well as the associated dll that the fixed-point package will build. Your transcendental routine should take one integer (32 bit) for an argument is it is an fxp; two if it is a cfxp. The first argument is the fixed-point value for which the transcendental is to be evaluated; the second for cfxps is the imaginary part of the cfxp. The FxP Toolbox will pass as following arguments in integers the number of bits to the left of the decimal and the number of bits to the right, but since you probably know these values, you can ignore them in your calling sequence. Your routine should return a 32 bit integer for fxps that gives the resulting value; a 64 bit integer for cfxps that has the real and imaginary packed. The library assumes that these are scaled the same as the input. The fxp_routines that are provided in the directory by default provide examples of how to write your routines. To summarize, all you need do to insert your own version of a transcendental function is to create a routine which accepts the value in the form of an integer and place that routine in the location <install directory>/@(c)fxp/@(c)fxp_<transcendental name>.c. The system currently works only with the Microsoft C compiler. All the cfxp transcendental functions call various combinations of fxp functions to obtain their results, so there should be no need to replace the cfxp functions with your C versions. The FxP Toolbox currently supports the following mathematical/transcendental functions:
All functions return arguments that are identical in size, bits to the left and right of decimal, and signedness to their inputs. The Catalytic Fixed-Point library provides a number of functions solely for the support of fixed-point numbers. These include:
As an example of how simple it is to convert most double precision Matlab programs into fixed-point, consider the following general FIR filter:
This generic form of the filter accepts both coefficients and data, and returns the filtered result. For instance, a typical call might be:
Because the function “fir” is written using generic Matlab operands, it can be invoked directly without change on fixed-point operands. For instance, inserting the conversion:
performs the filter as a fixed point operation, rather than as double precision. Given the choice of input data and coefficients, it's easy to see that the output will be the same, but it's also easily verified as well:
As you can see, the conversion was easy, but the answer in the fixed-point case is 5 times larger than the correct answer—not what we'd expect given the input data and simple coefficients. Turning on the warnings, it's easy to find the answer:
Using the Matlab debugger to stop on warnings, it's easy to find the problem—the length of x inside the fir function is 4, which overflows and saturates at essentially 1 when converted into an fxp(1, 7), causing the answer to be 4 times too big. This hypothesis can easily be verified by increasing the number of bits on the left:
and we see the expected answer. However, we see we have an odd number of bits in the fxp, which is not desirable, so we see if we can reduce it to a total of 8.
As we expected, we cannot. While the coefficients can be exactly represented with 4 bits to the right of the decimal place, the data (0.1) has too much error:
Given that we need the bits on precision on the right, the simplest fix is to slightly modify our original fir function, eliminating the overflow:
By doing the division in double precision, we keep our number within our scaling, and going back to our original fxps, we will get an exact answer:
In general, converting a working double precision program into fixed-point is extremely simple and straightforward using the FxP Toolbox. Because types propagate forward naturally in Matlab, converting a program generally requires the insertion of only a few fxp or cfxp constructors on variables at the beginning of the program. However, there are a few common “gotchas” that often tend to arise. Following are a few of the common pratfalls, as well as guidance on how to detect and avoid them
The Catalytic Fixed-Point Library implements all the operators and functions listed in sections “Supported Operators” and “Supported Functions”; more are being added over time. Any user function or Matlab function that uses only these operators or functions will convert automatically to fixed-point operation by simply passing in a vector containing fixed point. For instance, the following simple fir function:
will work correctly when passed a vector of fixed-point numbers as well as when passed a vector of double precision numbers. The coefficients will automatically be converted to the same precision as the fixed-point numbers by the package. This allows for an easy way of minimizing the number of bits required while maintaining required error tolerances. For instance, given the simple input sequence a=[1 2 3 4], the following loop:
will produce
Despite this effort, not all functions will transparently run on fixed-point numbers. Functions that use Matlab built-ins or that use functions relying on other operators or built-in functions will not run when passed a fixed-point number. For example, the DCT example in the section “Getting Started” will not run with the package as is because the “dct” program calls a built-in function for “fft”, and that fft did not know how to handle fixed-point. The program ran only after we filled in our own fft computation. Catalytic is currently filling out all the built-in functions required to run the Signal Processing Toolbox, the Communications Toolbox, and the DSP Toolbox. The fixed-point library does not currently support mixed mode arithmetic. That is, two operands must have the same number of bits to the left of the decimal and the same number of bits to the right of the decimal, or the package issues an error. This restriction was put in primarily for decreasing the time of getting a prototype up for use, and will be removed shortly, so that any precision numbers may be combined. Even as is, this limitation is primarily annoying only on multiply-accumulates, since the multiply step produces a result twice as big as the accumulator, requiring a conversion to step it back down. Longer term, the Catalytic Fixed-Point Library will support a routine “fxp_precision” which allows you to specify the desired precision on specific operators or functions. Following is a list of all fxp control functions and their purpose:
Patent Citations
Referenced by
Classifications
Rotate |