diff: samples/e.m
Andrew Bromage
bromage at cs.mu.oz.au
Mon Jul 28 16:16:48 AEST 1997
G'day.
Someone want to do a quick review?
Cheers,
Andrew Bromage
Estimated hours taken: 3
Added a new sample program, e.m, and fixed some out-of-date
documentation.
samples/Mmakefile:
samples/e.m:
Sample program 'e' which calculates the base of natural
logarithms to lots of digits (if you're prepared to wait).
samples/README:
Added documentation for e.m, updated documentation for
samples/diff/* to reflect recent changes.
Index: Mmakefile
===================================================================
RCS file: /home/staff/zs/imp/mercury/samples/Mmakefile,v
retrieving revision 1.2
diff -u -r1.2 Mmakefile
--- Mmakefile 1997/07/27 15:09:15 1.2
+++ Mmakefile 1997/07/28 06:07:13
@@ -10,7 +10,7 @@
# To build these programs, first install the Mercury compiler,
# type `mmake depend', and then type `mmake'.
-PROGS= hello cat calculator sort eliza ultra_sub \
+PROGS= hello cat calculator sort eliza ultra_sub e \
all_solutions committed_choice interpreter expand_terms
DEPENDS=$(PROGS:%=%.depend)
Index: README
===================================================================
RCS file: /home/staff/zs/imp/mercury/samples/README,v
retrieving revision 1.3
diff -u -r1.3 README
--- README 1996/07/25 17:14:21 1.3
+++ README 1997/07/28 06:11:07
@@ -27,6 +27,11 @@
expand_terms.m Another example meta-program, showing how to
emulate Prolog's `expand_term' mechanism.
+e.m A small program which calculates the base of
+ natural logarithms to however many digits you
+ choose. It illustrates one way to achieve
+ lazy evaluation in Mercury.
+
Mmake The file used by `mmake', the Mercury Make program,
to build the programs in this directory.
@@ -41,12 +46,17 @@
diff/file.m A module which defines a `file' abstract data type
to hold the lines of text in a file.
-diff/lcss.m A module which defines a `diff' abstract data type;
- it exports a routine for computing the difference
+diff/lcsstype.m A module which defines the `lcss' type; used to
+ represent the longest common subsequence between
+ two files.
+
+diff/lcss.m A module which defines a `diff' data type; it
+ exports a routine for computing the difference
between two `file's, represented as a `diff',
- using the "least common subsequence" algorithm,
- and routines for printing `diff's in a couple
- of different formats.
+ using the "longest common subsequence" algorithm.
+
+diff/diffs.m Routines for printing `diff's in a couple of
+ different formats.
diff/diff.m The top-level driver for the `diff' program;
it contains some "glue" code which handles
New File: e.m
===================================================================
%-----------------------------------------------------------------------------%
% Copyright (C) 1997 The University of Melbourne.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
%-----------------------------------------------------------------------------%
% File: e.m.
% Main author: bromage.
% Calculate the base of natural logarithms using lazy evaluation.
% The algorithm is O(N^2) in the number of digits requested.
%-----------------------------------------------------------------------------%
:- module e.
:- interface.
:- import_module io.
:- pred main(io__state :: di, io__state :: uo) is det.
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
:- implementation.
:- import_module int, list, require, char, string.
% Default number of digits displayed (if this is not specified
% on the command line).
:- func default_digits = int.
default_digits = 1000.
% Change this for a base other than 10. Any integer between
% 2 and 36 makes sense.
:- func base = int.
base = 10.
% Number of columns on the terminal.
:- func columns = int.
columns = 78.
%-----------------------------------------------------------------------------%
% This is a simple implementation of an infinite lazy stream.
:- type int_stream --->
[int | int_stream]
; closure((func) = int_stream).
:- inst int_stream =
bound(
[ground | int_stream]
; closure((func) = is_out is det)
).
:- mode is_in :: in(int_stream).
:- mode is_out :: out(int_stream).
%-----------------------------------------------------------------------------%
% An infinite stream of ones.
:- func ones = (int_stream :: is_out) is det.
ones = [1 | closure((func) = ones)].
% All the digits of e in one stream.
:- func digits_of_e = (int_stream :: is_out) is det.
digits_of_e = next_digit(ones).
:- func next_digit(int_stream :: is_in) = (int_stream :: is_out) is det.
next_digit(Stream0) = [Digit | closure((func) = next_digit(Stream))] :-
scale(2, Digit, Stream0, Stream).
:- pred scale(int, int, int_stream, int_stream).
:- mode scale(in, out, is_in, is_out) is det.
scale(C, Digit, closure(Func), Stream) :-
scale(C, Digit, apply(Func), Stream).
scale(C, Digit, [D | Ds], Stream) :-
K = base * D,
KdC = K // C,
( KdC = (K + base - 1) // C ->
% We have the next digit. Construct a closure to
% generate the rest.
Digit = KdC,
Stream = closure((func) = [K rem C + NextDigit | Stream0] :-
scale(C + 1, NextDigit, Ds, Stream0)
)
;
% We have a carry to factor in, so calculate the next
% digit eagerly then add it on.
scale(C + 1, A1, Ds, B1),
Digit = (K + A1) // C,
Stream = [(K + A1) rem C | B1]
).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
main -->
io__command_line_arguments(Args),
{
Args = [Arg | _],
string__to_int(Arg, Digits0)
->
Digits = Digits0
;
Digits = default_digits
},
{ string__int_to_base_string(2, base, BaseString) },
io__write_strings([BaseString, "."]),
{ string__length(BaseString, BaseStringLength) },
main_2(Digits, columns - BaseStringLength - 1, digits_of_e),
io__nl.
% Print out digits until we don't have any more.
:- pred main_2(int, int, int_stream, io__state, io__state).
:- mode main_2(in, in, is_in, di, uo) is det.
main_2(Digits, Columns, closure(Func)) -->
main_2(Digits, Columns, apply(Func)).
main_2(Digits, Columns, [I | Is]) -->
( { Digits = 0 } ->
[]
; { Columns = 0 } ->
io__nl,
main_2(Digits, columns, [I | Is])
;
{ char__det_int_to_digit(I, Digit) },
io__write_char(Digit),
main_2(Digits - 1, Columns - 1, Is)
).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
More information about the developers
mailing list