1/*---------------------------------------------------------------------------*
2 *  imeld_rd.c  *
3 *                                                                           *
4 *  Copyright 2007, 2008 Nuance Communciations, Inc.                               *
5 *                                                                           *
6 *  Licensed under the Apache License, Version 2.0 (the 'License');          *
7 *  you may not use this file except in compliance with the License.         *
8 *                                                                           *
9 *  You may obtain a copy of the License at                                  *
10 *      http://www.apache.org/licenses/LICENSE-2.0                           *
11 *                                                                           *
12 *  Unless required by applicable law or agreed to in writing, software      *
13 *  distributed under the License is distributed on an 'AS IS' BASIS,        *
14 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
15 *  See the License for the specific language governing permissions and      *
16 *  limitations under the License.                                           *
17 *                                                                           *
18 *---------------------------------------------------------------------------*/
19
20
21#ifndef _RTT
22#include <stdio.h>
23#endif
24#include <stdlib.h>
25#include <math.h>
26#include <string.h>
27#ifdef unix
28#include <limits.h>
29#endif
30#include <assert.h>
31
32#include "prelib.h"
33#ifndef _RTT
34#include "duk_io.h"
35#endif
36
37#include "pendian.h"
38#include "portable.h"
39
40static const char imeld_rd[] = "$Id: imeld_rd.c,v 1.5.6.7 2007/10/15 18:06:24 dahan Exp $";
41
42/* function prototypes */
43
44imeldata **create_fixed_matrix(int dimen);
45covdata **create_matrix(int dimen);
46void delete_matrix(covdata **matrix, int dimen);
47void delete_fixed_matrix(imeldata **matrix, int dimen);
48int scale_matrix_for_fixedpoint(imeldata **fixmat, covdata **matrix,int dimen);
49int     invert_matrix(covdata **mat, covdata **inv, int dim);
50
51
52void create_linear_transform(preprocessed *prep, int matdim,
53                             int with_offset)
54{
55  ASSERT(prep);
56  ASSERT(matdim > 0);
57  prep->dim = matdim;
58  prep->matrix = create_fixed_matrix(matdim);
59  if (with_offset)
60    prep->offset = (imeldata *) CALLOC(matdim,
61                   sizeof(imeldata), "clib.offset");
62  prep->imelda = create_matrix(matdim);
63  prep->invmat = create_fixed_matrix(matdim);
64  prep->inverse = create_matrix(matdim);
65  return;
66}
67
68void free_linear_transform(preprocessed *prep)
69{
70  ASSERT(prep);
71  ASSERT(prep->matrix);
72  delete_fixed_matrix(prep->matrix, prep->dim);
73  if (prep->offset)
74    FREE(prep->offset);
75  prep->matrix = NULL;
76  prep->offset = NULL;
77  ASSERT(prep->imelda);
78  delete_matrix(prep->imelda, prep->dim);
79  prep->imelda = NULL;
80  ASSERT(prep->invmat);
81  ASSERT(prep->inverse);
82  delete_fixed_matrix(prep->invmat, prep->dim);
83  delete_matrix(prep->inverse, prep->dim);
84  prep->invmat = NULL;
85  prep->inverse = NULL;
86  return;
87}
88
89#ifndef _RTT
90int init_newton_transform(preprocessed *prep, float reqscale,
91                          char *filename, int dimen)
92/*
93*/
94{
95  int  ii, jj;
96  unsigned short matdim;
97  double scale, onerow[MAX_DIMEN];
98  PFile* dfpt;
99  long foffset;
100  double xfp;
101  /* Open file
102  */
103  ASSERT(prep);
104  ASSERT(filename);
105  dfpt = file_must_open(NULL, filename, ("rb"), ESR_TRUE);
106  prep->post_proc |= LIN_TRAN;
107  prep->use_dim = dimen;
108  pfread(&matdim, sizeof(short), 1, dfpt);
109  if (matdim > MAX_DIMEN)
110    SERVICE_ERROR(BAD_IMELDA);
111
112  create_linear_transform(prep, matdim, 1);
113  pfread(&scale, sizeof(double), 1, dfpt);
114
115  if (reqscale != 0) scale = reqscale;
116#if DEBUG
117  PLogMessage("L: LDA Suggested scale is %.1f\n", scale);
118#endif
119  if (!prep->dim) prep->dim = matdim;
120  else if (prep->dim != matdim)
121  {
122    log_report("Data (%d) and LDA (%d) dimensions don't match\n",
123               prep->dim, matdim);
124    SERVICE_ERROR(BAD_IMELDA);
125  }
126
127  /*  Eigenvalues, ignored
128  */
129  pfread(onerow, sizeof(double), matdim, dfpt);
130
131  /*  Translation Vector
132  */
133  pfread(onerow, sizeof(double), matdim, dfpt);
134  for (ii = 0; ii < matdim; ii++)
135  {
136    xfp = scale * (onerow[ii] - UTB_MEAN) + UTB_MEAN;
137    if (xfp > 0.0)
138      xfp += 0.5;
139    else if (xfp < 0.0)
140      xfp -= 0.5;
141
142    prep->offset[ii] = (imeldata) xfp;
143  }
144
145  /*  The imelda matrix
146  */
147  for (ii = 0; ii < matdim; ii++)
148  {
149    pfread(onerow, sizeof(double), matdim, dfpt);
150    for (jj = 0; jj < matdim; jj++)
151      prep->imelda[ii][jj] = (covdata)(scale * onerow[jj]);
152  }
153
154  prep->imel_shift = scale_matrix_for_fixedpoint(prep->matrix,
155                     prep->imelda, matdim);
156
157  /* The inverse imelda matrix
158   */
159  foffset = pftell(dfpt);
160  pfread(onerow, sizeof(double), matdim, dfpt);
161
162  if (pfeof(dfpt) != 0)
163  {
164#ifdef SREC_ENGINE_VERBOSE_LOGGING
165    PLogMessage("W: Inverting imelda matrix");
166#endif
167    invert_matrix(prep->imelda, prep->inverse, prep->dim);
168  }
169  else
170  {
171    pfseek(dfpt, foffset, SEEK_SET);
172
173    for (ii = 0; ii < matdim; ii++)
174    {
175      pfread(onerow, sizeof(double), matdim, dfpt);
176      for (jj = 0; jj < matdim; jj++)
177        prep->inverse[ii][jj] = (covdata)(onerow[jj] / scale);
178    }
179  }
180
181  prep->inv_shift = scale_matrix_for_fixedpoint(prep->invmat,
182                    prep->inverse, matdim);
183
184  pfclose(dfpt);
185  return (0);
186}
187#endif
188