As noted in Section 5.3, the Generic-Arithmetic library provides an extensible protocol for adding specialized arithmetic functionality to your applications. By using the Generic-Arithmetic library alongside a special implementation library, you can make the standard arithmetic operations support number types such as big (64-bit) integers, or complex numbers.
This section provides an example of extending the basic Dylan arithmetic features using the Generic-Arithmetic library and the Big-Integers implementation library.
To use special arithmetic features, an a library's define library declaration must use at least the following libraries:
common-dylan generic-arithmetic special-arithmetic-implementation-library
So for Big-Integers you would write:
define library foo use common-dylan; use generic-arithmetic; use big-integers; ... end library foo;
Next you have to declare a module. There are three ways of using big-integer arithmetic that we can arrange with a suitable module declaration:
To get one of the three different effects described above, you need to arrange the define module declaration accordingly. To replace all integer arithmetic with big-integer arithmetic, include the following in your define module declaration:
use generic-arithmetic-common-dylan;
(Note that the module definition should not use the Big-Integers module. The Big-Integers library is used as a side-effects library only, that is, it is referenced in the library definition so that it will be loaded. Its definitions extend the Generic-Arithmetic library.)
If you replace all integer arithmetic with big-integer arithmetic in this way, there will be performance hits. For instance, loop indices will have to be checked at run-time to see whether a normal or big integer representation is being used, and a choice must be made about the representation for an incremented value.
You can take a different approach that reduces the cost of big-integer arithmetic. Under this approach you leave normal integer arithmetic unchanged, and get access to big-integer arithmetic when you need it. To do this, use the same libraries but instead of using the common-dylan-generic-arithmetic module, include the following in your define module declaration:
use common-dylan; use generic-arithmetic, prefix: "ga/"; // use any prefix you like
This imports the big-integer arithmetic binding names, but gives them a prefix ga/, using the standard renaming mechanism available in module declarations. Thus you gain access to big arithmetic using renamed classes and operations like:
ga/<integer> ga/+ ga/- ga/* ...
The operations take either instances of <integer> or ga/<integer> (a subclass of <integer>) and return instances of ga/<integer>.
Note that having imported the big-integer operations under new names, you have to use prefix rather than infix syntax when calling them. For example:
ga/+ (5, 4);
not:
5 ga/+ 4;
The existing functions like + and - will only accept <integer> instances and ga/<integer> instances small enough to be represented as <integer> instances.
Under this renaming scheme, reduced performance will be confined to the ga/ operations. Other operations, such as loop index increments and decrements, will retain their efficiency.
Finally, you can make big-integer arithmetic the default but keep normal arithmetic around for when you need it. Your define module declaration should contain:
use generic-arithmetic-common-dylan; use dylan-arithmetic, prefix: "dylan/"; //use any prefix you like