mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2024-11-01 08:07:10 -04:00
189 lines
3.8 KiB
C
189 lines
3.8 KiB
C
|
/* DISTRIB.C - Procedures for handling distributions over numbers. */
|
||
|
|
||
|
/* Copyright (c) 1995-2012 by Radford M. Neal and Peter Junteng Liu.
|
||
|
*
|
||
|
* Permission is granted for anyone to copy, use, modify, and distribute
|
||
|
* these programs and accompanying documents for any purpose, provided
|
||
|
* this copyright notice is retained and prominently displayed, and note
|
||
|
* is made of any changes made to these programs. These programs and
|
||
|
* documents are distributed without any warranty, express or implied.
|
||
|
* As the programs were written for research purposes only, they have not
|
||
|
* been tested to the degree that would be advisable in any important
|
||
|
* application. All use of these programs is entirely at the user's own
|
||
|
* risk.
|
||
|
*/
|
||
|
|
||
|
#include <stdlib.h>
|
||
|
#include <stdio.h>
|
||
|
#include <math.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
#include "alloc.h"
|
||
|
#include "distrib.h"
|
||
|
|
||
|
|
||
|
/* CREATE A DISTRIBUTION AS SPECIFIED IN A STRING. Space for the distribution
|
||
|
is allocated; the string is not freed.
|
||
|
|
||
|
The string must consist either of a single positive integer, representing
|
||
|
the distribution over just that number, or have a form such as the
|
||
|
following:
|
||
|
|
||
|
5x2/3.5x1/1.5x4
|
||
|
|
||
|
This specifies a distribution over 3 numbers, 2, 1, and 4, specified by
|
||
|
the second number in each pair, with proportions of 0.5, 0.35, and 0.15,
|
||
|
respectively, specified by the first number in each pair. The actual
|
||
|
proportions are found by dividing the first number in each pair by the sum
|
||
|
of these numbers.
|
||
|
|
||
|
The distrib type represents the distribution list. It stores a pointer to
|
||
|
an array of distrib_entry elements along with the length of this array.
|
||
|
Each distrib_entry contains a (number,proportion) pair.
|
||
|
*/
|
||
|
|
||
|
distrib *distrib_create
|
||
|
( char *c /* String describing distribution over numbers */
|
||
|
)
|
||
|
{
|
||
|
distrib *d;
|
||
|
char *str, *tstr;
|
||
|
int i, n, scan_num, size;
|
||
|
double prop, sum;
|
||
|
char junk;
|
||
|
|
||
|
/* Check for special case of a single number. */
|
||
|
|
||
|
if (sscanf(c,"%d%c",&n,&junk)==1 && n>0)
|
||
|
{ tstr = chk_alloc ( (int)(4.1+log10(n)), sizeof(*tstr));
|
||
|
sprintf(tstr,"1x%d",n);
|
||
|
d = distrib_create(tstr);
|
||
|
free(tstr);
|
||
|
return d;
|
||
|
}
|
||
|
|
||
|
/* Initial scan of string for size and proper usage. */
|
||
|
|
||
|
str = c;
|
||
|
size = 0;
|
||
|
sum = 0;
|
||
|
|
||
|
d = chk_alloc(1, sizeof *d);
|
||
|
|
||
|
for (;;)
|
||
|
{
|
||
|
scan_num = sscanf(str, "%lgx%d%c", &prop, &n, &junk);
|
||
|
|
||
|
if ((scan_num!=2 && scan_num!=3) || prop<=0 || n<=0)
|
||
|
{ return 0;
|
||
|
}
|
||
|
if (scan_num==3 && junk!='/')
|
||
|
{ return 0;
|
||
|
}
|
||
|
|
||
|
size += 1;
|
||
|
sum += prop;
|
||
|
|
||
|
if (scan_num==2)
|
||
|
{ break;
|
||
|
}
|
||
|
else
|
||
|
{ str = (char*)strchr(str, '/') + 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Allocate memory for the list and fill it in */
|
||
|
|
||
|
d->size = size;
|
||
|
d->list = chk_alloc (size, sizeof(distrib_entry));
|
||
|
|
||
|
i = 0;
|
||
|
str = c;
|
||
|
|
||
|
for (;;)
|
||
|
{
|
||
|
scan_num = sscanf(str, "%lgx%d%c", &prop, &n, &junk);
|
||
|
|
||
|
d->list[i].prop = prop/sum;
|
||
|
d->list[i].num = n;
|
||
|
i += 1;
|
||
|
|
||
|
if (scan_num==2)
|
||
|
{ break;
|
||
|
}
|
||
|
else if (scan_num==3)
|
||
|
{ str = (char*)strchr(str, '/') + 1;
|
||
|
}
|
||
|
else
|
||
|
{ abort();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return d;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* FREE SPACE OCCUPIED A DISTRIBUTION LIST. */
|
||
|
|
||
|
void distrib_free
|
||
|
( distrib *d /* List to free */
|
||
|
)
|
||
|
{ free(d->list);
|
||
|
free(d);
|
||
|
}
|
||
|
|
||
|
|
||
|
/* RETURN THE MAXIMUM NUMBER IN A DISTRIBUTION LIST. Returns 0 if the list
|
||
|
pointer is 0. */
|
||
|
|
||
|
int distrib_max
|
||
|
( distrib *d /* List to examine */
|
||
|
)
|
||
|
{
|
||
|
int i;
|
||
|
int cur;
|
||
|
|
||
|
if (d==0) return 0;
|
||
|
|
||
|
cur = 0;
|
||
|
|
||
|
for (i = 1; i<d->size; i++)
|
||
|
{ if (d->list[i].num > d->list[cur].num)
|
||
|
{ cur = i;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return d->list[cur].num;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* TEST PROGRAM. */
|
||
|
|
||
|
#ifdef TEST_DISTRIB
|
||
|
|
||
|
main
|
||
|
( int argc,
|
||
|
char **argv
|
||
|
)
|
||
|
{
|
||
|
distrib *d;
|
||
|
int i, j;
|
||
|
|
||
|
for (i = 1; i<argc; i++)
|
||
|
{ d = distrib_create(argv[i]);
|
||
|
if (d==0)
|
||
|
{ printf("Error\n\n");
|
||
|
}
|
||
|
else
|
||
|
{ for (j = 0; j<distrib_size(d); j++)
|
||
|
{ printf("%.3f %d\n",distrib_prop(d,j),distrib_num(d,j));
|
||
|
}
|
||
|
printf("\n");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
exit(0);
|
||
|
}
|
||
|
|
||
|
#endif
|