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