diff: extras/complex_number changes
Fergus Henderson
fjh at cs.mu.oz.au
Wed Jul 16 17:52:51 AEST 1997
extras/complex_numbers/*:
Add an Mmakefile to build the complex number library, using the
new support for user-defined libraries.
Move the test cases into a new subdirectory `tests'.
Add a new subdirectory `samples', containing an example
module `fft.m' that uses the library.
Add a README file.
extras/complex_numbers/complex.m:
Add new functions `complex/1' (converts float to complex),
`cis' (cos + i * sin), and `conj'.
Rename `norm' as `abs2' (square of absolute value).
cvs diff: Diffing .
Index: README
===================================================================
RCS file: README
diff -N README
--- /dev/null Wed Jul 16 17:48:20 1997
+++ README Tue Jul 15 20:12:38 1997
@@ -0,0 +1,6 @@
+This directory contains a library for handling complex numbers.
+
+The subdirectory `tests' contains a test case.
+
+The subdirectory `samples' contains an example module using this library.
+
Index: complex.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/extras/complex_numbers/complex.m,v
retrieving revision 1.1
diff -u -r1.1 complex.m
--- complex.m 1997/07/10 09:08:44 1.1
+++ complex.m 1997/07/16 05:42:54
@@ -31,12 +31,18 @@
% both constructing and pattern matching; with intermodule optimization
% enabled, the compiler should generate equally good code for it.
+ % convert float to complex
+:- func complex(float) = complex.
+
% extract real part
:- func real(complex) = float.
% extract imaginary part
:- func imag(complex) = float.
+ % square of absolute value
+:- func abs2(complex) = float.
+
% absolute value (a.k.a. modulus)
:- func abs(complex) = float.
@@ -45,9 +51,8 @@
% for all Z, -pi < arg(Z) and arg(Z) =< pi.
:- func arg(complex) = float.
- % norm (square of absolute value)
- % XXX is `norm' the right terminology?
-:- func norm(complex) = float.
+ % complex conjugate
+:- func conj(complex) = complex.
% addition
:- func complex + complex = complex.
@@ -85,6 +90,9 @@
:- func sqrt(complex) = complex.
:- mode sqrt(in) = out is det.
+ % cis(Theta) = cos(Theta) + i * sin(Theta)
+:- func cis(float) = complex.
+
% polar_to_complex(R, Theta):
% conversion from polar coordinates
:- func polar_to_complex(float, float) = complex.
@@ -100,6 +108,8 @@
:- implementation.
:- import_module float, math.
+complex(Real) = cmplx(Real, 0.0).
+
real(cmplx(Real, _Imag)) = Real.
imag(cmplx(_Real, Imag)) = Imag.
@@ -123,12 +133,14 @@
+ cmplx(R, I) = cmplx(+ R, + I).
- cmplx(R, I) = cmplx(- R, - I).
-norm(cmplx(R, I)) = R*R + I*I.
+abs2(cmplx(R, I)) = R*R + I*I.
-abs(Z) = sqrt(norm(Z)).
+abs(Z) = sqrt(abs2(Z)).
arg(cmplx(R, I)) = atan2(I, R).
+conj(cmplx(R, I)) = cmplx(R, -I).
+
sqr(cmplx(Re0, Im0)) = cmplx(Re, Im) :-
Re = Re0 * Re0 - Im0 * Im0,
Im = 2.0 * Re0 * Im0.
@@ -144,5 +156,7 @@
polar_to_complex(Magnitude, Theta) = cmplx(Real, Imag) :-
Real = Magnitude * cos(Theta),
Imag = Magnitude * sin(Theta).
+
+cis(Theta) = cmplx(cos(Theta), sin(Theta)).
%------------------------------------------------------------------------------%
Index: complex_lib.m
===================================================================
RCS file: complex_lib.m
diff -N complex_lib.m
--- /dev/null Wed Jul 16 17:48:20 1997
+++ complex_lib.m Mon Jul 14 20:55:29 1997
@@ -0,0 +1,5 @@
+:- module complex_lib.
+:- import_module complex, float, imag.
+:- import_module complex_imag, imag_complex.
+:- import_module float_imag, imag_float.
cvs diff: complex_test.exp was removed, no comparison available
cvs diff: complex_test.m was removed, no comparison available
cvs diff: Diffing tests
Index: tests/Mmakefile
===================================================================
RCS file: Mmakefile
diff -N Mmakefile
--- /dev/null Wed Jul 16 17:51:42 1997
+++ Mmakefile Mon Jul 14 20:58:35 1997
@@ -0,0 +1,21 @@
+# COMPLEX_NUMBER_DIR specifies the location of the complex number library,
+# e.g. `/foo/bar/mercury-<version>/extra/complex_numbers'.
+COMPLEX_NUMBER_DIR = ..
+
+# The following stuff tells Mmake to use the complex number library
+VPATH = $(COMPLEX_NUMBER_DIR):$(MMAKE_VPATH)
+MCFLAGS = -I$(COMPLEX_NUMBER_DIR) $(EXTRA_MCFLAGS)
+MLFLAGS = -R$(COMPLEX_NUMBER_DIR) -L$(COMPLEX_NUMBER_DIR) $(EXTRA_MLFLAGS)
+MLLIBS = -lcomplex_lib $(EXTRA_MLLIBS)
+C2INITFLAGS = $(COMPLEX_NUMBER_DIR)/complex_lib.init
+
+MAIN_TARGET = complex_test.res
+
+depend: complex_test.depend
+
+complex_test.out: complex_test
+ ./complex_test > complex_test.out
+
+complex_test.res: complex_test.out complex_test.exp
+ diff -c complex_test.out complex_test.exp > complex_test.res
+
cvs diff: tests/complex_test.exp is a new entry, no comparison available
cvs diff: tests/complex_test.m is a new entry, no comparison available
cvs diff: Diffing samples
Index: samples/Mmakefile
===================================================================
RCS file: Mmakefile
diff -N Mmakefile
--- /dev/null Wed Jul 16 17:51:42 1997
+++ Mmakefile Mon Jul 14 18:52:17 1997
@@ -0,0 +1,12 @@
+# COMPLEX_NUMBER_DIR specifies the location of the complex number library,
+# e.g. `/foo/bar/mercury-<version>/extra/complex_numbers'.
+COMPLEX_NUMBER_DIR = ..
+
+# The following stuff tells Mmake to use the complex number library
+VPATH = $(COMPLEX_NUMBER_DIR):$(MMAKE_VPATH)
+MCFLAGS = -I$(COMPLEX_NUMBER_DIR)
+MLFLAGS = -R$(COMPLEX_NUMBER_DIR) -L$(COMPLEX_NUMBER_DIR)
+MLLIBS = -lmercomplex
+
+MAIN_TARGET = fft
+depend : fft.depend
Index: samples/fft.m
===================================================================
RCS file: fft.m
diff -N fft.m
--- /dev/null Wed Jul 16 17:51:42 1997
+++ fft.m Mon Jul 14 16:16:23 1997
@@ -0,0 +1,127 @@
+%------------------------------------------------------------------------------%
+%
+% file: fft.m
+% main author: conway.
+% data: August 1996
+%
+% This module provides a predicate for performing the Fast Fourier Transfrom
+% (fft) on a list of complex numbers. The list must be a power of 2 in length
+% (ie 4, 8, 16, ... elements).
+%
+% The algorithm used here is derived from a few sources:
+% - "Numerical Recipes in C": Press, et al
+% - "Elements of Computer Music": Moore
+% - Lecture notes from 433-325 "Mathemematical Software B": Dr Rex Harris
+%
+% It actually took the combination of these sources for me to uncover the
+% algorithm for combining the component transforms. This code is not maximally
+% efficient, but rather is intended as a clear presentation of the FFT
+% algorithm.
+%
+%------------------------------------------------------------------------------%
+:- module fft.
+%------------------------------------------------------------------------------%
+:- interface.
+
+:- import_module list, complex.
+
+:- pred fft(list(complex), list(complex)).
+:- mode fft(in, out) is det.
+
+%------------------------------------------------------------------------------%
+:- implementation.
+
+:- import_module float, int, math, require.
+
+fft(Ins, Outs) :-
+ % First put the list into bit-reversed order.
+ bit_rev(Ins, Shuffle),
+ list__length(Shuffle, NInt),
+ int__log2(NInt, R),
+ int__to_float(NInt, N),
+ % Now recombine the component transforms
+ combine(N, 1.0, R, Shuffle, Outs).
+
+:- pred bit_rev(list(T), list(T)).
+:- mode bit_rev(in, out) is det.
+
+bit_rev([], []).
+bit_rev([X], [X]).
+bit_rev([X1,X2|Xs], List) :-
+ split([X1,X2|Xs], List1, List2),
+ bit_rev(List1, List3),
+ bit_rev(List2, List4),
+ list__append(List3, List4, List).
+
+:- pred split(list(T), list(T), list(T)).
+:- mode split(in, out, out) is det.
+
+split([], [], []).
+split([_], _, _) :-
+ error("Input sequence not a power of two in length").
+split([X1, X2|Xs], [X1|Ys], [X2|Zs]) :-
+ split(Xs, Ys, Zs).
+
+:- pred combine(float, float, int, list(complex), list(complex)).
+:- mode combine(in, in, in, in, out) is det.
+
+combine(N, K, R, Ins, Outs) :-
+ (
+ R = 0
+ ->
+ Outs = Ins
+ ;
+ R1 = R - 1,
+ L = 1 << R1,
+ % Split the list in half
+ divide(L, Ins, Fs0, Ss0),
+ K2 = K * 2.0,
+ % Now combine the transforms in the respective halves
+ combine(N, K2, R1, Fs0, Fs),
+ combine(N, K2, R1, Ss0, Ss),
+ % Now perform the 'butterfly'
+ xform(Fs, Ss, complex(1.0), w(K, N), Rs0, Rs1),
+ list__append(Rs0, Rs1, Outs)
+ ).
+
+:- pred xform(list(complex), list(complex), complex, complex,
+ list(complex), list(complex)).
+:- mode xform(in, in, in, in, out, out) is det.
+
+xform([], [_|_], _WJN, _WKN, _, _) :-
+ error("ran out of Di's").
+xform([_|_], [], _WJN, _WKN, _, _) :-
+ error("ran out of Dj's").
+xform([], [], _WJN, _WKN, [], []).
+xform([Di0|Dis0], [Dj0|Djs0], WJN, WKN, [Di|Dis], [Dj|Djs]) :-
+ Tmp = WJN * Dj0,
+ Di = Di0 + Tmp,
+ Dj = Di0 - Tmp,
+ xform(Dis0, Djs0, WJN*WKN, WKN, Dis, Djs).
+
+:- pred divide(int, list(T), list(T), list(T)).
+:- mode divide(in, in, out, out) is det.
+
+divide(R, Ins, Fs, Ss) :-
+ (
+ R =< 0
+ ->
+ Fs = [],
+ Ss = Ins
+ ;
+ (
+ Ins = [],
+ error("divide error!")
+ ;
+ Ins = [F|Ins1],
+ divide(R-1, Ins1, Fs1, Ss),
+ Fs = [F|Fs1]
+ )
+ ).
+
+:- func w(float, float) = complex.
+
+w(J, N) = cis(Theta) :-
+ Theta = J * 2.0 * pi / N.
+
+%------------------------------------------------------------------------------%
--
Fergus Henderson <fjh at cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3 | -- the last words of T. S. Garp.
More information about the developers
mailing list