#!/bin/sh
# This is a shar archive.
# The rest of this file is a shell script which will extract:
#
# 5_7A.cmp 5_7A.h 5_7B.cmp 5_7B.h 5_7B2.cmp 5_7a1.c 5_7a2.c 5_7a3.c 5_7atst.c 5_7b1.c 5_7b2.c 5_7b3.c 5_7b4.c 5_7btst.c histogram.h makefile
#
# To extract the files from this shell archive file simply
# create a directory for this file, move the archive file
# to it and enter the command
#
#	sh filename
# 
# The files will be extracted automatically.
# Note: Do not use csh.
#
# Archive created: Mon Jul 30 23:04:11 EDT 1990
#
echo x - 5_7A.cmp
sed 's/^X//' > 5_7A.cmp << '!EOF!'
[0:200) : 3
[200:400) : 2
[400:600) : 6
[600:800) : 12
[800:1000) : 1
[1000:1200) : 4
[1200:1400) : 8
[1400:1600) : 4
[1600:1800) : 7
[2000:2200) : 6
[2200:2400) : 1
[2400:2600) : 2
[2600:2800) : 8
[2800:3000) : 11
[3000:3200) : 4
[3200:3400) : 3
!EOF!
ls -l 5_7A.cmp
echo x - 5_7A.h
sed 's/^X//' > 5_7A.h << '!EOF!'
/* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */
/* The C++ Answer Book */
/* Tony Hansen */
/* All rights reserved. */
// Exercise 5.7, version 2
// A histogram class
// <histogram.h>
//
//	"nbin" bins covering
//	the range [l:r[ uniformly
//	nbin*binsize == r-l
//
#ifndef HISTOGRAM_H
# define HISTOGRAM_H

struct histogram
{
    int l,
	r,
	binsize,
	nbin;
    int* h;
    long sum,
	 sqsum;

    histogram(int nbin=16, int l=0, int r=16);
    ~histogram();

    void add(int value);
    void print();
};
#endif /* HISTOGRAM_H */
!EOF!
ls -l 5_7A.h
echo x - 5_7B.cmp
sed 's/^X//' > 5_7B.cmp << '!EOF!'
< 0 : 0
[0:50) : 2
[50:200) : 1
[200:500) : 7
[500:1000) : 14
[1000:1500) : 16
[1500:2000) : 7
[2000:2500) : 7
[2500:3000) : 21
[3000:3500) : 7
> 4000 : 0
!EOF!
ls -l 5_7B.cmp
echo x - 5_7B.h
sed 's/^X//' > 5_7B.h << '!EOF!'
/* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */
/* The C++ Answer Book */
/* Tony Hansen */
/* All rights reserved. */
// Exercise 5.7, version 2
// A histogram class
// <histogram.h>
//	"nbin" bins covering the range
//	[ lovals[0] : lovals[nbin] )
#ifndef HISTOGRAM_H
# define HISTOGRAM_H

struct histogram
{
    int *lovals;
    int *h;
    int nbin,
	underflow,
	overflow;
    long sum,
	 sqsum;

    histogram(int nbin, int lovals[]);
    ~histogram();

    void add(int value);
    void print();
};
#endif /* HISTOGRAM_H */
!EOF!
ls -l 5_7B.h
echo x - 5_7B2.cmp
sed 's/^X//' > 5_7B2.cmp << '!EOF!'
      <    0 :	
[    0:   50) :	**
[   50:  200) :	*
[  200:  500) :	*******
[  500: 1000) :	**************
[ 1000: 1500) :	****************
[ 1500: 2000) :	*******
[ 2000: 2500) :	*******
[ 2500: 3000) :	*********************
[ 3000: 3500) :	*******
[ 3500: 4000) :	
> 4000 : 
!EOF!
ls -l 5_7B2.cmp
echo x - 5_7a1.c
sed 's/^X//' > 5_7a1.c << '!EOF!'
/* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */
/* The C++ Answer Book */
/* Tony Hansen */
/* All rights reserved. */
// implement a histogram
// with a fixed number of
// uniform, adjustable size, bins
#include <histogram.h>
#include <string.h>
#include <error.h>

histogram::histogram(int nbins, int left, int right)
{
    if (right <= left || nbins < 1)
	error ("bad args");

    // set up the vector
    h = new int[nbins];
    memset(h, 0, nbins * sizeof(int));

    // adjust the right end
    int range = right - left;
    binsize = range / nbins;
    if (range % nbins != 0)
	{
	binsize++;
	range = binsize * nbins;
	right = left + range;
	}

    // set class variables
    l = left;
    r = right;
    nbin = nbins;
    sum = sqsum = 0;
}

histogram::~histogram()
{
    delete h;
}
!EOF!
ls -l 5_7a1.c
echo x - 5_7a2.c
sed 's/^X//' > 5_7a2.c << '!EOF!'
/* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */
/* The C++ Answer Book */
/* Tony Hansen */
/* All rights reserved. */
// Add one to the bin which contains a.
// Adjust the histogram, if necessary.
#include <histogram.h>
#include <string.h>

void histogram::add(int a)
{
    register int i, j;

    // make l <= a < r, possibly expanding histogram by
    // doubling the binsize and range.
    // First the left end.
    while (a < l)
	{
	// combine the bins
	for (i = nbin - 1, j = nbin - 2;
	     0 <= j;
	     i--, j -= 2)
	    h[i] = h[j] + h[j + 1];

	// check for odd number of bins
	if (j == -1)
	    h[i--] = h[0];

	// zero out the rest
	if (i >= 0)
	    memset(h, 0, (i + 1) * sizeof(int));
	binsize += binsize;
	l -= r - l;
	}

    // Then the right end
    while (r <= a)
	{
	// combine the bins
	int halfbin = nbin / 2;
	for (i = 0, j = 0; i < halfbin; i++, j += 2)
	    h[i] = h[j] + h[j + 1];

	// check for odd number of bins
	if (j < nbin)
	    h[i++] = h[j];

	// zero out the rest
	if (i < nbin)
	    memset(&h[i], 0, (nbin - i) * sizeof(int));
	binsize += binsize;
	r += r - l;
	}

    sum += a;
    sqsum += a * a;
    h[(a - l) / binsize]++;
}
!EOF!
ls -l 5_7a2.c
echo x - 5_7a3.c
sed 's/^X//' > 5_7a3.c << '!EOF!'
/* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */
/* The C++ Answer Book */
/* Tony Hansen */
/* All rights reserved. */
//	printout non-empty ranges
#include <histogram.h>
#include <stream.h>

void histogram::print()
{
    register int d = binsize;

    for (register i = 0; i < nbin; i++)
	{
	register int x = h[i];
	// only print out values when non-zero
	if (x != 0)
	    {
	    int ll = l + d * i;
	    cout << "[" << ll << ":" << (ll + d)
		<< ") : " << x << "\n";
	    }
	}
}
!EOF!
ls -l 5_7a3.c
echo x - 5_7atst.c
sed 's/^X//' > 5_7atst.c << '!EOF!'
/* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */
/* The C++ Answer Book */
/* Tony Hansen */
/* All rights reserved. */
/* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */
/* The C++ Answer Book */
/* Tony Hansen */
/* All rights reserved. */
#include <histogram.h>

long x[] = {
    2867, 457, 1613, 2837, 748, 2120, 2691, 754,
    1318, 37, 1417, 1256, 2644, 1253, 3255, 1444,
    2620, 2889, 884, 1179, 544, 425, 1153, 617,
    2867, 457, 1613, 2837, 748, 2120, 2691, 754,
    1318, 37, 1417, 1256, 2644, 1253, 3255, 1444,
    273, 1168, 1750, 2042, 2577, 3075, 2691, 1602,
    2867, 457, 1613, 2837, 748, 2120, 2691, 754,
    2135, 2328, 1709, 709, 3015, 2919, 2964, 3027,
    2867, 457, 1613, 2837, 748, 2120, 2691, 754,
    2555, 3156, 1265, 625, 72, 1201, 690, 389,
    3254, 1068,
    -1 };
    

main()
{
#ifdef TSTA
    histogram h(20, 0, 4000);
#else
    static int lowvals[] = {
	0, 50, 200, 500, 1000, 1500, 2000, 2500, 3000, 3500, 4000
    };
    histogram h(10, lowvals);
#endif
    for (long *xp = x; *xp != -1; xp++)
	h.add(*xp);
    h.print();
    return 0;
}
!EOF!
ls -l 5_7atst.c
echo x - 5_7b1.c
sed 's/^X//' > 5_7b1.c << '!EOF!'
/* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */
/* The C++ Answer Book */
/* Tony Hansen */
/* All rights reserved. */
// implement a histogram
// with a fixed number of
// variable size bins
#include <histogram.h>
#include <string.h>
#include <error.h>

static int okayvals(register int nbins, int Alovals[])
{
    for (register int i = 0, j = 1; i < nbins; )
	if (Alovals[i++] >= Alovals[j++])
	    return 0;
    return 1;
}

histogram:: histogram(int nbins, int Alovals[])
{
    if (!Alovals || nbins < 1 ||
	!okayvals(nbins, Alovals))
	error("bad args");

    // set up the vectors
    lovals = new int[nbins + 1];
    h = new int[nbins];

    // set class variables
    memcpy(lovals, Alovals, (nbins + 1) * sizeof(int));
    memset(h, 0, nbins * sizeof(int));
    nbin = nbins;
    underflow = overflow = 0;
}

histogram:: ~histogram()
{
    delete lovals;
    delete h;
}
!EOF!
ls -l 5_7b1.c
echo x - 5_7b2.c
sed 's/^X//' > 5_7b2.c << '!EOF!'
/* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */
/* The C++ Answer Book */
/* Tony Hansen */
/* All rights reserved. */
// Add one to the bin which contains a.
// If none contains a, increment the
// underflow or overflow count.
#include <histogram.h>

void histogram:: add(int value)
{
    if (value < lovals[0])
	underflow++;

    else
	{
	for (int i = 1; i <= nbin; i++)
	    if (value < lovals[i])
		{
		h[i-1]++;
		break;
		}

	if (i > nbin)
	    overflow++;
	}

    sum += value;
    sqsum += value * value;
}
!EOF!
ls -l 5_7b2.c
echo x - 5_7b3.c
sed 's/^X//' > 5_7b3.c << '!EOF!'
/* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */
/* The C++ Answer Book */
/* Tony Hansen */
/* All rights reserved. */
//	printout non-empty ranges
#include <histogram.h>
#include <stream.h>

void histogram:: print()
{
    cout << "< " << lovals[0] << " : " <<
	underflow << "\n";
    for (register int i = 0, j = 1;
	 i < nbin;
	 i++, j++)
	{
	register int x = h[i];
	if (x != 0)
	    cout << "[" << lovals[i] << ":" <<
		lovals[j] << ") : " << x << "\n";
	}
    cout << "> " << lovals[nbin] << " : " <<
	overflow << "\n";
}
!EOF!
ls -l 5_7b3.c
echo x - 5_7b4.c
sed 's/^X//' > 5_7b4.c << '!EOF!'
/* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */
/* The C++ Answer Book */
/* Tony Hansen */
/* All rights reserved. */
//	print a bar chart representation
//	or the histogram ranges
#include <histogram.h>
#include <stream.h>

// Only print out 65 asterisks on each line.
// If there are more than that, print an indicator.
const int maxperline = 65;
static void printasterisks(register int count)
{
    int beyond = 0;
    if (count > maxperline)
	{
	count = maxperline;
	beyond++;
	}

    while (count-- > 0)
	cout.put('*');
    if (beyond)
	cout << ">>";
    cout << "\n";
}

void histogram:: print()
{
    cout << "      <" << dec(lovals[0],5) << " :\t";
    printasterisks(underflow);

    for (register int i = 0, j = 1;
	 i < nbin;
	 i++, j++)
	{
	cout << "[" << dec(lovals[i],5) << ":" <<
	    dec(lovals[j],5) << ") :\t";
	printasterisks(h[i]);
	}

    cout << "> " << lovals[nbin] << " : ";
    printasterisks(overflow);
}
!EOF!
ls -l 5_7b4.c
echo x - 5_7btst.c
sed 's/^X//' > 5_7btst.c << '!EOF!'
/* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */
/* The C++ Answer Book */
/* Tony Hansen */
/* All rights reserved. */
/* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */
/* The C++ Answer Book */
/* Tony Hansen */
/* All rights reserved. */
#include <histogram.h>

long x[] = {
    2867, 457, 1613, 2837, 748, 2120, 2691, 754,
    1318, 37, 1417, 1256, 2644, 1253, 3255, 1444,
    2620, 2889, 884, 1179, 544, 425, 1153, 617,
    2867, 457, 1613, 2837, 748, 2120, 2691, 754,
    1318, 37, 1417, 1256, 2644, 1253, 3255, 1444,
    273, 1168, 1750, 2042, 2577, 3075, 2691, 1602,
    2867, 457, 1613, 2837, 748, 2120, 2691, 754,
    2135, 2328, 1709, 709, 3015, 2919, 2964, 3027,
    2867, 457, 1613, 2837, 748, 2120, 2691, 754,
    2555, 3156, 1265, 625, 72, 1201, 690, 389,
    3254, 1068,
    -1 };
    

main()
{
#ifdef TSTA
    histogram h(20, 0, 4000);
#else
    static int lowvals[] = {
	0, 50, 200, 500, 1000, 1500, 2000, 2500, 3000, 3500, 4000
    };
    histogram h(10, lowvals);
#endif
    for (long *xp = x; *xp != -1; xp++)
	h.add(*xp);
    h.print();
    return 0;
}
!EOF!
ls -l 5_7btst.c
echo x - histogram.h
sed 's/^X//' > histogram.h << '!EOF!'
/* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */
/* The C++ Answer Book */
/* Tony Hansen */
/* All rights reserved. */
#ifdef TSTA
# include "5_7A.h"
#else
#ifdef TSTB
# include "5_7B.h"
#else
    ????;
#endif
#endif
!EOF!
ls -l histogram.h
echo x - makefile
sed 's/^X//' > makefile << '!EOF!'
CC= CC -I. -I../../CC
ERROR=  ../../error.o
all: 5_7A 5_7B 5_7B2

AOBJS= 5_7a1.o 5_7a2.o 5_7a3.o 5_7atst.o
BOBJS= 5_7b1.o 5_7b2.o 5_7b3.o 5_7btst.o
B2OBJS= 5_7b1.o 5_7b2.o 5_7b4.o 5_7btst.o

5_7A: $(AOBJS)
	$(CC) $(AOBJS) -o 5_7A $(ERROR)

5_7B: $(BOBJS)
	$(CC) $(BOBJS) -o 5_7B $(ERROR)

5_7B2: $(B2OBJS)
	$(CC) $(B2OBJS) -o 5_7B2 $(ERROR)

5_7a1.o: 5_7a1.c 5_7A.h histogram.h
	$(CC) -DTSTA -I. -c  5_7a1.c

5_7a2.o: 5_7a2.c 5_7A.h histogram.h
	$(CC) -DTSTA -I. -c  5_7a2.c

5_7a3.o: 5_7a3.c 5_7A.h histogram.h
	$(CC) -DTSTA -I. -c  5_7a3.c

5_7atst.o: 5_7atst.c 5_7B.h histogram.h
	$(CC) -DTSTA -I. -c  5_7atst.c

5_7b1.o: 5_7b1.c 5_7B.h histogram.h
	$(CC) -DTSTB -I. -c  5_7b1.c

5_7b2.o: 5_7b2.c 5_7B.h histogram.h
	$(CC) -DTSTB -I. -c  5_7b2.c

5_7b3.o: 5_7b3.c 5_7B.h histogram.h
	$(CC) -DTSTB -I. -c  5_7b3.c

5_7b4.o: 5_7b4.c 5_7B.h histogram.h
	$(CC) -DTSTB -I. -c  5_7b4.c

5_7btst.o: 5_7btst.c 5_7B.h histogram.h
	$(CC) -DTSTB -I. -c  5_7btst.c

CMP= 5_7A.cmp 5_7B.cmp 5_7B2.cmp
OUT= 5_7A.out 5_7B.out 5_7B2.out

5_7A.out: 5_7A ;	5_7A > 5_7A.out
5_7B.out: 5_7B ;	5_7B > 5_7B.out
5_7B2.out: 5_7B2 ;	5_7B2 > 5_7B2.out

test: all $(OUT) $(CMP)
	cmp 5_7A.out 5_7A.cmp
	cmp 5_7B.out 5_7B.cmp
	cmp 5_7B2.out 5_7B2.cmp
	echo tests done
!EOF!
ls -l makefile
# The following exit is to ensure that extra garbage 
# after the end of the shar file will be ignored.
exit 0
