Thu, 15 Jan 2015 15:59:08 +0100
Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
michael@0 | 1 | /*********************************************************************** |
michael@0 | 2 | Copyright (c) 2006-2011, Skype Limited. All rights reserved. |
michael@0 | 3 | Redistribution and use in source and binary forms, with or without |
michael@0 | 4 | modification, are permitted provided that the following conditions |
michael@0 | 5 | are met: |
michael@0 | 6 | - Redistributions of source code must retain the above copyright notice, |
michael@0 | 7 | this list of conditions and the following disclaimer. |
michael@0 | 8 | - Redistributions in binary form must reproduce the above copyright |
michael@0 | 9 | notice, this list of conditions and the following disclaimer in the |
michael@0 | 10 | documentation and/or other materials provided with the distribution. |
michael@0 | 11 | - Neither the name of Internet Society, IETF or IETF Trust, nor the |
michael@0 | 12 | names of specific contributors, may be used to endorse or promote |
michael@0 | 13 | products derived from this software without specific prior written |
michael@0 | 14 | permission. |
michael@0 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
michael@0 | 16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
michael@0 | 17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
michael@0 | 18 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
michael@0 | 19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
michael@0 | 20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
michael@0 | 21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
michael@0 | 22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
michael@0 | 23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
michael@0 | 24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
michael@0 | 25 | POSSIBILITY OF SUCH DAMAGE. |
michael@0 | 26 | ***********************************************************************/ |
michael@0 | 27 | |
michael@0 | 28 | #ifdef HAVE_CONFIG_H |
michael@0 | 29 | #include "config.h" |
michael@0 | 30 | #endif |
michael@0 | 31 | |
michael@0 | 32 | #include "main_FIX.h" |
michael@0 | 33 | #include "stack_alloc.h" |
michael@0 | 34 | #include "tuning_parameters.h" |
michael@0 | 35 | |
michael@0 | 36 | /*****************************/ |
michael@0 | 37 | /* Internal function headers */ |
michael@0 | 38 | /*****************************/ |
michael@0 | 39 | |
michael@0 | 40 | typedef struct { |
michael@0 | 41 | opus_int32 Q36_part; |
michael@0 | 42 | opus_int32 Q48_part; |
michael@0 | 43 | } inv_D_t; |
michael@0 | 44 | |
michael@0 | 45 | /* Factorize square matrix A into LDL form */ |
michael@0 | 46 | static OPUS_INLINE void silk_LDL_factorize_FIX( |
michael@0 | 47 | opus_int32 *A, /* I/O Pointer to Symetric Square Matrix */ |
michael@0 | 48 | opus_int M, /* I Size of Matrix */ |
michael@0 | 49 | opus_int32 *L_Q16, /* I/O Pointer to Square Upper triangular Matrix */ |
michael@0 | 50 | inv_D_t *inv_D /* I/O Pointer to vector holding inverted diagonal elements of D */ |
michael@0 | 51 | ); |
michael@0 | 52 | |
michael@0 | 53 | /* Solve Lx = b, when L is lower triangular and has ones on the diagonal */ |
michael@0 | 54 | static OPUS_INLINE void silk_LS_SolveFirst_FIX( |
michael@0 | 55 | const opus_int32 *L_Q16, /* I Pointer to Lower Triangular Matrix */ |
michael@0 | 56 | opus_int M, /* I Dim of Matrix equation */ |
michael@0 | 57 | const opus_int32 *b, /* I b Vector */ |
michael@0 | 58 | opus_int32 *x_Q16 /* O x Vector */ |
michael@0 | 59 | ); |
michael@0 | 60 | |
michael@0 | 61 | /* Solve L^t*x = b, where L is lower triangular with ones on the diagonal */ |
michael@0 | 62 | static OPUS_INLINE void silk_LS_SolveLast_FIX( |
michael@0 | 63 | const opus_int32 *L_Q16, /* I Pointer to Lower Triangular Matrix */ |
michael@0 | 64 | const opus_int M, /* I Dim of Matrix equation */ |
michael@0 | 65 | const opus_int32 *b, /* I b Vector */ |
michael@0 | 66 | opus_int32 *x_Q16 /* O x Vector */ |
michael@0 | 67 | ); |
michael@0 | 68 | |
michael@0 | 69 | static OPUS_INLINE void silk_LS_divide_Q16_FIX( |
michael@0 | 70 | opus_int32 T[], /* I/O Numenator vector */ |
michael@0 | 71 | inv_D_t *inv_D, /* I 1 / D vector */ |
michael@0 | 72 | opus_int M /* I dimension */ |
michael@0 | 73 | ); |
michael@0 | 74 | |
michael@0 | 75 | /* Solves Ax = b, assuming A is symmetric */ |
michael@0 | 76 | void silk_solve_LDL_FIX( |
michael@0 | 77 | opus_int32 *A, /* I Pointer to symetric square matrix A */ |
michael@0 | 78 | opus_int M, /* I Size of matrix */ |
michael@0 | 79 | const opus_int32 *b, /* I Pointer to b vector */ |
michael@0 | 80 | opus_int32 *x_Q16 /* O Pointer to x solution vector */ |
michael@0 | 81 | ) |
michael@0 | 82 | { |
michael@0 | 83 | VARDECL( opus_int32, L_Q16 ); |
michael@0 | 84 | opus_int32 Y[ MAX_MATRIX_SIZE ]; |
michael@0 | 85 | inv_D_t inv_D[ MAX_MATRIX_SIZE ]; |
michael@0 | 86 | SAVE_STACK; |
michael@0 | 87 | |
michael@0 | 88 | silk_assert( M <= MAX_MATRIX_SIZE ); |
michael@0 | 89 | ALLOC( L_Q16, M * M, opus_int32 ); |
michael@0 | 90 | |
michael@0 | 91 | /*************************************************** |
michael@0 | 92 | Factorize A by LDL such that A = L*D*L', |
michael@0 | 93 | where L is lower triangular with ones on diagonal |
michael@0 | 94 | ****************************************************/ |
michael@0 | 95 | silk_LDL_factorize_FIX( A, M, L_Q16, inv_D ); |
michael@0 | 96 | |
michael@0 | 97 | /**************************************************** |
michael@0 | 98 | * substitute D*L'*x = Y. ie: |
michael@0 | 99 | L*D*L'*x = b => L*Y = b <=> Y = inv(L)*b |
michael@0 | 100 | ******************************************************/ |
michael@0 | 101 | silk_LS_SolveFirst_FIX( L_Q16, M, b, Y ); |
michael@0 | 102 | |
michael@0 | 103 | /**************************************************** |
michael@0 | 104 | D*L'*x = Y <=> L'*x = inv(D)*Y, because D is |
michael@0 | 105 | diagonal just multiply with 1/d_i |
michael@0 | 106 | ****************************************************/ |
michael@0 | 107 | silk_LS_divide_Q16_FIX( Y, inv_D, M ); |
michael@0 | 108 | |
michael@0 | 109 | /**************************************************** |
michael@0 | 110 | x = inv(L') * inv(D) * Y |
michael@0 | 111 | *****************************************************/ |
michael@0 | 112 | silk_LS_SolveLast_FIX( L_Q16, M, Y, x_Q16 ); |
michael@0 | 113 | RESTORE_STACK; |
michael@0 | 114 | } |
michael@0 | 115 | |
michael@0 | 116 | static OPUS_INLINE void silk_LDL_factorize_FIX( |
michael@0 | 117 | opus_int32 *A, /* I/O Pointer to Symetric Square Matrix */ |
michael@0 | 118 | opus_int M, /* I Size of Matrix */ |
michael@0 | 119 | opus_int32 *L_Q16, /* I/O Pointer to Square Upper triangular Matrix */ |
michael@0 | 120 | inv_D_t *inv_D /* I/O Pointer to vector holding inverted diagonal elements of D */ |
michael@0 | 121 | ) |
michael@0 | 122 | { |
michael@0 | 123 | opus_int i, j, k, status, loop_count; |
michael@0 | 124 | const opus_int32 *ptr1, *ptr2; |
michael@0 | 125 | opus_int32 diag_min_value, tmp_32, err; |
michael@0 | 126 | opus_int32 v_Q0[ MAX_MATRIX_SIZE ], D_Q0[ MAX_MATRIX_SIZE ]; |
michael@0 | 127 | opus_int32 one_div_diag_Q36, one_div_diag_Q40, one_div_diag_Q48; |
michael@0 | 128 | |
michael@0 | 129 | silk_assert( M <= MAX_MATRIX_SIZE ); |
michael@0 | 130 | |
michael@0 | 131 | status = 1; |
michael@0 | 132 | diag_min_value = silk_max_32( silk_SMMUL( silk_ADD_SAT32( A[ 0 ], A[ silk_SMULBB( M, M ) - 1 ] ), SILK_FIX_CONST( FIND_LTP_COND_FAC, 31 ) ), 1 << 9 ); |
michael@0 | 133 | for( loop_count = 0; loop_count < M && status == 1; loop_count++ ) { |
michael@0 | 134 | status = 0; |
michael@0 | 135 | for( j = 0; j < M; j++ ) { |
michael@0 | 136 | ptr1 = matrix_adr( L_Q16, j, 0, M ); |
michael@0 | 137 | tmp_32 = 0; |
michael@0 | 138 | for( i = 0; i < j; i++ ) { |
michael@0 | 139 | v_Q0[ i ] = silk_SMULWW( D_Q0[ i ], ptr1[ i ] ); /* Q0 */ |
michael@0 | 140 | tmp_32 = silk_SMLAWW( tmp_32, v_Q0[ i ], ptr1[ i ] ); /* Q0 */ |
michael@0 | 141 | } |
michael@0 | 142 | tmp_32 = silk_SUB32( matrix_ptr( A, j, j, M ), tmp_32 ); |
michael@0 | 143 | |
michael@0 | 144 | if( tmp_32 < diag_min_value ) { |
michael@0 | 145 | tmp_32 = silk_SUB32( silk_SMULBB( loop_count + 1, diag_min_value ), tmp_32 ); |
michael@0 | 146 | /* Matrix not positive semi-definite, or ill conditioned */ |
michael@0 | 147 | for( i = 0; i < M; i++ ) { |
michael@0 | 148 | matrix_ptr( A, i, i, M ) = silk_ADD32( matrix_ptr( A, i, i, M ), tmp_32 ); |
michael@0 | 149 | } |
michael@0 | 150 | status = 1; |
michael@0 | 151 | break; |
michael@0 | 152 | } |
michael@0 | 153 | D_Q0[ j ] = tmp_32; /* always < max(Correlation) */ |
michael@0 | 154 | |
michael@0 | 155 | /* two-step division */ |
michael@0 | 156 | one_div_diag_Q36 = silk_INVERSE32_varQ( tmp_32, 36 ); /* Q36 */ |
michael@0 | 157 | one_div_diag_Q40 = silk_LSHIFT( one_div_diag_Q36, 4 ); /* Q40 */ |
michael@0 | 158 | err = silk_SUB32( (opus_int32)1 << 24, silk_SMULWW( tmp_32, one_div_diag_Q40 ) ); /* Q24 */ |
michael@0 | 159 | one_div_diag_Q48 = silk_SMULWW( err, one_div_diag_Q40 ); /* Q48 */ |
michael@0 | 160 | |
michael@0 | 161 | /* Save 1/Ds */ |
michael@0 | 162 | inv_D[ j ].Q36_part = one_div_diag_Q36; |
michael@0 | 163 | inv_D[ j ].Q48_part = one_div_diag_Q48; |
michael@0 | 164 | |
michael@0 | 165 | matrix_ptr( L_Q16, j, j, M ) = 65536; /* 1.0 in Q16 */ |
michael@0 | 166 | ptr1 = matrix_adr( A, j, 0, M ); |
michael@0 | 167 | ptr2 = matrix_adr( L_Q16, j + 1, 0, M ); |
michael@0 | 168 | for( i = j + 1; i < M; i++ ) { |
michael@0 | 169 | tmp_32 = 0; |
michael@0 | 170 | for( k = 0; k < j; k++ ) { |
michael@0 | 171 | tmp_32 = silk_SMLAWW( tmp_32, v_Q0[ k ], ptr2[ k ] ); /* Q0 */ |
michael@0 | 172 | } |
michael@0 | 173 | tmp_32 = silk_SUB32( ptr1[ i ], tmp_32 ); /* always < max(Correlation) */ |
michael@0 | 174 | |
michael@0 | 175 | /* tmp_32 / D_Q0[j] : Divide to Q16 */ |
michael@0 | 176 | matrix_ptr( L_Q16, i, j, M ) = silk_ADD32( silk_SMMUL( tmp_32, one_div_diag_Q48 ), |
michael@0 | 177 | silk_RSHIFT( silk_SMULWW( tmp_32, one_div_diag_Q36 ), 4 ) ); |
michael@0 | 178 | |
michael@0 | 179 | /* go to next column */ |
michael@0 | 180 | ptr2 += M; |
michael@0 | 181 | } |
michael@0 | 182 | } |
michael@0 | 183 | } |
michael@0 | 184 | |
michael@0 | 185 | silk_assert( status == 0 ); |
michael@0 | 186 | } |
michael@0 | 187 | |
michael@0 | 188 | static OPUS_INLINE void silk_LS_divide_Q16_FIX( |
michael@0 | 189 | opus_int32 T[], /* I/O Numenator vector */ |
michael@0 | 190 | inv_D_t *inv_D, /* I 1 / D vector */ |
michael@0 | 191 | opus_int M /* I dimension */ |
michael@0 | 192 | ) |
michael@0 | 193 | { |
michael@0 | 194 | opus_int i; |
michael@0 | 195 | opus_int32 tmp_32; |
michael@0 | 196 | opus_int32 one_div_diag_Q36, one_div_diag_Q48; |
michael@0 | 197 | |
michael@0 | 198 | for( i = 0; i < M; i++ ) { |
michael@0 | 199 | one_div_diag_Q36 = inv_D[ i ].Q36_part; |
michael@0 | 200 | one_div_diag_Q48 = inv_D[ i ].Q48_part; |
michael@0 | 201 | |
michael@0 | 202 | tmp_32 = T[ i ]; |
michael@0 | 203 | T[ i ] = silk_ADD32( silk_SMMUL( tmp_32, one_div_diag_Q48 ), silk_RSHIFT( silk_SMULWW( tmp_32, one_div_diag_Q36 ), 4 ) ); |
michael@0 | 204 | } |
michael@0 | 205 | } |
michael@0 | 206 | |
michael@0 | 207 | /* Solve Lx = b, when L is lower triangular and has ones on the diagonal */ |
michael@0 | 208 | static OPUS_INLINE void silk_LS_SolveFirst_FIX( |
michael@0 | 209 | const opus_int32 *L_Q16, /* I Pointer to Lower Triangular Matrix */ |
michael@0 | 210 | opus_int M, /* I Dim of Matrix equation */ |
michael@0 | 211 | const opus_int32 *b, /* I b Vector */ |
michael@0 | 212 | opus_int32 *x_Q16 /* O x Vector */ |
michael@0 | 213 | ) |
michael@0 | 214 | { |
michael@0 | 215 | opus_int i, j; |
michael@0 | 216 | const opus_int32 *ptr32; |
michael@0 | 217 | opus_int32 tmp_32; |
michael@0 | 218 | |
michael@0 | 219 | for( i = 0; i < M; i++ ) { |
michael@0 | 220 | ptr32 = matrix_adr( L_Q16, i, 0, M ); |
michael@0 | 221 | tmp_32 = 0; |
michael@0 | 222 | for( j = 0; j < i; j++ ) { |
michael@0 | 223 | tmp_32 = silk_SMLAWW( tmp_32, ptr32[ j ], x_Q16[ j ] ); |
michael@0 | 224 | } |
michael@0 | 225 | x_Q16[ i ] = silk_SUB32( b[ i ], tmp_32 ); |
michael@0 | 226 | } |
michael@0 | 227 | } |
michael@0 | 228 | |
michael@0 | 229 | /* Solve L^t*x = b, where L is lower triangular with ones on the diagonal */ |
michael@0 | 230 | static OPUS_INLINE void silk_LS_SolveLast_FIX( |
michael@0 | 231 | const opus_int32 *L_Q16, /* I Pointer to Lower Triangular Matrix */ |
michael@0 | 232 | const opus_int M, /* I Dim of Matrix equation */ |
michael@0 | 233 | const opus_int32 *b, /* I b Vector */ |
michael@0 | 234 | opus_int32 *x_Q16 /* O x Vector */ |
michael@0 | 235 | ) |
michael@0 | 236 | { |
michael@0 | 237 | opus_int i, j; |
michael@0 | 238 | const opus_int32 *ptr32; |
michael@0 | 239 | opus_int32 tmp_32; |
michael@0 | 240 | |
michael@0 | 241 | for( i = M - 1; i >= 0; i-- ) { |
michael@0 | 242 | ptr32 = matrix_adr( L_Q16, 0, i, M ); |
michael@0 | 243 | tmp_32 = 0; |
michael@0 | 244 | for( j = M - 1; j > i; j-- ) { |
michael@0 | 245 | tmp_32 = silk_SMLAWW( tmp_32, ptr32[ silk_SMULBB( j, M ) ], x_Q16[ j ] ); |
michael@0 | 246 | } |
michael@0 | 247 | x_Q16[ i ] = silk_SUB32( b[ i ], tmp_32 ); |
michael@0 | 248 | } |
michael@0 | 249 | } |