blob: 667f174bb31d784193d5b82856655fac766e0266 [file] [log] [blame]
/*---------------------------------------------------------------------------*
* imeld_rd.c *
* *
* Copyright 2007, 2008 Nuance Communciations, Inc. *
* *
* Licensed under the Apache License, Version 2.0 (the 'License'); *
* you may not use this file except in compliance with the License. *
* *
* You may obtain a copy of the License at *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, software *
* distributed under the License is distributed on an 'AS IS' BASIS, *
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
* See the License for the specific language governing permissions and *
* limitations under the License. *
* *
*---------------------------------------------------------------------------*/
#ifndef _RTT
#include <stdio.h>
#endif
#include <stdlib.h>
#include <math.h>
#include <string.h>
#ifdef unix
#include <limits.h>
#endif
#include <assert.h>
#include "prelib.h"
#ifndef _RTT
#include "duk_io.h"
#endif
#include "pendian.h"
#include "portable.h"
static const char imeld_rd[] = "$Id: imeld_rd.c,v 1.5.6.7 2007/10/15 18:06:24 dahan Exp $";
/* function prototypes */
imeldata **create_fixed_matrix(int dimen);
covdata **create_matrix(int dimen);
void delete_matrix(covdata **matrix, int dimen);
void delete_fixed_matrix(imeldata **matrix, int dimen);
int scale_matrix_for_fixedpoint(imeldata **fixmat, covdata **matrix,int dimen);
int invert_matrix(covdata **mat, covdata **inv, int dim);
void create_linear_transform(preprocessed *prep, int matdim,
int with_offset)
{
ASSERT(prep);
ASSERT(matdim > 0);
prep->dim = matdim;
prep->matrix = create_fixed_matrix(matdim);
if (with_offset)
prep->offset = (imeldata *) CALLOC(matdim,
sizeof(imeldata), "clib.offset");
prep->imelda = create_matrix(matdim);
prep->invmat = create_fixed_matrix(matdim);
prep->inverse = create_matrix(matdim);
return;
}
void free_linear_transform(preprocessed *prep)
{
ASSERT(prep);
ASSERT(prep->matrix);
delete_fixed_matrix(prep->matrix, prep->dim);
if (prep->offset)
FREE(prep->offset);
prep->matrix = NULL;
prep->offset = NULL;
ASSERT(prep->imelda);
delete_matrix(prep->imelda, prep->dim);
prep->imelda = NULL;
ASSERT(prep->invmat);
ASSERT(prep->inverse);
delete_fixed_matrix(prep->invmat, prep->dim);
delete_matrix(prep->inverse, prep->dim);
prep->invmat = NULL;
prep->inverse = NULL;
return;
}
#ifndef _RTT
int init_newton_transform(preprocessed *prep, float reqscale,
char *filename, int dimen)
/*
*/
{
int ii, jj;
unsigned short matdim;
double scale, onerow[MAX_DIMEN];
PFile* dfpt;
long foffset;
double xfp;
/* Open file
*/
ASSERT(prep);
ASSERT(filename);
dfpt = file_must_open(NULL, filename, ("rb"), ESR_TRUE);
prep->post_proc |= LIN_TRAN;
prep->use_dim = dimen;
pfread(&matdim, sizeof(short), 1, dfpt);
if (matdim > MAX_DIMEN)
SERVICE_ERROR(BAD_IMELDA);
create_linear_transform(prep, matdim, 1);
pfread(&scale, sizeof(double), 1, dfpt);
if (reqscale != 0) scale = reqscale;
#if DEBUG
PLogMessage("L: LDA Suggested scale is %.1f\n", scale);
#endif
if (!prep->dim) prep->dim = matdim;
else if (prep->dim != matdim)
{
log_report("Data (%d) and LDA (%d) dimensions don't match\n",
prep->dim, matdim);
SERVICE_ERROR(BAD_IMELDA);
}
/* Eigenvalues, ignored
*/
pfread(onerow, sizeof(double), matdim, dfpt);
/* Translation Vector
*/
pfread(onerow, sizeof(double), matdim, dfpt);
for (ii = 0; ii < matdim; ii++)
{
xfp = scale * (onerow[ii] - UTB_MEAN) + UTB_MEAN;
if (xfp > 0.0)
xfp += 0.5;
else if (xfp < 0.0)
xfp -= 0.5;
prep->offset[ii] = (imeldata) xfp;
}
/* The imelda matrix
*/
for (ii = 0; ii < matdim; ii++)
{
pfread(onerow, sizeof(double), matdim, dfpt);
for (jj = 0; jj < matdim; jj++)
prep->imelda[ii][jj] = (covdata)(scale * onerow[jj]);
}
prep->imel_shift = scale_matrix_for_fixedpoint(prep->matrix,
prep->imelda, matdim);
/* The inverse imelda matrix
*/
foffset = pftell(dfpt);
pfread(onerow, sizeof(double), matdim, dfpt);
if (pfeof(dfpt) != 0)
{
#ifdef SREC_ENGINE_VERBOSE_LOGGING
PLogMessage("W: Inverting imelda matrix");
#endif
invert_matrix(prep->imelda, prep->inverse, prep->dim);
}
else
{
pfseek(dfpt, foffset, SEEK_SET);
for (ii = 0; ii < matdim; ii++)
{
pfread(onerow, sizeof(double), matdim, dfpt);
for (jj = 0; jj < matdim; jj++)
prep->inverse[ii][jj] = (covdata)(onerow[jj] / scale);
}
}
prep->inv_shift = scale_matrix_for_fixedpoint(prep->invmat,
prep->inverse, matdim);
pfclose(dfpt);
return (0);
}
#endif