complete update

This commit is contained in:
gurkenhabicht 2018-05-19 19:04:50 +02:00
parent 17c1c6c1e6
commit 07d6db93dc
4 changed files with 997 additions and 851 deletions

View File

@ -1,133 +1,185 @@
// /*
// ===========================================================================
// NLMSvariants.c
// Created by Stefan Friese on 26.04.2018
// Created by FBRDNLMS on 26.04.18.
// ===========================================================================
*/
// //
#include <stdio.h> #include <stdio.h>
#include <math.h> #include <math.h>
#include <time.h> #include <time.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <float.h> // DBL_MAX //#include <float.h> // DBL_MAX
#include "nlms_types.h" // added types
#define NUMBER_OF_SAMPLES 500
#define WINDOWSIZE 5
#define learnrate 0.8
#define RGB_COLOR 255 #define RGB_COLOR 255
#if defined(_MSC_VER) #if defined(_MSC_VER)
#include <BaseTsd.h> #include <BaseTsd.h>
typedef SSIZE_T ssize_t; typedef SSIZE_T ssize_t;
#endif #endif
enum fileSuffix_t { // used in conjunction with mkFileName() typedef struct {
PURE_WEIGHTS, double *weights;
USED_WEIGHTS, unsigned windowSize;
DIRECT_PREDECESSOR, unsigned samplesCount;
RESULTS, double learnrate;
LOCAL_MEAN, } mldata_t;
TEST_VALUES,
DIFFERENTIAL_PREDECESSOR enum fileHeader{
LOCAL_MEAN_HEADER,
DIRECT_PREDECESSOR_HEADER,
DIFFERENTIAL_PREDECESSOR_HEADER
}; };
double xSamples[NUMBER_OF_SAMPLES] = { 0.0 }; double *xSamples;
mldata_t *mlData = NULL; // Machine learning
point_t *points = NULL; // Graphing
/* *svg graph building* */ /* *graph building* */
typedef struct { static imagePixel_t * rdPPM(char *fileName); // Read PPM file format
double xVal[7]; void mkPpmFile(char *fileName, imagePixel_t *image); // Writes PPM file
double yVal[7]; int ppmColorChannel(FILE* fp, imagePixel_t *image, // Writes colorChannel from PPM file to log file
}point_t; char *colorChannel, mldata_t *mlData);
void colorSamples(FILE* fp, mldata_t *mlData); // Stores color channel values in xSamples
point_t points[NUMBER_OF_SAMPLES]; // [0] = xActual, [1]=xpredicted from localMean, [2]=xpredicted from directPredecessor, [3] = xpredicted from differentialpredecessor, [4] = xError from localMean, [5] xError from directPredecessor, [6] xError from differentialPredecessor
/* *ppm read, copy, write* */
typedef struct {
unsigned char red, green, blue;
}colorChannel_t;
typedef struct {
int x, y;
colorChannel_t *data;
}imagePixel_t;
static imagePixel_t * rdPPM(char *fileName); // read PPM file format
void mkPpmFile(char *fileName, imagePixel_t *image); // writes PPM file
int ppmColorChannel(FILE* fp, imagePixel_t *image); // writes colorChannel from PPM file to log file
void colorSamples(FILE* fp); // stores color channel values in xSamples[]
/* *file handling* */ /* *file handling* */
char * mkFileName(char* buffer, size_t max_len, int suffixId); char * mkFileName ( char* buffer,
size_t max_len, int suffixId );
char *fileSuffix ( int id ); char *fileSuffix ( int id );
void myLogger(FILE* fp, point_t points[]); char *fileHeader ( int id ); // Header inside the logfiles
void mkSvgGraph(point_t points[]); //void myLogger ( FILE* fp, point_t points[] );
//void weightsLogger(double *weights, int var); void bufferLogger(char *buffer, point_t points[]); // Writes points to graph template
void mkSvgGraph ( point_t points[] ); // Parses graph template and calls bufferLogger()
void weightsLogger ( double *weights, int suffix ); // Writes updated weights to a file
/* *rand seed* */ /* *rand seed* */
double r2(void); double r2 ( void ); // Random val between 0 and 1
double rndm ( void ); double rndm ( void );
/* *args parser* */
void usage ( void ); // Help text called by args parser
/* *math* */ /* *math* */
mldata_t * init_mldata_t(unsigned windowSize, unsigned samplesCount, double learnrate);
double sum_array(double x[], int length); double sum_array(double x[], int length);
void directPredecessor(double weights[WINDOWSIZE][NUMBER_OF_SAMPLES]);
void localMean(double weights[WINDOWSIZE][NUMBER_OF_SAMPLES]); void localMean ( mldata_t *mlData,point_t points[] ); // First,
void differentialPredecessor(double weights[WINDOWSIZE][NUMBER_OF_SAMPLES]); void directPredecessor ( mldata_t *mlData, point_t points[] ); // Second,
//void differentialPredecessor(double *weights); void differentialPredecessor ( mldata_t *mlData, point_t points[] ); // Third filter implementation
double *popNAN(double *xError); //return new array without NAN values
double windowXMean(int _arraylength, int xCount); double *popNAN(double *xError); // Returns array without NAN values, if any exist
double windowXMean(int _arraylength, int xCount); // Returns mean value of given window
//int main(int argc, char **argv) {
int main(void) { int main( int argc, char **argv ) {
double weights[WINDOWSIZE][NUMBER_OF_SAMPLES]; // = { { 0.0 }, {0.0} }; char *colorChannel = (char *) malloc(sizeof(char)* 32);
// double local_weights[WINDOWSIZE][NUMBER_OF_SAMPLES]; char *inputfile = (char *)malloc(sizeof(char) * 32);
char fileName[50]; unsigned int *seed = NULL;
int i, k, xLength; unsigned k, xLength;
unsigned int windowSize = 5;
unsigned int samplesCount = 501;
char *stdcolor = "green";
colorChannel = stdcolor;
unsigned int uint_buffer[1];
double learnrate = 0.8;
while( (argc > 1) && (argv[1][0] == '-') ) { // Parses parameters from stdin
switch( argv[1][1] ) {
case 'i':
inputfile = &argv[1][3];
++argv;
--argc;
break;
case 'w':
sscanf(&argv[1][3], "%u", &windowSize);
++argv;
--argc;
break;
case 'c':
colorChannel = &argv[1][3];
++argv;
--argc;
break;
case 's':
sscanf(&argv[1][3], "%u", uint_buffer);
seed = &uint_buffer[0];
++argv;
--argc;
break;
case 'n':
sscanf(&argv[1][3], "%u", &samplesCount);
++argv;
--argc;
break;
case'h':
printf("Program name: %s\n", argv[0]);
usage();
break;
case 'l':
sscanf(&argv[1][3], "%lf", &learnrate);
++argv;
--argc;
break;
default:
printf("Wrong Arguments: %s\n", argv[1]);
usage();
}
++argv;
--argc;
}
init_mldata_t(windowSize, samplesCount, learnrate);
xSamples = (double *) malloc ( sizeof(double) * mlData->samplesCount );
points = (point_t *) malloc ( sizeof(point_t) * mlData->samplesCount);
imagePixel_t *image; imagePixel_t *image;
char fileName[50];
image = rdPPM("cow.ppm"); image = rdPPM(inputfile);
mkFileName(fileName, sizeof(fileName), TEST_VALUES); mkFileName(fileName, sizeof(fileName), TEST_VALUES);
FILE* fp5 = fopen(fileName, "w"); FILE* fp5 = fopen(fileName, "w");
xLength = ppmColorChannel(fp5, image); xLength = ppmColorChannel(fp5, image, colorChannel, mlData); // Returns length of ppm input values
printf("%d\n", xLength); printf("%d\n", xLength);
FILE* fp6 = fopen(fileName, "r"); FILE* fp6 = fopen(fileName, "r");
colorSamples(fp6); colorSamples(fp6, mlData);
if ( (seed != NULL) ){
srand( *seed ); // Seed for random number generating
printf("srand is reproducable : %u", seed);
} else {
srand( (unsigned int)time(NULL) ); srand( (unsigned int)time(NULL) );
for (i = 0; i < NUMBER_OF_SAMPLES; i++) { printf("srand from time\n"); // Default seed is time(NULL)
for (int k = 0; k < WINDOWSIZE; k++) {
weights[k][i] = rndm(); // Init weights
} }
// for (i = 0; i < NUMBER_OF_SAMPLES; i++) {
for (k = 0; k < mlData->windowSize; k++) {
mlData->weights[k] = rndm(); // Init random weights
printf("%lf\n", mlData->weights[k]);
} }
mkFileName(fileName, sizeof(fileName), PURE_WEIGHTS); // }
// save plain test_array before math magic happens
FILE *fp0 = fopen(fileName, "w");
for (i = 0; i < NUMBER_OF_SAMPLES; i++) {
for (k = 0; k < WINDOWSIZE; k++) {
fprintf(fp0, "[%d][%d]%lf\n", k, i, weights[k][i]);
}
}
fclose(fp0);
// math magic
localMean(weights);
directPredecessor(weights);
differentialPredecessor(weights);
mkSvgGraph(points);
// save test_array after math magic happened
// memset( fileName, '\0', sizeof(fileName) );
/* mkFileName(fileName, sizeof(fileName), USED_WEIGHTS);
FILE *fp1 = fopen(fileName, "w");
for (i = 0; i < tracking; i++) {
for (int k = 0; k < WINDOWSIZE; k++) {
fprintf(fp1, "[%d][%d] %lf\n", k, i, w[k][i]);
}
mkFileName(fileName, sizeof(fileName), PURE_WEIGHTS);
FILE *fp0 = fopen(fileName, "w");
// for (i = 0; i < NUMBER_OF_SAMPLES; i++) {
for (k = 0; k < mlData->windowSize; k++) {
fprintf(fp0, "[%d]%lf\n", k, mlData->weights[k]); // Save generated weights to to file
} }
fclose(fp1); // }
*/ fclose(fp0);
// math magic
localMean ( mlData, points );
directPredecessor ( mlData, points);
differentialPredecessor( mlData, points );
mkSvgGraph(points);
free(xSamples);
free(points);
printf("\nDONE!\n"); printf("\nDONE!\n");
} }
/* /*
====================================================================================================== ======================================================================================================
@ -137,43 +189,37 @@ Variant (1/3), substract local mean.
====================================================================================================== ======================================================================================================
*/ */
void localMean ( mldata_t *mlData, point_t points[] ) {
// double (*local_weights)[WINDOWSIZE] =(double (*)[WINDOWSIZE]) malloc(sizeof(double) * (WINDOWSIZE+1) * (NUMBER_OF_SAMPLES+1));
//memcpy(local_weights, weights, sizeof(double) * WINDOWSIZE * NUMBER_OF_SAMPLES);
double *localWeights = (double *) malloc ( sizeof(double) * mlData->windowSize + 1);
memcpy ( localWeights, mlData->weights, sizeof(mlData->windowSize) ); // TODO: check size !!!
void localMean(double weights[WINDOWSIZE][NUMBER_OF_SAMPLES]) {
//double local_weights[WINDOWSIZE][NUMBER_OF_SAMPLES];
double(*local_weights)[WINDOWSIZE] = (double(*)[WINDOWSIZE])malloc(sizeof(double) * (WINDOWSIZE + 1) * (NUMBER_OF_SAMPLES + 1));
// double *local_weights[WINDOWSIZE];
memcpy(local_weights, weights, sizeof(double) * WINDOWSIZE * NUMBER_OF_SAMPLES);
char fileName[50]; char fileName[50];
double xError[2048]; // includes e(n) double xError[2048]; // includes e(n)
memset(xError, 0.0, NUMBER_OF_SAMPLES);// initialize xError-array with Zero memset(xError, 0.0, mlData->samplesCount);// initialize xError-array with Zero
int xCount = 0, i; // runtime var; unsigned i, xCount = 0; // runtime var
mkFileName(fileName, sizeof(fileName), LOCAL_MEAN); mkFileName(fileName, sizeof(fileName), LOCAL_MEAN);
FILE* fp4 = fopen(fileName, "w"); FILE* fp4 = fopen(fileName, "w");
fprintf(fp4, "\n=====================================LocalMean=====================================\nNo.\txPredicted\txActual\t\txError\n"); fprintf( fp4, fileHeader(LOCAL_MEAN_HEADER) );
double xMean = xSamples[0]; double xMean = xSamples[0];
double xSquared = 0.0; double xSquared = 0.0;
double xPredicted = 0.0; double xPredicted = 0.0;
double xActual = 0.0; double xActual = 0.0;
for (xCount = 1; xCount < NUMBER_OF_SAMPLES; xCount++) { // first value will not get predicted for (xCount = 1; xCount < mlData->samplesCount; xCount++) { // first value will not get predicted
int _arrayLength = (xCount > WINDOWSIZE) ? WINDOWSIZE + 1 : xCount; unsigned _arrayLength = ( xCount > mlData->windowSize ) ? mlData->windowSize + 1 : xCount;
xMean = (xCount > 0) ? windowXMean(_arrayLength, xCount) : 0; xMean = (xCount > 0) ? windowXMean(_arrayLength, xCount) : 0;
xPredicted = 0.0; xPredicted = 0.0;
xActual = xSamples[xCount + 1]; xActual = xSamples[xCount];
// weightedSum += _x[ xCount-1 ] * w[xCount][0];
for (i = 1; i < _arrayLength; i++) { //get predicted value for (i = 1; i < _arrayLength; i++) { //get predicted value
xPredicted += (local_weights[i][xCount] * (xSamples[xCount - i] - xMean)); xPredicted += (localWeights[i] * (xSamples[xCount - i] - xMean));
} }
xPredicted += xMean; xPredicted += xMean;
xError[xCount] = xActual - xPredicted; xError[xCount] = xActual - xPredicted;
points[xCount].xVal[1] = xCount;
points[xCount].yVal[1] = xPredicted;
points[xCount].xVal[4] = xCount;
points[xCount].yVal[4] = xError[xCount];
xSquared = 0.0; xSquared = 0.0;
for (i = 1; i < _arrayLength; i++) { //get xSquared for (i = 1; i < _arrayLength; i++) { //get xSquared
xSquared += pow(xSamples[xCount - i] - xMean, 2); xSquared += pow(xSamples[xCount - i] - xMean, 2);
@ -182,14 +228,22 @@ void localMean(double weights[WINDOWSIZE][NUMBER_OF_SAMPLES]) {
xSquared = 1.0; xSquared = 1.0;
} }
for ( i = 1; i < _arrayLength; i++ ) { //update weights for ( i = 1; i < _arrayLength; i++ ) { //update weights
local_weights[i][xCount + 1] = local_weights[i][xCount] + learnrate * xError[xCount] * ((xSamples[xCount - i] - xMean) / xSquared); localWeights[ i + 1 ] = localWeights[i] + mlData->learnrate * xError[xCount] * ( (xSamples[xCount - i] - xMean) / xSquared );
} }
fprintf(fp4, "%d\t%f\t%f\t%f\n", xCount, xPredicted, xActual, xError[xCount]); fprintf(fp4, "%d\t%f\t%f\t%f\n", xCount, xPredicted, xActual, xError[xCount]);
points[xCount].xVal[1] = xCount;
points[xCount].yVal[1] = xPredicted;
points[xCount].xVal[4] = xCount;
points[xCount].yVal[4] = xError[xCount];
} }
double *xErrorPtr = popNAN(xError); // delete NAN values from xError[] double *xErrorPtr = popNAN(xError); // delete NAN values from xError[]
double xErrorLength = *xErrorPtr; // Watch popNAN()! double xErrorLength = *xErrorPtr; // Watch popNAN()!
xErrorPtr[0] = 0.0; xErrorPtr[0] = 0.0;
printf("Xerrorl:%lf", xErrorLength); // printf("Xerrorl:%lf", xErrorLength);
double mean = sum_array(xErrorPtr, xErrorLength) / xErrorLength; double mean = sum_array(xErrorPtr, xErrorLength) / xErrorLength;
double deviation = 0.0; double deviation = 0.0;
@ -205,7 +259,7 @@ void localMean(double weights[WINDOWSIZE][NUMBER_OF_SAMPLES]) {
//FILE *fp2 = fopen(fileName, "w"); //FILE *fp2 = fopen(fileName, "w");
fprintf(fp4, "\nQuadratische Varianz(x_error): %f\nMittelwert:(x_error): %f\n\n", deviation, mean); fprintf(fp4, "\nQuadratische Varianz(x_error): %f\nMittelwert:(x_error): %f\n\n", deviation, mean);
//fclose(fp2); //fclose(fp2);
free(local_weights); free(localWeights);
fclose(fp4); fclose(fp4);
//weightsLogger( local_weights, USED_WEIGHTS ); //weightsLogger( local_weights, USED_WEIGHTS );
@ -221,61 +275,58 @@ substract direct predecessor
====================================================================================================== ======================================================================================================
*/ */
void directPredecessor( mldata_t *mlData, point_t points[]) {
void directPredecessor(double weights[WINDOWSIZE][NUMBER_OF_SAMPLES]) { double *localWeights = ( double * ) malloc ( sizeof(double) * mlData->windowSize + 1 );
double(*local_weights)[WINDOWSIZE] = (double(*)[WINDOWSIZE])malloc(sizeof(double) * (WINDOWSIZE + 1) * (NUMBER_OF_SAMPLES + 1)); memcpy ( localWeights, mlData->weights, sizeof(mlData->windowSize) );
// double local_weights[WINDOWSIZE][NUMBER_OF_SAMPLES];
memcpy(local_weights, weights, sizeof(double) * WINDOWSIZE * NUMBER_OF_SAMPLES);
char fileName[512]; char fileName[512];
double xError[2048]; double xError[2048];
int xCount = 0, i; unsigned xCount = 0, i;
double xActual = 0.0; double xActual = 0.0;
double xPredicted = 0.0; double xPredicted = 0.0;
// File handling
mkFileName(fileName, sizeof(fileName), DIRECT_PREDECESSOR); mkFileName(fileName, sizeof(fileName), DIRECT_PREDECESSOR);
FILE *fp3 = fopen(fileName, "w"); FILE *fp3 = fopen(fileName, "w");
fprintf(fp3, "\n=====================================DirectPredecessor=====================================\nNo.\txPredicted\txAcutal\t\txError\n"); fprintf( fp3, fileHeader(DIRECT_PREDECESSOR_HEADER) );
mkFileName ( fileName, sizeof(fileName), USED_WEIGHTS);
FILE *fp9 = fopen(fileName, "w");
for (xCount = 1; xCount < NUMBER_OF_SAMPLES; xCount++) { // first value will not get predicted for (xCount = 1; xCount < mlData->samplesCount; xCount++) { // first value will not get predicted
//double xPartArray[1000]; //includes all values at the size of runtime var unsigned _arrayLength = ( xCount > mlData->windowSize ) ? mlData->windowSize + 1 : xCount;
//int _sourceIndex = (xCount > WINDOWSIZE) ? xCount - WINDOWSIZE : xCount;
int _arrayLength = (xCount > WINDOWSIZE) ? WINDOWSIZE + 1 : xCount;
//printf("xCount:%d, length:%d\n", xCount, _arrayLength);
// printf("WINDOWSIZE:%f\n", windowXMean(_arrayLength, xCount));
xPredicted = 0.0; xPredicted = 0.0;
xActual = xSamples[xCount + 1]; xActual = xSamples[xCount];
// weightedSum += _x[ xCount-1 ] * w[xCount][0];
for (i = 1; i < _arrayLength; i++) { for (i = 1; i < _arrayLength; i++) {
xPredicted += (local_weights[i][xCount] * (xSamples[xCount - 1] - xSamples[xCount - i - 1])); xPredicted += ( localWeights[i - 1] * (xSamples[xCount - 1] - xSamples[xCount - i - 1]));
} }
xPredicted += xSamples[xCount - 1]; xPredicted += xSamples[xCount - 1];
xError[xCount] = xActual - xPredicted; xError[xCount] = xActual - xPredicted;
//fprintf(fp3, "{%d}.\txPredicted{%f}\txActual{%f}\txError{%f}\n", xCount, xPredicted, xActual, xError[xCount]);
points[xCount].xVal[2] = xCount;
points[xCount].yVal[2] = xPredicted;
points[xCount].xVal[5] = xCount;
points[xCount].yVal[5] = xError[xCount];
double xSquared = 0.0; double xSquared = 0.0;
for (i = 1; i < _arrayLength; i++) { for (i = 1; i < _arrayLength; i++) {
xSquared += pow(xSamples[xCount - 1] - xSamples[xCount - i - 1], 2); // substract direct predecessor xSquared += pow(xSamples[xCount - 1] - xSamples[xCount - i - 1], 2); // substract direct predecessor
} }
for (i = 1; i < _arrayLength; i++) { for (i = 1; i < _arrayLength; i++) {
local_weights[i][xCount + 1] = local_weights[i][xCount] + learnrate * xError[xCount] * ((xSamples[xCount - 1] - xSamples[xCount - i - 1]) / xSquared); localWeights[i + 1] = localWeights[i] + mlData->learnrate * xError[xCount] * ( (xSamples[xCount - 1] - xSamples[xCount - i - 1]) / xSquared);
} fprintf( fp9, "%lf\n", localWeights[i] );
fprintf(fp3, "%d\t%f\t%f\t%f\n", xCount, xPredicted, xActual, xError[xCount]);
} }
fprintf(fp3, "%d\t%f\t%f\t%f\n", xCount, xPredicted, xActual, xError[xCount]);
points[xCount].xVal[2] = xCount; // Fill point_t array for graph building
points[xCount].yVal[2] = xPredicted;
points[xCount].xVal[5] = xCount;
points[xCount].yVal[5] = xError[xCount];
// weightsLogger( fp, localWeights, USED_WEIGHTS );
}
fclose(fp9);
double *xErrorPtr = popNAN(xError); // delete NAN values from xError[] double *xErrorPtr = popNAN(xError); // delete NAN values from xError[]
//printf("%lf", xErrorPtr[499]); //printf("%lf", xErrorPtr[499]);
double xErrorLength = *xErrorPtr; // Watch popNAN()! double xErrorLength = *xErrorPtr; // Watch popNAN()!
xErrorPtr[0] = 0.0; xErrorPtr[0] = 0.0;
printf("Xerrorl:%lf", xErrorLength); //printf("Xerrorl:%lf", xErrorLength);
double mean = sum_array(xErrorPtr, xErrorLength) / xErrorLength; double mean = sum_array(xErrorPtr, xErrorLength) / xErrorLength;
double deviation = 0.0; double deviation = 0.0;
@ -293,12 +344,10 @@ void directPredecessor(double weights[WINDOWSIZE][NUMBER_OF_SAMPLES]) {
fprintf(fp3, "\nQuadratische Varianz(x_error): %f\nMittelwert:(x_error): %f\n\n", deviation, mean); fprintf(fp3, "\nQuadratische Varianz(x_error): %f\nMittelwert:(x_error): %f\n\n", deviation, mean);
fclose(fp3); fclose(fp3);
//fclose(fp2); //fclose(fp2);
free(local_weights); free(localWeights);
//weightsLogger( local_weights, USED_WEIGHTS );
} }
/* /*
====================================================================================================== ======================================================================================================
@ -309,71 +358,54 @@ differential predecessor.
====================================================================================================== ======================================================================================================
*/ */
void differentialPredecessor(double weights[WINDOWSIZE][NUMBER_OF_SAMPLES]) { void differentialPredecessor ( mldata_t *mlData, point_t points[] ) {
// double local_weights[WINDOWSIZE][NUMBER_OF_SAMPLES]; double *localWeights = (double *) malloc ( sizeof(double) * mlData->windowSize + 1 );
double(*local_weights)[WINDOWSIZE] = (double(*)[WINDOWSIZE])malloc(sizeof(double) * (WINDOWSIZE + 1) * (NUMBER_OF_SAMPLES + 1)); memcpy( localWeights, mlData->weights, sizeof(mlData->windowSize) );
memcpy(local_weights, weights, sizeof(double) * WINDOWSIZE * NUMBER_OF_SAMPLES);
char fileName[512]; char fileName[512];
double xError[2048]; double xError[2048];
int xCount = 0, i; unsigned xCount = 0, i;
double xPredicted = 0.0; double xPredicted = 0.0;
double xActual = 0.0; double xActual = 0.0;
// File handling // File handling
mkFileName(fileName, sizeof(fileName), DIFFERENTIAL_PREDECESSOR); mkFileName(fileName, sizeof(fileName), DIFFERENTIAL_PREDECESSOR);
FILE *fp6 = fopen(fileName, "w"); FILE *fp6 = fopen(fileName, "w");
fprintf(fp6, "\n=====================================DifferentialPredecessor=====================================\nNo.\txPredicted\txAcutal\t\txError\n"); fprintf(fp6, fileHeader(DIFFERENTIAL_PREDECESSOR_HEADER) );
for (xCount = 1; xCount < NUMBER_OF_SAMPLES; xCount++) { // first value will not get predicted for (xCount = 1; xCount < mlData->samplesCount; xCount++) { // first value will not get predicted
int _arrayLength = (xCount > WINDOWSIZE) ? WINDOWSIZE + 1 : xCount; unsigned _arrayLength = (xCount > mlData->windowSize) ? mlData->windowSize + 1 : xCount;
xPredicted = 0.0; xPredicted = 0.0;
xActual = xSamples[xCount + 1]; xActual = xSamples[xCount];
for (i = 1; i < _arrayLength; i++) { for (i = 1; i < _arrayLength; i++) {
xPredicted += (local_weights[i][xCount] * (xSamples[xCount - i] - xSamples[xCount - i - 1])); xPredicted += ( localWeights[i - 1] * (xSamples[xCount - i] - xSamples[xCount - i - 1]));
} }
xPredicted += xSamples[xCount - 1]; xPredicted += xSamples[xCount - 1];
xError[xCount] = xActual - xPredicted; xError[xCount] = xActual - xPredicted;
//fprintf(fp6, "{%d}.\txPredicted{%f}\txActual{%f}\txError{%f}\n", xCount, xPredicted, xActual, xError[xCount]);
points[xCount].xVal[3] = xCount;
points[xCount].yVal[3] = xPredicted;
points[xCount].xVal[6] = xCount;
points[xCount].yVal[6] = xError[xCount];
double xSquared = 0.0; double xSquared = 0.0;
for (i = 1; i < _arrayLength; i++) { for (i = 1; i < _arrayLength; i++) {
xSquared += pow(xSamples[xCount - i] - xSamples[xCount - i - 1], 2); // substract direct predecessor xSquared += pow(xSamples[xCount - i] - xSamples[xCount - i - 1], 2); // substract direct predecessor
} }
for (i = 1; i < _arrayLength; i++) { for (i = 1; i < _arrayLength; i++) {
local_weights[i][xCount + 1] = local_weights[i][xCount] + learnrate * xError[xCount] * ((xSamples[xCount - i] - xSamples[xCount - i - 1]) / xSquared); localWeights[i+1] = localWeights[i] + mlData->learnrate * xError[xCount] * ((xSamples[xCount - i] - xSamples[xCount - i - 1]) / xSquared);
} }
fprintf(fp6, "%d\t%f\t%f\t%f\n", xCount, xPredicted, xActual, xError[xCount]); fprintf(fp6, "%d\t%f\t%f\t%f\n", xCount, xPredicted, xActual, xError[xCount]); // Write to logfile
points[xCount].xVal[3] = xCount;
points[xCount].yVal[3] = xPredicted;
points[xCount].xVal[6] = xCount;
points[xCount].yVal[6] = xError[xCount];
} }
/* int xErrorLength = sizeof(xError) / sizeof(xError[0]);
printf("vor:%d", xErrorLength);
popNAN(xError);
printf("nach:%d", xErrorLength);
xErrorLength = sizeof(xError) / sizeof(xError[0]);
double mean = sum_array(xError, xErrorLength) / xErrorLength;
double deviation = 0.0;
for (i = 0; i < xErrorLength - 1; i++) {
deviation += pow(xError[i] - mean, 2);
}
deviation /= xErrorLength;
//mkSvgGraph(points);
fprintf(fp6, "{%d}.\tLeast Mean Squared{%f}\tMean{%f}\n\n", xCount, deviation, mean);
*/
double *xErrorPtr = popNAN(xError); // delete NAN values from xError[] double *xErrorPtr = popNAN(xError); // delete NAN values from xError[]
//printf("%lf", xErrorPtr[499]); //printf("%lf", xErrorPtr[499]);
double xErrorLength = *xErrorPtr; // Watch popNAN()! double xErrorLength = *xErrorPtr; // Watch popNAN()!
xErrorPtr[0] = 0.0; xErrorPtr[0] = 0.0;
printf("Xerrorl:%lf", xErrorLength); // printf("Xerrorl:%lf", xErrorLength);
double mean = sum_array(xErrorPtr, xErrorLength) / xErrorLength; double mean = sum_array(xErrorPtr, xErrorLength) / xErrorLength;
double deviation = 0.0; double deviation = 0.0;
@ -391,12 +423,11 @@ void differentialPredecessor(double weights[WINDOWSIZE][NUMBER_OF_SAMPLES]) {
fprintf(fp6, "\nQuadratische Varianz(x_error): %f\nMittelwert:(x_error): %f\n\n", deviation, mean); fprintf(fp6, "\nQuadratische Varianz(x_error): %f\nMittelwert:(x_error): %f\n\n", deviation, mean);
//fclose(fp2); //fclose(fp2);
fclose(fp6); fclose(fp6);
free(local_weights); free(localWeights);
//weightsLogger( local_weights, USED_WEIGHTS ); // weightsLogger( localWeights, USED_WEIGHTS );
} }
/* /*
====================================================================================================== ======================================================================================================
@ -407,9 +438,7 @@ into the given buffer. If the total length is longer than max_len,
only max_len characters will be written. only max_len characters will be written.
====================================================================================================== ======================================================================================================
*/ */
char *mkFileName(char* buffer, size_t max_len, int suffixId) { char *mkFileName(char* buffer, size_t max_len, int suffixId) {
const char * format_str = "%Y-%m-%d_%H_%M_%S"; const char * format_str = "%Y-%m-%d_%H_%M_%S";
size_t date_len; size_t date_len;
@ -422,7 +451,6 @@ char *mkFileName(char* buffer, size_t max_len, int suffixId) {
return buffer; return buffer;
} }
/* /*
====================================================================================================== ======================================================================================================
@ -432,12 +460,34 @@ Contains and returns every suffix for all existing filenames
====================================================================================================== ======================================================================================================
*/ */
char * fileSuffix ( int id ) { char * fileSuffix ( int id ) {
char * suffix[] = { "_weights_pure.txt", "_weights_used.txt", "_direct_predecessor.txt", "_ergebnisse.txt", "_localMean.txt","_testvalues.txt", "_differential_predecessor.txt" }; char * suffix[] = { "_weights_pure.txt",
"_weights_used.txt",
"_direct_predecessor.txt",
"_ergebnisse.txt",
"_localMean.txt",
"_testvalues.txt",
"_differential_predecessor.txt"
};
return suffix[id]; return suffix[id];
} }
/*
======================================================================================================
fileHeader
Contains and returns header for logfiles
======================================================================================================
*/
char * fileHeader ( int id ) {
char * header[] = { "\n=========================== Local Mean ===========================\nNo.\txPredicted\txAcutal\t\txError\n",
"\n=========================== Direct Predecessor ===========================\nNo.\txPredicted\txAcutal\t\txError\n",
"\n=========================== Differential Predecessor ===========================\nNo.\txPredicted\txAcutal\t\txError\n"
};
return header[id];
}
/* /*
====================================================================================================== ======================================================================================================
@ -448,13 +498,12 @@ Logs x,y points to svg graph
====================================================================================================== ======================================================================================================
*/ */
void weightsLogger (double *weights, int val ) {
void weightsLogger(double weights[WINDOWSIZE], int val) {
char fileName[512]; char fileName[512];
int i; unsigned i;
mkFileName(fileName, sizeof(fileName), val); mkFileName(fileName, sizeof(fileName), val);
FILE* fp = fopen(fileName, "wa"); FILE* fp = fopen(fileName, "wa");
for (i = 0; i < WINDOWSIZE; i++) { for (i = 0; i < mlData->windowSize - 1; i++) {
// for (int k = 0; k < WINDOWSIZE; k++) { // for (int k = 0; k < WINDOWSIZE; k++) {
fprintf(fp, "[%d]%lf\n", i, weights[i]); fprintf(fp, "[%d]%lf\n", i, weights[i]);
// } // }
@ -463,44 +512,48 @@ void weightsLogger(double weights[WINDOWSIZE], int val) {
fclose(fp); fclose(fp);
} }
/* /*
====================================================================================================== ======================================================================================================
bufferLogger bufferLogger
formats output of mkSvgGraph -- Please open graphResults.html to see the output-- formats output of mkSvgGraph -- Please open graphResults.html to see the output--
[0] = xActual,
[1] = xPredicted from localMean,
[2] = xPredicted from directPredecessor,
[3] = xPredicted from differentialpredecessor,
[4] = xError from localMean,
[5] = xError from directPredecessor,
[6] = xError from differentialPredecessor
====================================================================================================== ======================================================================================================
*/ */
void bufferLogger(char *buffer, point_t points[]) { void bufferLogger(char *buffer, point_t points[]) {
int i; unsigned i;
char _buffer[512] = ""; char _buffer[512] = "";
for (i = 0; i < NUMBER_OF_SAMPLES - 1; i++) { // xActual for (i = 0; i < mlData->samplesCount - 1; i++) { // xActual
sprintf(_buffer, "L %f %f\n", points[i].xVal[0], points[i].yVal[0]); sprintf(_buffer, "L %f %f\n", points[i].xVal[0], points[i].yVal[0]);
strcat(buffer, _buffer); strcat(buffer, _buffer);
} }
strcat(buffer, "\" fill=\"none\" id=\"svg_1\" stroke=\"black\" stroke-width=\"0.4px\"/>\n<path d=\"M0 0\n"); strcat(buffer, "\" fill=\"none\" id=\"svg_1\" stroke=\"black\" stroke-width=\"0.4px\"/>\n<path d=\"M0 0\n");
for (i = 0; i < NUMBER_OF_SAMPLES - 1; i++) { // xPredicted from localMean for (i = 0; i < mlData->samplesCount - 1; i++) { // xPredicted from localMean
sprintf(_buffer, "L %f %f\n", points[i].xVal[1], points[i].yVal[1]); sprintf(_buffer, "L %f %f\n", points[i].xVal[1], points[i].yVal[1]);
strcat(buffer, _buffer); strcat(buffer, _buffer);
} }
strcat(buffer, "\" fill=\"none\" id=\"svg_2\" stroke=\"green\" stroke-width=\"0.4px\"/>\n<path d=\"M0 0\n"); strcat(buffer, "\" fill=\"none\" id=\"svg_2\" stroke=\"green\" stroke-width=\"0.4px\"/>\n<path d=\"M0 0\n");
for (i = 0; i <= NUMBER_OF_SAMPLES - 1; i++) { //xPreddicted from directPredecessor for (i = 0; i <= mlData->samplesCount - 1; i++) { //xPreddicted from directPredecessor
sprintf(_buffer, "L %f %f\n", points[i].xVal[2], points[i].yVal[2]); sprintf(_buffer, "L %f %f\n", points[i].xVal[2], points[i].yVal[2]);
strcat(buffer, _buffer); strcat(buffer, _buffer);
} }
strcat(buffer, "\" fill=\"none\" id=\"svg_3\" stroke=\"blue\" stroke-width=\"0.4px\"/>\n<path d=\"M0 0\n"); strcat(buffer, "\" fill=\"none\" id=\"svg_3\" stroke=\"blue\" stroke-width=\"0.4px\"/>\n<path d=\"M0 0\n");
for (i = 0; i < NUMBER_OF_SAMPLES - 1; i++) { //xPredicted from diff Pred for (i = 0; i < mlData->samplesCount - 1; i++) { //xPredicted from diff Pred
sprintf(_buffer, "L %f %f\n", points[i].xVal[3], points[i].yVal[3]); sprintf(_buffer, "L %f %f\n", points[i].xVal[3], points[i].yVal[3]);
strcat(buffer, _buffer); strcat(buffer, _buffer);
} }
strcat(buffer, "\" fill=\"none\" id=\"svg_4\" stroke=\"red\" stroke-width=\"0.4px\"/>\n"); strcat(buffer, "\" fill=\"none\" id=\"svg_4\" stroke=\"red\" stroke-width=\"0.4px\"/>\n");
} }
/* /*
====================================================================================================== ======================================================================================================
@ -510,7 +563,6 @@ Sum of all elements in x within a defined length
====================================================================================================== ======================================================================================================
*/ */
double sum_array(double x[], int xlength) { double sum_array(double x[], int xlength) {
int i = 0; int i = 0;
double sum = 0.0; double sum = 0.0;
@ -523,7 +575,6 @@ double sum_array(double x[], int xlength) {
return sum; return sum;
} }
/* /*
====================================================================================================== ======================================================================================================
@ -533,20 +584,19 @@ returns length of new array without NAN values
====================================================================================================== ======================================================================================================
*/ */
double *popNAN(double *xError) { double *popNAN(double *xError) {
int i, counter = 1; unsigned i, counter = 1;
double tmpLength = 0.0; double tmpLength = 0.0;
double *tmp = NULL; double *tmp = NULL;
double *more_tmp = NULL; double *more_tmp = NULL;
for (i = 0; i < NUMBER_OF_SAMPLES; i++) { for ( i = 0; i < mlData->samplesCount - 1; i++ ) {
counter ++; counter ++;
more_tmp = (double *) realloc ( tmp, counter*(sizeof(double) )); more_tmp = (double *) realloc ( tmp, counter*(sizeof(double) ));
if ( !isnan(xError[i]) ) { if ( !isnan(xError[i]) ) {
tmp = more_tmp; tmp = more_tmp;
tmp[counter - 1] = xError[i]; tmp[counter - 1] = xError[i];
printf("xERROR:%lf\n", tmp[counter - 1]); //printf("xERROR:%lf\n", tmp[counter - 1]);
tmpLength++; tmpLength++;
} }
} }
@ -560,6 +610,7 @@ double *popNAN(double *xError) {
return tmp; return tmp;
} }
/* /*
====================================================================================================== ======================================================================================================
@ -569,12 +620,10 @@ returns a random double value between 0 and 1
====================================================================================================== ======================================================================================================
*/ */
double r2(void) { double r2(void) {
return((rand() % 10000) / 10000.0); return((rand() % 10000) / 10000.0);
} }
/* /*
====================================================================================================== ======================================================================================================
@ -584,13 +633,11 @@ fills a double variable with random value and returns it
====================================================================================================== ======================================================================================================
*/ */
double rndm(void) { double rndm(void) {
double rndmval = r2(); double rndmval = r2();
return rndmval; return rndmval;
} }
/* /*
====================================================================================================== ======================================================================================================
@ -600,7 +647,6 @@ parses template.svg and writes results in said template
====================================================================================================== ======================================================================================================
*/ */
void mkSvgGraph(point_t points[]) { void mkSvgGraph(point_t points[]) {
FILE *input = fopen("graphResults_template.html", "r"); FILE *input = fopen("graphResults_template.html", "r");
FILE *target = fopen("graphResults.html", "w"); FILE *target = fopen("graphResults.html", "w");
@ -625,7 +671,6 @@ void mkSvgGraph(point_t points[]) {
fprintf(target, buffer); fprintf(target, buffer);
} }
/* /*
====================================================================================================== ======================================================================================================
@ -636,7 +681,6 @@ size of given picture
====================================================================================================== ======================================================================================================
*/ */
static imagePixel_t *rdPPM(char *fileName) { static imagePixel_t *rdPPM(char *fileName) {
char buffer[16]; char buffer[16];
imagePixel_t *image; imagePixel_t *image;
@ -689,7 +733,6 @@ static imagePixel_t *rdPPM(char *fileName) {
return image; return image;
} }
/* /*
====================================================================================================== ======================================================================================================
@ -700,7 +743,6 @@ carbon copy of the source image. Build for debugging
====================================================================================================== ======================================================================================================
*/ */
void mkPpmFile(char *fileName, imagePixel_t *image) { void mkPpmFile(char *fileName, imagePixel_t *image) {
FILE* fp = fopen(fileName, "wb"); FILE* fp = fopen(fileName, "wb");
if (!fp) { if (!fp) {
@ -714,7 +756,6 @@ void mkPpmFile(char *fileName, imagePixel_t *image) {
fclose(fp); fclose(fp);
} }
/* /*
====================================================================================================== ======================================================================================================
@ -724,37 +765,54 @@ gets one of the rgb color channels and writes them to a file
====================================================================================================== ======================================================================================================
*/ */
int ppmColorChannel(FILE* fp, imagePixel_t *image, char *colorChannel, mldata_t *mlData) {
int ppmColorChannel(FILE* fp, imagePixel_t *image) {
// int length = (image->x * image->y) / 3; // int length = (image->x * image->y) / 3;
int i = 0; unsigned i = 0;
printf("colorChannel in Function: %s", colorChannel);
if (image) { if (image) {
for (i = 0; i < NUMBER_OF_SAMPLES - 1; i++) {
if (strcmp(colorChannel, "green") == 0){
for (i = 0; i < mlData->samplesCount - 1; i++) {
fprintf(fp, "%d\n", image->data[i].green); fprintf(fp, "%d\n", image->data[i].green);
printf("|");
}
} else if (strcmp(colorChannel, "red") == 0){
for (i = 0; i < mlData->samplesCount - 1; i++) {
fprintf(fp, "%d\n", image->data[i].red);
printf(".");
}
} else if (strcmp(colorChannel, "blue") == 0 ) {
for (i = 0; i < mlData->samplesCount - 1; i++ ) {
fprintf(fp, "%d\n", image->data[i].blue);
printf("/");
}
} else {
printf("Colorchannels are red, green and blue. Pick one of them!");
exit(EXIT_FAILURE);
} }
} }
fclose(fp); fclose(fp);
return NUMBER_OF_SAMPLES; return mlData->samplesCount;
} }
/* /*
====================================================================================================== ======================================================================================================
colorSamples colorSamples
reads colorChannel values from file and stores them in xSamples as well as points datatype for reads colorChannel values from file and stores them in xSamples as well as in points datatype for
creating the SVG graph creating the SVG graph
====================================================================================================== ======================================================================================================
*/ */
void colorSamples(FILE* fp) { void colorSamples ( FILE* fp, mldata_t *mlData ) {
int i = 0; int i = 0;
char buffer[NUMBER_OF_SAMPLES]; //char buffer[NUMBER_OF_SAMPLES];
char *buffer = (char *) malloc(sizeof(char) * mlData->samplesCount);
while (!feof(fp)) { while (!feof(fp)) {
if (fgets(buffer, NUMBER_OF_SAMPLES, fp) != NULL) { if (fgets(buffer, mlData->samplesCount, fp) != NULL) {
sscanf(buffer, "%lf", &xSamples[i]); sscanf(buffer, "%lf", &xSamples[i]);
//printf("%lf\n", xSamples[i] ); //printf("%lf\n", xSamples[i] );
points[i].yVal[0] = xSamples[i]; points[i].yVal[0] = xSamples[i];
@ -765,7 +823,6 @@ void colorSamples(FILE* fp) {
fclose(fp); fclose(fp);
} }
/* /*
====================================================================================================== ======================================================================================================
@ -775,7 +832,6 @@ returns mean value of given input, which has a length of WINDOWSIZE
====================================================================================================== ======================================================================================================
*/ */
double windowXMean(int _arraylength, int xCount) { double windowXMean(int _arraylength, int xCount) {
double sum = 0.0; double sum = 0.0;
double *ptr; double *ptr;
@ -786,4 +842,45 @@ double windowXMean(int _arraylength, int xCount) {
return sum / (double)_arraylength; return sum / (double)_arraylength;
} }
/*
======================================================================================================
usage
used in conjunction with the args parser. Returns help section of "-h"
======================================================================================================
*/
void usage ( void ) {
printf("Usage: lms [POSIX style options] -i file ...\n");
printf("POSIX options:\n");
printf("\t-h\t\t\tDisplay this information.\n");
printf("\t-i <filename>\t\tName of inputfile. Must be PPM image.\n");
printf("\t-n <digit>\t\tAmount of input data used.\n");
printf("\t-c <color>\t\tUse this color channel from inputfile.\n");
printf("\t-w <digit>\t\tCount of used weights (windowSize).\n");
printf("\t-l <digit>\t\tLearnrate, 0 < learnrate < 1.\n");
printf("\t-s <digit>\t\tDigit for random seed generator.\n\t\t\t\tSame Digits produce same random values. Default is srand by time.");
printf("\n\n");
printf("lms compares prediction methods of least mean square filters.\nBy default it reads ppm file format and return logfiles as well\nas an svg graphs as an output of said least mean square methods.\n\nExample:\n\tlms -i myimage.ppm -w 3 -c green -s 5\n");
exit(8);
}
/*
======================================================================================================
init_mldata_t
Contains meachine learning data
======================================================================================================
*/
mldata_t * init_mldata_t(unsigned windowSize, unsigned samplesCount, double learnrate) {
mlData = (mldata_t *) malloc( sizeof(mldata_t) );
mlData->windowSize = windowSize;
mlData->samplesCount = samplesCount;
mlData->learnrate = learnrate;
mlData->weights = (double *) malloc ( sizeof(double) * windowSize + 1 );
return mlData;
}

View File

@ -0,0 +1,32 @@
## Installation
This is a carbon copy of the ANSI C version. Sole purpose of its existence is to be compiled under Visual Studio.
If you do not use VS, pick the ANSI C version __../src/ansi_c__implementation__.
## Features
This little piece of code compares 3 different implementations of a least mean square filter.
+ local mean
+ direct predecessor
+ differential predecessor
Greyscale PPM files can be used for input at this iteration. Output will be generated as .txt files with predicted value generated by the filter and its error value as well as given actual value from the PPM file. Furthermore there is an output as an svg graph to compare the implementatiosn on a visual level. These graphical results are build from __graphResults_template.html__ which creates the actual output to __graphResults.html__. Open this file to see the results.
You can hide graphs by clicking on its name for better visibility.
Use `$ ./lms -h` for help.
### Usage
There are a bunch of options you can predefine but do not have to. The only parameter needed is __-i__ which is the inputfile.
| Parameter | Description | StdVal |
|----------:|:-----------------------------:|:-------|
| -i | The inputfile, has to be PPM | none |
| -n | Amount of input data used | 500 |
| -w | Size of M (window) | 5 |
| -c | Choose RGB color channel, green has least noise. | green |
| -l | Learnrate of machine learning | 0.8 |
| -s | Seed randomizing weights. Choose for repoducability. | time(NULL)|

View File

@ -2,10 +2,11 @@
<html> <html>
<head> <head>
NLMSvariants | Graphical Output || NLMSvariants | Graphical Output || click font to hide graph
<font id="1" color="blue" onclick="clicksvg(this)">Eingangswert</font> | <h2><font face="arial" id="1" color="black" onclick="clicksvg(this)">Image Samples</font> |
<font id="2" color="red" onclick="clicksvg(this)">direkter Vorgaenger</font> | <font face="arial" id="2" color="green" onclick="clicksvg(this)">Local Mean</font> |
<font id="3" color="green" onclick="clicksvg(this)">letzter Mittelwert</font> <font face="arial" id="3" color="blue" onclick="clicksvg(this)">Direct predecessor</font> |
<font face="arial" id="4" color="red" onclick="clicksvg(this)">Differential predecessor</font></h2>
<script> <script>
function clicksvg(e){ function clicksvg(e){
id = e.id id = e.id
@ -18,7 +19,7 @@
} }
</script> </script>
</head> </head>
<body> <body bgcolor="#efefef">
<svg height="1200" viewBox="100 50 400 -400" width="3000" version="1.1" <svg height="1200" viewBox="100 50 400 -400" width="3000" version="1.1"
xmlns="http://www.w3.org/2000/svg"> xmlns="http://www.w3.org/2000/svg">
<desc>NLMSvariants output graph <desc>NLMSvariants output graph
@ -32,31 +33,19 @@
<path d="M 100 0 L 0 0 0 100" fill="none" stroke="gray" stroke-width="1"></path> <path d="M 100 0 L 0 0 0 100" fill="none" stroke="gray" stroke-width="1"></path>
</pattern> </pattern>
</defs> </defs>
<rect fill="white" height="1200" width="3000" y="0"></rect> <rect fill="white" height="800" width="3000" y="0"></rect>
<rect fill="url(#grid10)" height="1200" width="3000" y="0"></rect> <rect fill="url(#grid10)" height="800" width="3000" y="0"></rect>
<g transform="translate(0,0) scale(1, 1)"> <g transform="translate(0,0) scale(1, 1)">
<line class="l1 s-black " stroke="black" x1="-200" x2="3000" y1="400" y2="400"></line> <line class="l1 s-black " stroke="black" x1="-200" x2="3000" y1="400" y2="400"></line>
<line class="l1 s-black " stroke="black" x1="200" x2="200" y1="-200" y2="1200"></line> <line class="l1 s-black " stroke="black" x1="50" x2="50" y1="-200" y2="800"></line>
</g> </g>
<g transform="translate(200, 400) scale(1,-1)"> <g transform="translate(50, 400) scale(1,-1)">
<path d="M0 0 <path d="M0 0
<text class="t36 t-mid bold f-black" x="50" y="50">+ +</text> <text class="t36 t-mid bold f-black" x="40" y="40">+ +</text>
<text class="t36 t-mid bold f-black" x="-50" y="50">- +</text> <text class="t36 t-mid bold f-black" x="-40" y="40">- +</text>
<text class="t36 t-mid bold f-black" x="50" y="-50">+ -</text> <text class="t36 t-mid bold f-black" x="40" y="-40">+ -</text>
<text class="t36 t-mid bold f-black" x="-50" y="-50">- -</text> <text class="t36 t-mid bold f-black" x="-40" y="-40">- -</text>
</g> </g>
</svg> </svg>
<table width = "100%" border = 1>
<tr align = "top">
<td colspan = "2" bgcolor = "#fefefe">
<h1>
<font color="blue">Eingangswert</font> |
<font color="red">direkter Vorgaenger</font> |
<font color="green">letzter Mittelwert</font>
</h1>
</td>
</tr>
</body> </body>
<html> <html>

View File

@ -0,0 +1,28 @@
/* *svg graph building* */
typedef struct {
double xVal[7];
double yVal[7];
}point_t;
/* *ppm read, copy, write* */
typedef struct {
unsigned char red, green, blue;
}colorChannel_t;
typedef struct {
int x, y;
colorChannel_t *data;
}imagePixel_t;
enum fileSuffix_t{ // used in conjunction with mkFileName()
PURE_WEIGHTS,
USED_WEIGHTS,
DIRECT_PREDECESSOR,
RESULTS,
LOCAL_MEAN,
TEST_VALUES,
DIFFERENTIAL_PREDECESSOR
};