Coverage Report

Created: 2023-12-08 06:53

/src/freeimage-svn/FreeImage/trunk/Source/LibOpenJPEG/invert.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2008, Jerome Fimes, Communications & Systemes <jerome.fimes@c-s.fr>
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright
11
 *    notice, this list of conditions and the following disclaimer in the
12
 *    documentation and/or other materials provided with the distribution.
13
 *
14
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
15
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24
 * POSSIBILITY OF SUCH DAMAGE.
25
 */
26
27
#include "opj_includes.h"
28
29
/** 
30
 * LUP decomposition
31
 */
32
static OPJ_BOOL opj_lupDecompose(OPJ_FLOAT32 * matrix,
33
                                 OPJ_UINT32 * permutations, 
34
                                 OPJ_FLOAT32 * p_swap_area,
35
                                 OPJ_UINT32 nb_compo);
36
/** 
37
 * LUP solving
38
 */
39
static void opj_lupSolve(OPJ_FLOAT32 * pResult, 
40
                         OPJ_FLOAT32* pMatrix, 
41
                         OPJ_FLOAT32* pVector, 
42
                         OPJ_UINT32* pPermutations, 
43
                         OPJ_UINT32 nb_compo,
44
                         OPJ_FLOAT32 * p_intermediate_data);
45
46
/** 
47
 *LUP inversion (call with the result of lupDecompose)
48
 */
49
static void opj_lupInvert ( OPJ_FLOAT32 * pSrcMatrix,
50
                            OPJ_FLOAT32 * pDestMatrix,
51
                            OPJ_UINT32 nb_compo,
52
                            OPJ_UINT32 * pPermutations,
53
                            OPJ_FLOAT32 * p_src_temp,
54
                            OPJ_FLOAT32 * p_dest_temp,
55
                            OPJ_FLOAT32 * p_swap_area);
56
57
/*
58
==========================================================
59
   Matric inversion interface
60
==========================================================
61
*/
62
/**
63
 * Matrix inversion.
64
 */
65
OPJ_BOOL opj_matrix_inversion_f(OPJ_FLOAT32 * pSrcMatrix,
66
                                OPJ_FLOAT32 * pDestMatrix, 
67
                                OPJ_UINT32 nb_compo)
68
0
{
69
0
  OPJ_BYTE * l_data = 00;
70
0
  OPJ_UINT32 l_permutation_size = nb_compo * (OPJ_UINT32)sizeof(OPJ_UINT32);
71
0
  OPJ_UINT32 l_swap_size = nb_compo * (OPJ_UINT32)sizeof(OPJ_FLOAT32);
72
0
  OPJ_UINT32 l_total_size = l_permutation_size + 3 * l_swap_size;
73
0
  OPJ_UINT32 * lPermutations = 00;
74
0
  OPJ_FLOAT32 * l_double_data = 00;
75
76
0
  l_data = (OPJ_BYTE *) opj_malloc(l_total_size);
77
0
  if (l_data == 0) {
78
0
    return OPJ_FALSE;
79
0
  }
80
0
  lPermutations = (OPJ_UINT32 *) l_data;
81
0
  l_double_data = (OPJ_FLOAT32 *) (l_data + l_permutation_size);
82
0
  memset(lPermutations,0,l_permutation_size);
83
84
0
  if(! opj_lupDecompose(pSrcMatrix,lPermutations,l_double_data,nb_compo)) {
85
0
    opj_free(l_data);
86
0
    return OPJ_FALSE;
87
0
  }
88
  
89
0
    opj_lupInvert(pSrcMatrix,pDestMatrix,nb_compo,lPermutations,l_double_data,l_double_data + nb_compo,l_double_data + 2*nb_compo);
90
0
  opj_free(l_data);
91
  
92
0
    return OPJ_TRUE;
93
0
}
94
95
96
/*
97
==========================================================
98
   Local functions
99
==========================================================
100
*/
101
OPJ_BOOL opj_lupDecompose(OPJ_FLOAT32 * matrix,OPJ_UINT32 * permutations, 
102
                          OPJ_FLOAT32 * p_swap_area,
103
                          OPJ_UINT32 nb_compo) 
104
0
{
105
0
  OPJ_UINT32 * tmpPermutations = permutations;
106
0
  OPJ_UINT32 * dstPermutations;
107
0
  OPJ_UINT32 k2=0,t;
108
0
  OPJ_FLOAT32 temp;
109
0
  OPJ_UINT32 i,j,k;
110
0
  OPJ_FLOAT32 p;
111
0
  OPJ_UINT32 lLastColum = nb_compo - 1;
112
0
  OPJ_UINT32 lSwapSize = nb_compo * (OPJ_UINT32)sizeof(OPJ_FLOAT32);
113
0
  OPJ_FLOAT32 * lTmpMatrix = matrix;
114
0
  OPJ_FLOAT32 * lColumnMatrix,* lDestMatrix;
115
0
  OPJ_UINT32 offset = 1;
116
0
  OPJ_UINT32 lStride = nb_compo-1;
117
118
  /*initialize permutations */
119
0
  for (i = 0; i < nb_compo; ++i) 
120
0
  {
121
0
      *tmpPermutations++ = i;
122
0
  }
123
  /* now make a pivot with colum switch */
124
0
  tmpPermutations = permutations;
125
0
  for (k = 0; k < lLastColum; ++k) {
126
0
    p = 0.0;
127
128
    /* take the middle element */
129
0
    lColumnMatrix = lTmpMatrix + k;
130
    
131
    /* make permutation with the biggest value in the column */
132
0
        for (i = k; i < nb_compo; ++i) {
133
0
      temp = ((*lColumnMatrix > 0) ? *lColumnMatrix : -(*lColumnMatrix));
134
0
        if (temp > p) {
135
0
          p = temp;
136
0
          k2 = i;
137
0
        }
138
      /* next line */
139
0
      lColumnMatrix += nb_compo;
140
0
      }
141
142
      /* a whole rest of 0 -> non singular */
143
0
      if (p == 0.0) {
144
0
        return OPJ_FALSE;
145
0
    }
146
147
    /* should we permute ? */
148
0
    if (k2 != k) {
149
      /*exchange of line */
150
        /* k2 > k */
151
0
      dstPermutations = tmpPermutations + k2 - k;
152
      /* swap indices */
153
0
      t = *tmpPermutations;
154
0
        *tmpPermutations = *dstPermutations;
155
0
        *dstPermutations = t;
156
157
      /* and swap entire line. */
158
0
      lColumnMatrix = lTmpMatrix + (k2 - k) * nb_compo;
159
0
      memcpy(p_swap_area,lColumnMatrix,lSwapSize);
160
0
      memcpy(lColumnMatrix,lTmpMatrix,lSwapSize);
161
0
      memcpy(lTmpMatrix,p_swap_area,lSwapSize);
162
0
    }
163
164
    /* now update data in the rest of the line and line after */
165
0
    lDestMatrix = lTmpMatrix + k;
166
0
    lColumnMatrix = lDestMatrix + nb_compo;
167
    /* take the middle element */
168
0
    temp = *(lDestMatrix++);
169
170
    /* now compute up data (i.e. coeff up of the diagonal). */
171
0
      for (i = offset; i < nb_compo; ++i)  {
172
      /*lColumnMatrix; */
173
      /* divide the lower column elements by the diagonal value */
174
175
      /* matrix[i][k] /= matrix[k][k]; */
176
        /* p = matrix[i][k] */
177
0
      p = *lColumnMatrix / temp;
178
0
      *(lColumnMatrix++) = p;
179
        
180
0
            for (j = /* k + 1 */ offset; j < nb_compo; ++j) {
181
        /* matrix[i][j] -= matrix[i][k] * matrix[k][j]; */
182
0
          *(lColumnMatrix++) -= p * (*(lDestMatrix++));
183
0
      }
184
      /* come back to the k+1th element */
185
0
      lDestMatrix -= lStride;
186
      /* go to kth element of the next line */
187
0
      lColumnMatrix += k;
188
0
      }
189
190
    /* offset is now k+2 */
191
0
    ++offset;
192
    /* 1 element less for stride */
193
0
    --lStride;
194
    /* next line */
195
0
    lTmpMatrix+=nb_compo;
196
    /* next permutation element */
197
0
    ++tmpPermutations;
198
0
  }
199
0
    return OPJ_TRUE;
200
0
}
201
      
202
void opj_lupSolve (OPJ_FLOAT32 * pResult, 
203
                   OPJ_FLOAT32 * pMatrix, 
204
                   OPJ_FLOAT32 * pVector, 
205
                   OPJ_UINT32* pPermutations, 
206
                   OPJ_UINT32 nb_compo,OPJ_FLOAT32 * p_intermediate_data) 
207
0
{
208
0
  OPJ_INT32 k;
209
0
    OPJ_UINT32 i,j;
210
0
  OPJ_FLOAT32 sum;
211
0
  OPJ_FLOAT32 u;
212
0
    OPJ_UINT32 lStride = nb_compo+1;
213
0
  OPJ_FLOAT32 * lCurrentPtr;
214
0
  OPJ_FLOAT32 * lIntermediatePtr;
215
0
  OPJ_FLOAT32 * lDestPtr;
216
0
  OPJ_FLOAT32 * lTmpMatrix;
217
0
  OPJ_FLOAT32 * lLineMatrix = pMatrix;
218
0
  OPJ_FLOAT32 * lBeginPtr = pResult + nb_compo - 1;
219
0
  OPJ_FLOAT32 * lGeneratedData;
220
0
  OPJ_UINT32 * lCurrentPermutationPtr = pPermutations;
221
222
  
223
0
  lIntermediatePtr = p_intermediate_data;
224
0
  lGeneratedData = p_intermediate_data + nb_compo - 1;
225
  
226
0
    for (i = 0; i < nb_compo; ++i) {
227
0
        sum = 0.0;
228
0
    lCurrentPtr = p_intermediate_data;
229
0
    lTmpMatrix = lLineMatrix;
230
0
        for (j = 1; j <= i; ++j) 
231
0
    {
232
      /* sum += matrix[i][j-1] * y[j-1]; */
233
0
          sum += (*(lTmpMatrix++)) * (*(lCurrentPtr++));
234
0
        }
235
    /*y[i] = pVector[pPermutations[i]] - sum; */
236
0
        *(lIntermediatePtr++) = pVector[*(lCurrentPermutationPtr++)] - sum;
237
0
    lLineMatrix += nb_compo;
238
0
  }
239
240
  /* we take the last point of the matrix */
241
0
  lLineMatrix = pMatrix + nb_compo*nb_compo - 1;
242
243
  /* and we take after the last point of the destination vector */
244
0
  lDestPtr = pResult + nb_compo;
245
246
247
0
    assert(nb_compo != 0);
248
0
  for (k = (OPJ_INT32)nb_compo - 1; k != -1 ; --k) {
249
0
    sum = 0.0;
250
0
    lTmpMatrix = lLineMatrix;
251
0
        u = *(lTmpMatrix++);
252
0
    lCurrentPtr = lDestPtr--;
253
0
        for (j = (OPJ_UINT32)(k + 1); j < nb_compo; ++j) {
254
      /* sum += matrix[k][j] * x[j] */
255
0
          sum += (*(lTmpMatrix++)) * (*(lCurrentPtr++));
256
0
    }
257
    /*x[k] = (y[k] - sum) / u; */
258
0
        *(lBeginPtr--) = (*(lGeneratedData--) - sum) / u;
259
0
    lLineMatrix -= lStride;
260
0
  }
261
0
}
262
    
263
264
void opj_lupInvert (OPJ_FLOAT32 * pSrcMatrix,
265
                    OPJ_FLOAT32 * pDestMatrix,
266
                    OPJ_UINT32 nb_compo,
267
                    OPJ_UINT32 * pPermutations,
268
                    OPJ_FLOAT32 * p_src_temp,
269
                    OPJ_FLOAT32 * p_dest_temp,
270
                    OPJ_FLOAT32 * p_swap_area )
271
0
{
272
0
  OPJ_UINT32 j,i;
273
0
  OPJ_FLOAT32 * lCurrentPtr;
274
0
  OPJ_FLOAT32 * lLineMatrix = pDestMatrix;
275
0
  OPJ_UINT32 lSwapSize = nb_compo * (OPJ_UINT32)sizeof(OPJ_FLOAT32);
276
277
0
  for (j = 0; j < nb_compo; ++j) {
278
0
    lCurrentPtr = lLineMatrix++;
279
0
        memset(p_src_temp,0,lSwapSize);
280
0
      p_src_temp[j] = 1.0;
281
0
    opj_lupSolve(p_dest_temp,pSrcMatrix,p_src_temp, pPermutations, nb_compo , p_swap_area);
282
283
0
    for (i = 0; i < nb_compo; ++i) {
284
0
        *(lCurrentPtr) = p_dest_temp[i];
285
0
      lCurrentPtr+=nb_compo;
286
0
      }
287
0
    }
288
0
}
289