The present invention relates to methods and systems for efficiently representing and efficiently computing values of quantitative properties in computer software and for validating the dimensional integrity of formulas and mathematical expressions involving those values.
Presently, most computer programming languages, such as C, C++, Java, Pascal, Ada, BASIC, and FORTRAN, support computation with floating-point numbers, which are limited, finite approximations to real numbers. Further, binary floating point numeric computation is commonly supported by hardware arithmetic circuitry native to the computers for which programs are written in such languages. Instead of native hardware floating point, more primitive computers may implement some form of numerical representation and arithmetic in software. Also, numerical software libraries are commonly available and provide approximations to mathematical functions, such as logarithms and trigonometric functions. These functions in addition to the common arithmetic operators involve numeric arguments and results represented by such software or hardware numbers.
For the purposes herein, and with no loss of generality, the description will assume that the native numbers are represented as a common floating-point numeric format, such as the IEEE-754 Standard single-precision or double-precision binary numbers. Alternative representations of approximations to real numbers can be used as well, such as a decimal floating point format, fixed point binary, fixed point decimal, fractions with integral numerators and denominators, or a custom nonstandard numeric format. The description herein will assume that the standard arithmetic operators (typically denoted by symbols +, −, *, /) and relational operators (typically including at least the symbols <, =, >) are available for the numeric format to use for computation.
In many application programs these numbers are frequently used to represent the values of measurable quantities of various physical, chemical, and engineering properties. These properties, for example, can include distance (or length), area, volume, angle, elapsed time (period or duration), velocity, acceleration, pressure, energy, power, concentration, temperature, viscosity, voltage, and so forth. Typically, quantities of these properties are represented in a computer by variables and constants of the ordinary native numbers provided in the programming language used. The native numbers in turn are generally implemented directly on the computer hardware.
When the value of a quantity of some physical property is typically represented by a number in a programming language's native number system, the unit of measurement is very relevant but is implicit. For example, a number may represent a distance (or length) quantity using a presumed unit of measure such as inches or centimeters. A frequent problem is that sometimes the wrong unit of measure is inadvertently assumed while composing computational formulas or when processing input values, and such an incorrect assumption leads to an incorrect computed result. For example, imperial (UK) gallons may be mistaken for US gallons. A well known instance involving incorrect units of measure was the failure of NASA's 125 million dollar Mars Climate Orbiter in September 1999. In that project, metric units (newton-seconds) were assumed in the satellite software, but English units (pound-seconds) were assumed in the ground station software.
Even when units and numerical values representing measurements are used correctly, a user often needs to explicitly convert a value relative to one unit into the corresponding value relative to another unit. For example, unit conversion may need to be performed when adding two lengths, such as where one length is a value expressed in centimeters and the other length is a value expressed in inches. Then a user must choose a common unit for the addition, apply appropriate conversion constants, and keep track of the unit associated with the resultant sum. Preferably, such conversions should be correctly handled automatically for the user, and appropriate conversion constants automatically supplied by an underlying method or system.
Further, a quantity of one property may be mistakenly used in a situation expecting a quantity of an entirely different property. For example, a velocity quantity may be inadvertently used where an acceleration quantity is expected. Even more subtly, pounds of force may be mistaken for pounds of mass. Similarly, newton•meters of torque may be confused with newton•meters of energy. In software in which all such quantities are naively represented by the ordinary, native numbers of the programming language (and the underlying computer hardware), a compiler will not and cannot detect this kind of error.
Quantitative properties need not be physical. One important example is monetary quantities of a property ‘worth’ or ‘financial value’, which are generally expressed as numbers relative to a unit of currency. Common units of the monetary property include US dollars, Euros, Yen, or other national currencies. Because the relative numerical values of such currencies are variable within the global marketplace, a constant unit of measure has sometimes been employed, such as an ounce of gold, silver, or platinum, but even that may vary with changes of availability. Alternatively, one particular currency, such as the US dollar, may be taken as the constant unit of measurement having a value of 1.00.
Therefore, it is desirable to have a method or system which treats quantities of differing properties in a type-safe way so that their usage can be distinguished and validated by a conventional programming language compiler, translator, interpreter, or a source code preprocessor even before a program is executed. It may also be desirable that the method or system contribute to the “self-documentation” of the software source code by using meaningful naming conventions.
For the purposes herein, a ‘quantity’ will be assumed to comprise a numerical ‘value’ and to be an instance of a specific measurable or quantitative ‘property’ or ‘dimension’. Each particular property may have one or more standard or customary units of measurement. Each unit of measurement is a quantity of the property and generally has a constant value. Conventionally, one such unit is given the value 1 and the other units are defined relative to it. Several traditional, national, international, and standardized systems exist for defining the units of some set of properties (or dimensions). Examples include the metric MKS system, the metric CGS system, and the SI international system of metric units. National standards include US and British systems of units, which now define their units in terms of the SI system.
Note that quantitative properties are often called ‘dimensions’, and the term ‘dimensional analysis’ means validating the correct and compatible usage of quantities of various properties within an arithmetic formula or mathematical expression. This specification will refer to applying dimensional analysis to a mathematical expression composed of arithmetic operator symbols (+ − × /), relational symbols (< = >), and function calls as ‘validating the dimensional integrity’ of the expression. In this specification the terms ‘property’ and ‘dimension’ are synonymous. Nevertheless, ‘property’ may be preferred over the term ‘dimension’, because the term ‘dimension’ is often more narrowly construed to mean the specific spatial property called distance or length. For example, the size of a rigid three-dimensional physical body may be specified by three distances: length, width, and height. In the same vein, non-technical people may not think of the physical properties acceleration, energy, and voltage as ‘dimensions’. Further, within programming languages, the term ‘dimension’ is a yet another concept, which is associated with arrays of values. Nevertheless, in physics, ‘dimension’ is the conventionally used term.
The accompanying drawings, which are incorporated herein and constitute part of this specification, illustrate presently preferred embodiments, and, together with the general description given above and the detailed description given below, serve to explain features of the embodiments.
Various embodiments of the present invention will be described in detail with reference to the accompanying drawings.
Some previous attempts to deal with the problems stated above fall into two main categories. One category proposes to extend a programming language compiler or interpreter to recognize units of measure. The obvious disadvantage of this is the large cost of such a project and the effort of upgrading the large installed base having the existing language. Another category “tags” each quantity with an explicit run-time representation of the unit—generally requiring both extra memory space and execution time overhead. One such popular method is to choose a fixed set of fundamental units of measure, each unit corresponding to a fundamental property (dimension). An example set of fundamental units consists of the following: meter (for distance or length property), gram (mass), second (time), coulomb (charge), candela (luminosity), kelvin (temperature), and radian (angle). That is, each property may be represented by a set of explicit integer exponents, one for each fundamental unit. For example,
acceleration=meter1•gram0•second−2•coulomb0•candela0•kelvin0•radian0.
The obvious disadvantages of this are that there is a fixed set of fundamental properties and a fixed set of corresponding units. Note that a majority of the combinations of the integer exponent values represent meaningless units. Further, it is not possible to represent units of certain important quantitative properties using the above set of fundamental units. Examples of such important properties and units include an amount of ‘information’ as measured in ‘bits’, ‘information density’ measured in ‘bits/cm2,’ ‘worth’ measured in ‘US dollars’ or ‘Euros’, and ‘sound loudness’ measure in ‘decibels’. In order to do so, a new fundamental unit may be required for each such quantitative property, and therefore yet another integer exponent must be added for the property of each new unit. Adding one or more new fundamental units to the exponent-based system may involve augmenting the underlying run-time data structure in a way which may not be backward compatible with the previous scheme. Furthermore, the exponent system requires run-time memory storage overhead for the set of integer tags and requires run-time execution overhead to compute new integral tag values for the result in addition to the time required to compute the resultant numerical value of a mathematical expression (formula). Additional run-time may be required to validate the dimensional integrity of the operators and the operands on which they operate. In any case, such a system of exponents generally does not allow for compile-time validation of the dimensional integrity of mathematical expressions by a conventional compiler. This is because, in the general case, the values of the exponents of a quantity may not be accessible to a compiler and may not be known until run-time. Stating it differently, all quantities are typically represented as objects of a single class, which represents all quantitative properties (dimensions). Therefore, arithmetic and relational (comparison) operators acting on such objects as operands cannot be validated to be correct and meaningful at compile-time with respect to the properties of the specific individual operands of the operators. To use programming language terminology, the operators and objects are not ‘type-safe’ with respect to the many properties represented by the various integer exponent values. In effect, the ‘type’ of the result of a mathematical expression must be computed and checked at run time.
In contrast to the explicit exponents associated with a fixed set of properties, a different method, presented herein, can exploit the built-in strong (type-safe) compile-time data type validation provided by an object-oriented programming language without modifying a programming language's conventional compiler or interpreter. An embodiment of the method may include source code which defines a class (also known as an abstract data type) to uniquely represent each distinct quantitative property to be referenced by a program. Each object of the class represents a quantity of the quantitative property (dimension) represented by the class. Therefore, a quantitative property and the unique software class (abstract data type) which represents the property may be considered essentially synonymous for the purposes of this specification. Similarly, a quantity of the property and a computer memory object of the class representing the property may be considered synonymous.
By conventional compiler, this specification means a compiler which compiles a standardized programming language, such as C++, Java, C#, or another modern object-oriented language. The compiler runs on a computer which includes an instruction processor and a memory having stored therein source code statements of the programming language, which are accessible to the instruction processor. For example, the memory may be semiconductor memory, magnetic memory, optical memory, or a combination thereof. The memory for the computer also includes a compiler for the programming language. The compiler includes instructions for the instruction processor which cause the instruction processor of the computer to access and compile the source code statements stored in the memory of the computer. Further, this specification assumes the programming language has no built-in features specifically intended for representing units and/or the quantitative properties represented by those units. This specification will include under the generic term ‘compile’ the normal translation and linking of source code into machine code, the translation to interpreted intermediate code (such as with Java), and direct interpretation of the source code.
Because each quantitative property uniquely corresponds to a specific property class representing the property, the concepts of a property and the software class representing the property may be used interchangeably without introducing confusion. Doing so sometimes keeps the description simpler. The terms property class and dimension class then means a class representing the property (dimension). Similarly, the concept of a property quantity and a software object of the class representing the quantity's property may be used interchangeably. For example, one may speak of a quantity belonging to a property class, whereas technically the quantity is really associated with a property, and the object corresponding to the quantity is actually what belongs to the property class, which represents the quantity's property. Thus a quantity and the object representing it may also be treated as synonymous in general. The term quantity object then means an object representing the quantity, and the object belongs to the class representing the property of the quantity.
Because each quantitative property corresponds to a unique class, a standard compiler (such as the Microsoft Visual C/C++ compiler) can validate at compile-time the type compatibility of the usage of objects of each class. Using this, an unmodified standard compiler can validate the “dimensional integrity” of computations (such as mathematical expressions) involving quantities’ objects of various property classes. That is, if the property classes are defined appropriately, a conventional compiler can validate at compile time whether source code statements and mathematical expressions conform to defined allowable calculations. The validation simply exploits the compiler's normal, built-in, strong type checking, which is performed during the parsing and translation of the source code which contains the statements and expressions. Otherwise, all of the details of the dimensional integrity are specified in source code definitions which the compiler compiles as input along with application source code which uses those definitions.
For example, a program may be written in which a mathematical expression references a distance object D and a velocity object V, and in which the expression directs that those two quantities be added together, as in “D+V” for example. Then, when a conventional compiler (such as the Microsoft Visual C++ compiler) inputs and compiles the program, the compiler can detect the invalid, meaningless addition already at compile time. The compiler then can generate some indication of the invalid addition as a programming error. There is no need to perform the calculation or execute the compiled code to detect the error. Similarly, if the program includes a subtraction of an object of the class ‘area’ from an object of the class ‘mass’, the compiler can detect and generate an indication that the meaningless, invalid operation is an error. Normally only quantity objects from the same property class can be added together or subtracted from each other. Further, a quantity object (such as the result of a mathematical expression) may be assigned only to a variable declared to be of the property class of the assigned quantity. Similar strong object-oriented-typing constrains may hold for copy constructors, relational (comparison) operators, pointer dereferencing, array indexing, and memory allocation—operations typically available in an object-oriented programming language.
Which operations are valid are determined by the operators and functions which are defined to the compiler. Any operator or function in a mathematical expression in the source code which does not match an operator definition or a function definition is deemed invalid. Note that “match” means that the operator symbol or function name in an expression matches the symbol or name in the definition. Further, the classes of the actual operands (arguments) of the operator or arguments of the function must also match the classes of the formal parameters specified in the definition. In other words, this specification will take advantage of a feature now common in many object-oriented languages: namely operator symbol and function name overloading. For example, the addition symbol (+) may be used in various contexts, where its specific definition depends on the classes of its actual operands. As more particular examples, there may be a definition for using the addition symbol to add two distance operands to yield a distance object as the sum, but no definition would be given for using the addition symbol to add a distance to a temperature. In general, the addition symbol would have a definition for each quantitative property class for adding two quantity objects of the class together. Similarly, the subtraction symbol (−) would have a definition for each property class for computing the difference between two objects of the class. However, generally no definition would exist for an addition symbol to add objects of unlike property classes together or for a subtraction symbol to subtract objects of unlike property classes. There may also be multiplier operators (commonly symbolized as *) which multiply a unitless numeric scalar times a quantity object, such as “1.5*Volt” where Volt is a constant object representing a unit of voltage or electrical potential. Similarly, division operators may be defined for all property classes, in which a quantity is divided by a scalar, such as “I/2.0” where I is a variable of the class ‘current’. Of course, I could also be a more complex arithmetic expression which evaluates to an object representing a quantity of current.
The compiler would validate and allow a mathematical expression in which, for example, a distance quantity is divided by a time period quantity resulting in a velocity quantity. This assumes the compiler previously and explicitly compiled a definition of such a useful division operator (presumably symbolized by /). Similarly, the compiler would validate and allow the multiplication of a volume quantity with a density quantity to yield a mass quantity. This assumes the compiler previously input and compiled the definition of such a useful multiplication operator (likely symbolized by *) which takes volume and density objects as operands. Depending on the semantics of the language, one may need to define both ‘volume*density’ and ‘density*volume’ as separate operators.
The definitions of common arithmetic operators (such as operator symbols +, −, * or /) acting on operands belonging to specifically defined combinations of classes, may be conveniently located in a standard, predefined header or “include” file initially input to the compiler. Note that only an applied instance of an operator symbol in an expression and its actual operands which match (corresponds to) a previously and explicitly compiled definition of the same symbol and formal operand classes will be allowed as valid by the compiler. In a program containing any instance of an operator symbol and its actual operand classes for which there is no corresponding definition of the symbol and formal operand classes, a standard compiler will generate and output an error notification in some form at compile-time.
As well as arithmetic operator symbols, there may be various other mathematical functions defined, each function having specified property classes for the allowed argument(s) of the function. For example, there may be a square root function “sqrt” defined for any non-negative quantity of the ‘area’ class as the (formal) argument of the square root, where the result is a distance (length) object. However, there presumably would not be a square root function “sqrt” defined for an argument object representing a quantity of the property classes length, time period, voltage, or energy. There is no conventional interpretation for such a function. More generally, a compiler can use strong typing constraints to validate a more complex mathematical expression (formula) within the source code programs which it compiles. That is, the more complex expression may involve multiple or nested operators and functions in the expression, in which the operands and arguments may be simple constants or simple references to named quantity objects, or the operands and arguments may themselves be more complex mathematical expressions involving operators and functions.
For the purposes herein, a quantity of a quantitative, measurable property will be assumed to have a numerical ‘value’ with respect to some assumed ‘measurement unit’. The quantity may be represented by an object (or instance) of a specific object-oriented class (also known as an abstract data type) corresponding to the property. Each particular property may have one or more units of measurement. Each unit of measurement is a named object of the property's class. Generally each unit is a constant, and generally one such unit of each property is given the value 1. Each unit may be ‘constructed’ by constructor functions defined as part of the property's class. (Constructing an object in an object-oriented language generally means allocating memory for the object.) On processing the definition of the class and unit object, the compiler can generate executable code to construct and initialize the value of the object when the code is executed. This is the same as for any other class constant or variable object, which a program may declare and direct to be constructed. Although a program may define any number of additional measurement units in a program, an embodiment of the method and system generally would provide at least one pre-defined unit for each class representing the property of the unit.
Instead of so many metric units for each property, the combination of the metric prefix “micro” and the unit “meter” can be written as the product Micro*Meter in a programming language, such as C++. Thus the method needs to define only 18 prefixes and only one name for each base unit of measurement. Nevertheless, source code utilizing the method can always define for convenience any of the following more common prefixed units, for example:
const distance Centimeter=Centi*Meter;
const energy Kilojoule=Kilo*Joule;
const period Microsecond=Micro*Second;
A few of such more common prefixed units may be predefined by a header file of an embodiment.
Note that in the examples immediately above, the metric prefix is simply the symbolic name of a scalar multiplier (such as the floating point number 0.01 for Centi). The subsequent figures will show that if Meter is defined to be an object of class ‘distance’, then multiplication by a scalar (such as Centi) is a source code expression which yields a run-time result which is also a ‘distance’ object. Similarly, in the definition of Kilojoule, Kilo*Joule is an ‘energy’ object, assuming Joule has been defined to be an energy object (presumably a measurement unit object in this case). Therefore, the value of a multiple of an energy object may be assigned to another energy object (a constant in this case). Similar comments apply to the time ‘period’ object Micro*Second.
Note that the embodiments of the Figures follow capitalization rules which parallel English. A class name is not capitalized—just like the common noun ‘woman’ is not capitalized. The name of a specific object instance, such as a constant, a unit name, or a variable is capitalized‘just as the woman's name ‘Judith’ is capitalized as a proper noun.
Most of the source code of the embodiment of
For example, for the property class called ‘distance’, there are many common constant units of measure, but Metre (SI spelling) will be the distinguished, internal standard unit relative to which all the others are internally defined. That choice is not a necessity, but was chosen to make the use of the SI system convenient. For example, the internal unit for the property ‘mass’ can be the gram, the kilogram, or even the pound (although the later may lead to unnecessary complication). The user of the methods herein need not be concerned about which measurement unit was chosen for internal use and generally does not even need to know. The following are example definitions which can appear in the implementation source code of the class distance:
When source code containing the above definitions is submitted to a compiler (such as the Microsoft Visual C/C++ compiler), run-time code may be generated to construct each constant unit object—that is, at run-time to allocate memory for each object and to initialize its value as indicated by the parenthesized mathematical expression which evaluates (in this case) to an object representing a distance quantity.
Units other than the internal base unit may be predefined in a system-provided header file or library or may be added by a user. Normally one designated internal base unit will have the value 1.0, but it is otherwise not obvious to a user what is the protected (or private) internal value of any quantity unit or variable. This allows changes to the internal implementation of a property class to be made without affecting any programs which use the class. For example, the user does not need to know whether the unit for the internal values of objects of the property class ‘mass’ is the unit Gram or the SI standard unit Kilo*Gram or some other unit such as the pound.
Classes for many other properties besides velocity, such as those of
When a program, which utilizes the method described herein, needs to compute or write the actual numerical value of a property, the ‘as( )’ function may be used. A typical usage would be to output a numerical value in terms of a specified unit of measure. The following examples illustrate how a velocity quantity may be converted to or from a numerical value which is relative to a specific unit of measure:
Unit conversion can take this form for all other property classes as well. So for classes representing mass and energy, for example, a program may contain statements such as these:
Of course the above source code snippet assumes that the header file “mass.h” includes the definition of a class which represents the property mass and was constructed in a way similar to how velocity was defined in
energy operator*(power P, period T);
For convenience the commutative form may also be provided:
energy operator*(period T, power P);
These statements are the way C++ declares multiplication of a power quantity times a time period quantity. An example of the use of this operator* in C++ is
5*Second*100*Watt
where 5*Second is a quantity of a time period and 100*Watt is a quantity of power. The inline bodies for these two overloaded operator declarations can be defined in a manner similar to the bodies of operator* in the last few lines of
electrical resistance times current (returning a quantity of voltage),
voltage times current (returning a quantity of power),
mass times velocity (returning a quantity of momentum), and
power times period (returning a quantity of energy).
The various operators are defined by one or more statements which define how to calculate the result returned. Examples are shown in
Many of the operators and functions declared in the embodiment of
Note that the internal representation of an object of the class velocity (or any other class representing a scalar-valued property) is simply a number native to the compiler and computer for which the compiler translates source code. Thus, a velocity object requires no additional memory overhead a single native (floating point) number. Similarly, where an optimizing compiler does support an in-line code feature, the generated code requires no run-time overhead beyond the execution time required for computing with the numbers in the internal representation of the values of the objects (such as a single floating point instruction: add, subtract, multiply or divide).
Note that some compilers such as the Microsoft Visual C/C++ compiler provide a feature which “precompiles” the source code form of header (include) files into an intermediate form in order to later expedite compiling of application programs including the header file. Such a feature is still equivalent in principle to including the original source code header files.
Note that in
Note that the method described herein does not explicitly distinguish which particular properties are “fundamental”, as does the SI system, in which the distinctions are somewhat arbitrary. For example, velocity could have been chosen as a fundamental property instead of distance, because one may argue that the velocity of light, c, is more fundamental in physics than distance. Then distance would be defined as speed times period (time). The same could be done in an alternative embodiment of the method described herein, because the method herein does not inherently depend on a certain fixed set of specific fundamental properties. The methods described herein may define an additional class representing any property as-yet unimplemented, for example, in a pre-packaged commercially available library of property classes.
The valid example source code statements of
QRTYPE the name of the class being defined,
QFUN is the name of the access function to the internal value,
Q1TYPE and Q2TYPE are the classes of the first and second parameters, and
Q1FUN and Q2FUN are the access functions for the first and second parameters.
Invoking the macro QR_PRODUCT, as shown in
QR_PRODUCT( velocity, acceleration, time) in which QRTYPE is velocity, Q1TYPE is acceleration, and Q2TYPE is time.
Similarly, invoking the macro QR_QUOTIENT will generate the C++ declaration for the division operator represented by the arithmetic operator ‘/’. The macros QR_RECIPROCAL, QR_SQUARE, QR_SQRT, and QR_CUBE are special cases which generate declarations of operators or functions which respectively compute the reciprocal, square, square root, and cube from an argument quantity of a different class.
The embodiment shown in
The embodiment shown in
Note that the template mechanism of C++ language was not used to define property classes in the embodiments of the Figures. This is because the C++ template mechanism can only parameterize a generic class which already has a name, but the mechanism is not appropriate for directly defining a set of new classes each with a new simple name of its own. Furthermore, not all programming languages provide a template mechanism like that of C++. However, any separate text macro processor or editor may be used to manually and permanently expand the macro calls and their parameters into normal source code for a programming language without built-in macro capabilities. In any case, the C++ preprocessor macro facility seemed to provide a more capable way than templates to provide parameterized patterns for easily defining a set of property classes.
The template mechanism can certainly be used to parameterize the precision of the values of objects of property classes, for example—particularly in a case where each property class is to have its own explicit individualized precision. Thus, in an alternative embodiment employing the template mechanism, a programmer can declare two different velocity variables of different precisions, as in the following:
velocity<float> V1;
velocity<double>V2;
The embodiments of the Figures avoided this parameterized template approach to keep the description and source code simpler to understand. The classes can alternatively be defined using parameterized templates in an alternative embodiment. The alternative embodiment can be derived from the Figures, for example, by a straightforward replacement of the ‘scalar’ data type with a template parameter ‘<scalar>’ and adding other appropriate required keywords and syntax as needed to define a template.
A number of details in the embodiments of
The in-line operators and functions can alternatively be implemented as ordinary function bodies, but in that case most compilers may generate slower code.
Further, the table and functions for looking up the external character-string names of the pre-defined units are an optional, convenient feature, are not essential to the methods herein and a system using the methods. The table and functions may be omitted.
There may be other constants defined besides the usual units of measure for a class. For example, a class abstracting the quantitative property ‘density’ can include pre-defined constants for the density of many different materials, such as water, other liquids, various metals, gemstones, and other solid elements and compounds. These may be defined for a specific combination of a standard temperature and a standard pressure or for a variety of temperatures and pressures. Furthermore, client software may include functions which compute an approximation to the density as a function of temperature and pressure quantity arguments.
One quantitative property of particular interest is angle. Because of the importance of trigonometric functions, it would be meaningful to define a full set of trigonometric functions which take angle objects as arguments—instead of or in addition to the usual trigonometric functions which take native floating point numbers as arguments. The functions can include sine, cosign, tangent, cotangent, secant, and cosecant. The results of the functions may still be native floating point numbers, because the results of those trigonometric functions are “unitless” ratios. Also the corresponding inverse trigonometric functions may be defined, which functions can return objects of the class angle instead of native floating point numbers.
Another particular quantitative property of interest is ‘radius’, which may be considered distinct from ‘distance’. Consider the ambiguous SI measurement called a newton•meter. It may be a newton of force applied at a meter radius perpendicular to the radius to yield a quantity of torque. Alternatively, a newton•meter may be a newton of force applied parallel to a distance of one meter to yield a quantity of energy (or work). Within the methods and system presented herein, the two properties may be distinguished respectively as a Newton*MeterRadius of class torque and Newton*Meter of class energy, for example. In this example, Newton is a unit of force, MeterRadius is a unit of radius from a pivot or fulcrum, and Meter is a unit of linear distance. When energy, torque, force, radius, and distance are distinct classes, and when only meaningful operators and functions are defined and allowed, then a compiler can validate whether mathematical expressions involving them are valid. In this way the compiler automatically validates “dimensional integrity” using the strong-typing method presented herein.
Because the macros of
If the STL is unavailable for a specific compiler or if its equivalent is not available in a computer language, equivalent code may be derived from the STL template for the complex class by manual textual substitution to yield source code for complex arithmetic operators and other functions.
QC_PRODUCTS(voltageAC, currentAC, impedanceAC);
which declares a commutative multiplication operator representing Ohm's Law for alternating current. As before, only operator-operand combinations which have matching definitions (such as in an include file) will be validated as acceptable expressions when a compiler compiles the source code containing them.
Definition of classes for representing quantities of AC current (class currentAC), impedance (class impedanceAC), and admittance (class admittanceAC) can be very similar using macros such as those of the embodiments of
Examples of other logarithmic scale quantitative properties include the seismic Richter scale, power amplification, radar reflectivity, and the musical scale of pitches. Classes to represent these properties can be built using the ‘˜qL˜core.h’ and ‘˜qL˜core.inl’ macros and the quantityL base class, similar to how ‘sound_pressure’ and ‘sound_log’ were defined. Predefined units for the musical scale would include the Octave and the HalfStep, for example, as well as a full octave of 11 notes such as the octave including “middle C” (constant objects PitchAFlat, PitchA, . . . PitchG). The underlying linear scale for musical pitch is frequency, and the linear reference can be the frequency (220 hertz) of the note ‘A’ below ‘middle C’. The linear reference is the value for which the corresponding logarithmic scale is zero. A C++ source code statement such as the following would make sense and be validated as valid source code by a compiler:
The embodiments herein have been illustrated exclusively in the C++ programming language. Nevertheless, the methods herein may be captured in parallel embodiments expressed in other programming languages albeit with changes in syntax at the least. The object code compiled from such source code, for example as an object code library, and run on a computer may form a programming system which implements the methods and which may originate as source code of a specific programming language. That is, some form of object code, such as a static or dynamically linked library, or interpreted pseudo-code, originating from source code employing the methods herein may be executed on a computer. Such object code executing on a computer constitutes a system for computing quantities using other quantities, in which the correct usage of the properties (dimensions) implicit in those quantities has been validated before execution.
A programming language with facilities for user-defined object-oriented classes or abstract data types can implement the methods and system described herein. Further, a language which allows overloading of the multiplication and division operators (* and /) is particularly well suited for implementing the method. However, a language such as standard C or Pascal, which allows user-defined data types, may be used to partially capture at least some of the ideas herein in an embodiment.
While the present invention has been disclosed with reference to specific example embodiments, numerous modifications, alterations, and changes to the described embodiments are possible without departing from the sphere and scope of the present invention, as defined in the appended claims. Accordingly, it is intended that the present invention not be limited to the described embodiments, but that it have the full scope defined by the language of the following claims, and equivalents thereof.