* qatar/master: configure: fix tests for 2-arg math functions doc: git-howto: Clarify comment about pushing series of commits ivi_common: Drop unused function parameter from decode_band() cook: Remove some silly Doxygen comments cook: Remove senseless maybe_reformat_buffer32() function cook: cosmetics: Better names for joint_decode() function parameters cook: cosmetics: Better name for ccpl COOKSubpacket member doxygen: Add av_alloc_size to list of predefined macros doxygen: Drop some pointless entries from PREDEFINED macros list h263: avoid memcpys over array bound in motion vector caching for obmc Conflicts: configure doc/git-howto.texi libavcodec/cook.c Merged-by: Michael Niedermayer <michaelni@gmx.at>tags/n1.1
| @@ -852,23 +852,13 @@ EOF | |||||
| check_mathfunc(){ | check_mathfunc(){ | ||||
| log check_mathfunc "$@" | log check_mathfunc "$@" | ||||
| func=$1 | func=$1 | ||||
| shift | |||||
| disable $func | |||||
| check_ld "cc" "$@" <<EOF && enable $func | |||||
| #include <math.h> | |||||
| float foo(float f) { return $func(f); } | |||||
| int main(void){ return (int) foo; } | |||||
| EOF | |||||
| } | |||||
| check_math2func(){ | |||||
| log check_math2func "$@" | |||||
| func=$1 | |||||
| shift | |||||
| narg=$2 | |||||
| shift 2 | |||||
| test $narg = 2 && args="f, g" || args="f" | |||||
| disable $func | disable $func | ||||
| check_ld "cc" "$@" <<EOF && enable $func | check_ld "cc" "$@" <<EOF && enable $func | ||||
| #include <math.h> | #include <math.h> | ||||
| float foo(float f) { return $func(f, f); } | |||||
| float foo(float f, float g) { return $func($args); } | |||||
| int main(void){ return (int) foo; } | int main(void){ return (int) foo; } | ||||
| EOF | EOF | ||||
| } | } | ||||
| @@ -1279,6 +1269,7 @@ HAVE_LIST_PUB=' | |||||
| MATH_FUNCS=" | MATH_FUNCS=" | ||||
| atanf | atanf | ||||
| atan2f | |||||
| cbrtf | cbrtf | ||||
| cosf | cosf | ||||
| exp2 | exp2 | ||||
| @@ -1286,6 +1277,7 @@ MATH_FUNCS=" | |||||
| expf | expf | ||||
| isinf | isinf | ||||
| isnan | isnan | ||||
| ldexpf | |||||
| llrint | llrint | ||||
| llrintf | llrintf | ||||
| log2 | log2 | ||||
| @@ -1293,6 +1285,7 @@ MATH_FUNCS=" | |||||
| log10f | log10f | ||||
| lrint | lrint | ||||
| lrintf | lrintf | ||||
| powf | |||||
| rint | rint | ||||
| round | round | ||||
| roundf | roundf | ||||
| @@ -1301,12 +1294,6 @@ MATH_FUNCS=" | |||||
| truncf | truncf | ||||
| " | " | ||||
| MATH2_FUNCS=" | |||||
| atan2f | |||||
| ldexpf | |||||
| powf | |||||
| " | |||||
| HAVE_LIST=" | HAVE_LIST=" | ||||
| $ARCH_EXT_LIST | $ARCH_EXT_LIST | ||||
| $(add_suffix _external $ARCH_EXT_LIST) | $(add_suffix _external $ARCH_EXT_LIST) | ||||
| @@ -1315,7 +1302,6 @@ HAVE_LIST=" | |||||
| $HAVE_LIST_PUB | $HAVE_LIST_PUB | ||||
| $THREADS_LIST | $THREADS_LIST | ||||
| $MATH_FUNCS | $MATH_FUNCS | ||||
| $MATH2_FUNCS | |||||
| aligned_malloc | aligned_malloc | ||||
| aligned_stack | aligned_stack | ||||
| alsa_asoundlib_h | alsa_asoundlib_h | ||||
| @@ -3671,12 +3657,12 @@ check_lib math.h sin -lm && LIBM="-lm" | |||||
| disabled crystalhd || check_lib libcrystalhd/libcrystalhd_if.h DtsCrystalHDVersion -lcrystalhd || disable crystalhd | disabled crystalhd || check_lib libcrystalhd/libcrystalhd_if.h DtsCrystalHDVersion -lcrystalhd || disable crystalhd | ||||
| enabled vaapi && require vaapi va/va.h vaInitialize -lva | enabled vaapi && require vaapi va/va.h vaInitialize -lva | ||||
| for func in $MATH_FUNCS; do | |||||
| check_mathfunc $func | |||||
| done | |||||
| atan2f_args=2 | |||||
| ldexpf_args=2 | |||||
| powf_args=2 | |||||
| for func in $MATH2_FUNCS; do | |||||
| check_math2func $func | |||||
| for func in $MATH_FUNCS; do | |||||
| eval check_mathfunc $func \${${func}_args:-1} | |||||
| done | done | ||||
| # these are off by default, so fail if requested and not available | # these are off by default, so fail if requested and not available | ||||
| @@ -1373,14 +1373,9 @@ INCLUDE_FILE_PATTERNS = | |||||
| # instead of the = operator. | # instead of the = operator. | ||||
| PREDEFINED = "__attribute__(x)=" \ | PREDEFINED = "__attribute__(x)=" \ | ||||
| "RENAME(x)=x ## _TMPL" \ | |||||
| "DEF(x)=x ## _TMPL" \ | |||||
| HAVE_AV_CONFIG_H \ | |||||
| HAVE_MMX \ | |||||
| HAVE_MMXEXT \ | |||||
| HAVE_AMD3DNOW \ | |||||
| "DECLARE_ALIGNED(a,t,n)=t n" \ | "DECLARE_ALIGNED(a,t,n)=t n" \ | ||||
| "offsetof(x,y)=0x42" | |||||
| "offsetof(x,y)=0x42" \ | |||||
| av_alloc_size \ | |||||
| # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then | # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then | ||||
| # this tag can be used to specify a list of macro names that should be expanded. | # this tag can be used to specify a list of macro names that should be expanded. | ||||
| @@ -79,16 +79,16 @@ typedef struct { | |||||
| int samples_per_channel; | int samples_per_channel; | ||||
| int log2_numvector_size; | int log2_numvector_size; | ||||
| unsigned int channel_mask; | unsigned int channel_mask; | ||||
| VLC ccpl; ///< channel coupling | |||||
| VLC channel_coupling; | |||||
| int joint_stereo; | int joint_stereo; | ||||
| int bits_per_subpacket; | int bits_per_subpacket; | ||||
| int bits_per_subpdiv; | int bits_per_subpdiv; | ||||
| int total_subbands; | int total_subbands; | ||||
| int numvector_size; ///< 1 << log2_numvector_size; | |||||
| int numvector_size; // 1 << log2_numvector_size; | |||||
| float mono_previous_buffer1[1024]; | float mono_previous_buffer1[1024]; | ||||
| float mono_previous_buffer2[1024]; | float mono_previous_buffer2[1024]; | ||||
| /** gain buffers */ | |||||
| cook_gains gains1; | cook_gains gains1; | ||||
| cook_gains gains2; | cook_gains gains2; | ||||
| int gain_1[9]; | int gain_1[9]; | ||||
| @@ -205,7 +205,8 @@ static av_cold int init_cook_vlc_tables(COOKContext *q) | |||||
| for (i = 0; i < q->num_subpackets; i++) { | for (i = 0; i < q->num_subpackets; i++) { | ||||
| if (q->subpacket[i].joint_stereo == 1) { | if (q->subpacket[i].joint_stereo == 1) { | ||||
| result |= init_vlc(&q->subpacket[i].ccpl, 6, (1 << q->subpacket[i].js_vlc_bits) - 1, | |||||
| result |= init_vlc(&q->subpacket[i].channel_coupling, 6, | |||||
| (1 << q->subpacket[i].js_vlc_bits) - 1, | |||||
| ccpl_huffbits[q->subpacket[i].js_vlc_bits - 2], 1, 1, | ccpl_huffbits[q->subpacket[i].js_vlc_bits - 2], 1, 1, | ||||
| ccpl_huffcodes[q->subpacket[i].js_vlc_bits - 2], 2, 2, 0); | ccpl_huffcodes[q->subpacket[i].js_vlc_bits - 2], 2, 2, 0); | ||||
| av_log(q->avctx, AV_LOG_DEBUG, "subpacket %i Joint-stereo VLC used.\n", i); | av_log(q->avctx, AV_LOG_DEBUG, "subpacket %i Joint-stereo VLC used.\n", i); | ||||
| @@ -240,17 +241,11 @@ static av_cold int init_cook_mlt(COOKContext *q) | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| static const float *maybe_reformat_buffer32(COOKContext *q, const float *ptr, int n) | |||||
| { | |||||
| if (1) | |||||
| return ptr; | |||||
| } | |||||
| static av_cold void init_cplscales_table(COOKContext *q) | static av_cold void init_cplscales_table(COOKContext *q) | ||||
| { | { | ||||
| int i; | int i; | ||||
| for (i = 0; i < 5; i++) | for (i = 0; i < 5; i++) | ||||
| q->cplscales[i] = maybe_reformat_buffer32(q, cplscales[i], (1 << (i + 2)) - 1); | |||||
| q->cplscales[i] = cplscales[i]; | |||||
| } | } | ||||
| /*************** init functions end ***********/ | /*************** init functions end ***********/ | ||||
| @@ -304,9 +299,6 @@ static inline int decode_bytes(const uint8_t *inbuffer, uint8_t *out, int bytes) | |||||
| return off; | return off; | ||||
| } | } | ||||
| /** | |||||
| * Cook uninit | |||||
| */ | |||||
| static av_cold int cook_decode_close(AVCodecContext *avctx) | static av_cold int cook_decode_close(AVCodecContext *avctx) | ||||
| { | { | ||||
| int i; | int i; | ||||
| @@ -326,7 +318,7 @@ static av_cold int cook_decode_close(AVCodecContext *avctx) | |||||
| for (i = 0; i < 7; i++) | for (i = 0; i < 7; i++) | ||||
| ff_free_vlc(&q->sqvh[i]); | ff_free_vlc(&q->sqvh[i]); | ||||
| for (i = 0; i < q->num_subpackets; i++) | for (i = 0; i < q->num_subpackets; i++) | ||||
| ff_free_vlc(&q->subpacket[i].ccpl); | |||||
| ff_free_vlc(&q->subpacket[i].channel_coupling); | |||||
| av_log(avctx, AV_LOG_DEBUG, "Memory deallocated.\n"); | av_log(avctx, AV_LOG_DEBUG, "Memory deallocated.\n"); | ||||
| @@ -636,12 +628,6 @@ static void decode_vectors(COOKContext *q, COOKSubpacket *p, int *category, | |||||
| } | } | ||||
| /** | |||||
| * function for decoding mono data | |||||
| * | |||||
| * @param q pointer to the COOKContext | |||||
| * @param mlt_buffer pointer to mlt coefficients | |||||
| */ | |||||
| static int mono_decode(COOKContext *q, COOKSubpacket *p, float *mlt_buffer) | static int mono_decode(COOKContext *q, COOKSubpacket *p, float *mlt_buffer) | ||||
| { | { | ||||
| int category_index[128] = { 0 }; | int category_index[128] = { 0 }; | ||||
| @@ -756,7 +742,6 @@ static void imlt_gain(COOKContext *q, float *inbuffer, | |||||
| * | * | ||||
| * @param q pointer to the COOKContext | * @param q pointer to the COOKContext | ||||
| * @param decouple_tab decoupling array | * @param decouple_tab decoupling array | ||||
| * | |||||
| */ | */ | ||||
| static int decouple_info(COOKContext *q, COOKSubpacket *p, int *decouple_tab) | static int decouple_info(COOKContext *q, COOKSubpacket *p, int *decouple_tab) | ||||
| { | { | ||||
| @@ -771,7 +756,9 @@ static int decouple_info(COOKContext *q, COOKSubpacket *p, int *decouple_tab) | |||||
| if (vlc) | if (vlc) | ||||
| for (i = 0; i < length; i++) | for (i = 0; i < length; i++) | ||||
| decouple_tab[start + i] = get_vlc2(&q->gb, p->ccpl.table, p->ccpl.bits, 2); | |||||
| decouple_tab[start + i] = get_vlc2(&q->gb, | |||||
| p->channel_coupling.table, | |||||
| p->channel_coupling.bits, 2); | |||||
| else | else | ||||
| for (i = 0; i < length; i++) { | for (i = 0; i < length; i++) { | ||||
| int v = get_bits(&q->gb, p->js_vlc_bits); | int v = get_bits(&q->gb, p->js_vlc_bits); | ||||
| @@ -817,8 +804,8 @@ static void decouple_float(COOKContext *q, | |||||
| * @param mlt_buffer1 pointer to left channel mlt coefficients | * @param mlt_buffer1 pointer to left channel mlt coefficients | ||||
| * @param mlt_buffer2 pointer to right channel mlt coefficients | * @param mlt_buffer2 pointer to right channel mlt coefficients | ||||
| */ | */ | ||||
| static int joint_decode(COOKContext *q, COOKSubpacket *p, float *mlt_buffer1, | |||||
| float *mlt_buffer2) | |||||
| static int joint_decode(COOKContext *q, COOKSubpacket *p, | |||||
| float *mlt_buffer_left, float *mlt_buffer_right) | |||||
| { | { | ||||
| int i, j, res; | int i, j, res; | ||||
| int decouple_tab[SUBBAND_SIZE] = { 0 }; | int decouple_tab[SUBBAND_SIZE] = { 0 }; | ||||
| @@ -830,8 +817,8 @@ static int joint_decode(COOKContext *q, COOKSubpacket *p, float *mlt_buffer1, | |||||
| memset(decode_buffer, 0, sizeof(q->decode_buffer_0)); | memset(decode_buffer, 0, sizeof(q->decode_buffer_0)); | ||||
| /* Make sure the buffers are zeroed out. */ | /* Make sure the buffers are zeroed out. */ | ||||
| memset(mlt_buffer1, 0, 1024 * sizeof(*mlt_buffer1)); | |||||
| memset(mlt_buffer2, 0, 1024 * sizeof(*mlt_buffer2)); | |||||
| memset(mlt_buffer_left, 0, 1024 * sizeof(*mlt_buffer_left)); | |||||
| memset(mlt_buffer_right, 0, 1024 * sizeof(*mlt_buffer_right)); | |||||
| if ((res = decouple_info(q, p, decouple_tab)) < 0) | if ((res = decouple_info(q, p, decouple_tab)) < 0) | ||||
| return res; | return res; | ||||
| if ((res = mono_decode(q, p, decode_buffer)) < 0) | if ((res = mono_decode(q, p, decode_buffer)) < 0) | ||||
| @@ -839,8 +826,8 @@ static int joint_decode(COOKContext *q, COOKSubpacket *p, float *mlt_buffer1, | |||||
| /* The two channels are stored interleaved in decode_buffer. */ | /* The two channels are stored interleaved in decode_buffer. */ | ||||
| for (i = 0; i < p->js_subband_start; i++) { | for (i = 0; i < p->js_subband_start; i++) { | ||||
| for (j = 0; j < SUBBAND_SIZE; j++) { | for (j = 0; j < SUBBAND_SIZE; j++) { | ||||
| mlt_buffer1[i * 20 + j] = decode_buffer[i * 40 + j]; | |||||
| mlt_buffer2[i * 20 + j] = decode_buffer[i * 40 + 20 + j]; | |||||
| mlt_buffer_left[i * 20 + j] = decode_buffer[i * 40 + j]; | |||||
| mlt_buffer_right[i * 20 + j] = decode_buffer[i * 40 + 20 + j]; | |||||
| } | } | ||||
| } | } | ||||
| @@ -853,7 +840,8 @@ static int joint_decode(COOKContext *q, COOKSubpacket *p, float *mlt_buffer1, | |||||
| cplscale = q->cplscales[p->js_vlc_bits - 2]; // choose decoupler table | cplscale = q->cplscales[p->js_vlc_bits - 2]; // choose decoupler table | ||||
| f1 = cplscale[decouple_tab[cpl_tmp] + 1]; | f1 = cplscale[decouple_tab[cpl_tmp] + 1]; | ||||
| f2 = cplscale[idx]; | f2 = cplscale[idx]; | ||||
| q->decouple(q, p, i, f1, f2, decode_buffer, mlt_buffer1, mlt_buffer2); | |||||
| q->decouple(q, p, i, f1, f2, decode_buffer, | |||||
| mlt_buffer_left, mlt_buffer_right); | |||||
| idx = (1 << p->js_vlc_bits) - 1; | idx = (1 << p->js_vlc_bits) - 1; | ||||
| } | } | ||||
| @@ -968,11 +956,6 @@ static int decode_subpacket(COOKContext *q, COOKSubpacket *p, | |||||
| } | } | ||||
| /** | |||||
| * Cook frame decoding | |||||
| * | |||||
| * @param avctx pointer to the AVCodecContext | |||||
| */ | |||||
| static int cook_decode_frame(AVCodecContext *avctx, void *data, | static int cook_decode_frame(AVCodecContext *avctx, void *data, | ||||
| int *got_frame_ptr, AVPacket *avpkt) | int *got_frame_ptr, AVPacket *avpkt) | ||||
| { | { | ||||
| @@ -650,7 +650,7 @@ void ff_ivi_output_plane(IVIPlaneDesc *plane, uint8_t *dst, int dst_pitch) | |||||
| * @param[in] avctx ptr to the AVCodecContext | * @param[in] avctx ptr to the AVCodecContext | ||||
| * @return result code: 0 = OK, -1 = error | * @return result code: 0 = OK, -1 = error | ||||
| */ | */ | ||||
| static int decode_band(IVI45DecContext *ctx, int plane_num, | |||||
| static int decode_band(IVI45DecContext *ctx, | |||||
| IVIBandDesc *band, AVCodecContext *avctx) | IVIBandDesc *band, AVCodecContext *avctx) | ||||
| { | { | ||||
| int result, i, t, idx1, idx2, pos; | int result, i, t, idx1, idx2, pos; | ||||
| @@ -791,7 +791,7 @@ int ff_ivi_decode_frame(AVCodecContext *avctx, void *data, int *data_size, | |||||
| ctx->buf_invalid[ctx->dst_buf] = 1; | ctx->buf_invalid[ctx->dst_buf] = 1; | ||||
| for (p = 0; p < 3; p++) { | for (p = 0; p < 3; p++) { | ||||
| for (b = 0; b < ctx->planes[p].num_bands; b++) { | for (b = 0; b < ctx->planes[p].num_bands; b++) { | ||||
| result = decode_band(ctx, p, &ctx->planes[p].bands[b], avctx); | |||||
| result = decode_band(ctx, &ctx->planes[p].bands[b], avctx); | |||||
| if (result) { | if (result) { | ||||
| av_log(avctx, AV_LOG_ERROR, | av_log(avctx, AV_LOG_ERROR, | ||||
| "Error while decoding band: %d, plane: %d\n", b, p); | "Error while decoding band: %d, plane: %d\n", b, p); | ||||
| @@ -639,37 +639,45 @@ static av_always_inline void MPV_motion_internal(MpegEncContext *s, | |||||
| prefetch_motion(s, ref_picture, dir); | prefetch_motion(s, ref_picture, dir); | ||||
| if(!is_mpeg12 && s->obmc && s->pict_type != AV_PICTURE_TYPE_B){ | if(!is_mpeg12 && s->obmc && s->pict_type != AV_PICTURE_TYPE_B){ | ||||
| int16_t mv_cache[4][4][2]; | |||||
| LOCAL_ALIGNED_8(int16_t, mv_cache, [4], [4][2]); | |||||
| AVFrame *cur_frame = &s->current_picture.f; | |||||
| const int xy= s->mb_x + s->mb_y*s->mb_stride; | const int xy= s->mb_x + s->mb_y*s->mb_stride; | ||||
| const int mot_stride= s->b8_stride; | const int mot_stride= s->b8_stride; | ||||
| const int mot_xy= mb_x*2 + mb_y*2*mot_stride; | const int mot_xy= mb_x*2 + mb_y*2*mot_stride; | ||||
| av_assert2(!s->mb_skipped); | av_assert2(!s->mb_skipped); | ||||
| memcpy(mv_cache[1][1], s->current_picture.f.motion_val[0][mot_xy ], sizeof(int16_t) * 4); | |||||
| memcpy(mv_cache[2][1], s->current_picture.f.motion_val[0][mot_xy + mot_stride], sizeof(int16_t) * 4); | |||||
| memcpy(mv_cache[3][1], s->current_picture.f.motion_val[0][mot_xy + mot_stride], sizeof(int16_t) * 4); | |||||
| AV_COPY32(mv_cache[1][1], cur_frame->motion_val[0][mot_xy ]); | |||||
| AV_COPY32(mv_cache[1][2], cur_frame->motion_val[0][mot_xy + 1]); | |||||
| if (mb_y == 0 || IS_INTRA(s->current_picture.f.mb_type[xy - s->mb_stride])) { | |||||
| memcpy(mv_cache[0][1], mv_cache[1][1], sizeof(int16_t)*4); | |||||
| AV_COPY32(mv_cache[2][1], cur_frame->motion_val[0][mot_xy + mot_stride ]); | |||||
| AV_COPY32(mv_cache[2][2], cur_frame->motion_val[0][mot_xy + mot_stride + 1]); | |||||
| AV_COPY32(mv_cache[3][1], cur_frame->motion_val[0][mot_xy + mot_stride ]); | |||||
| AV_COPY32(mv_cache[3][2], cur_frame->motion_val[0][mot_xy + mot_stride + 1]); | |||||
| if (mb_y == 0 || IS_INTRA(cur_frame->mb_type[xy - s->mb_stride])) { | |||||
| AV_COPY32(mv_cache[0][1], mv_cache[1][1]); | |||||
| AV_COPY32(mv_cache[0][2], mv_cache[1][2]); | |||||
| }else{ | }else{ | ||||
| memcpy(mv_cache[0][1], s->current_picture.f.motion_val[0][mot_xy - mot_stride], sizeof(int16_t) * 4); | |||||
| AV_COPY32(mv_cache[0][1], cur_frame->motion_val[0][mot_xy - mot_stride ]); | |||||
| AV_COPY32(mv_cache[0][2], cur_frame->motion_val[0][mot_xy - mot_stride + 1]); | |||||
| } | } | ||||
| if (mb_x == 0 || IS_INTRA(s->current_picture.f.mb_type[xy - 1])) { | |||||
| if (mb_x == 0 || IS_INTRA(cur_frame->mb_type[xy - 1])) { | |||||
| AV_COPY32(mv_cache[1][0], mv_cache[1][1]); | AV_COPY32(mv_cache[1][0], mv_cache[1][1]); | ||||
| AV_COPY32(mv_cache[2][0], mv_cache[2][1]); | AV_COPY32(mv_cache[2][0], mv_cache[2][1]); | ||||
| }else{ | }else{ | ||||
| AV_COPY32(mv_cache[1][0], s->current_picture.f.motion_val[0][mot_xy - 1]); | |||||
| AV_COPY32(mv_cache[2][0], s->current_picture.f.motion_val[0][mot_xy - 1 + mot_stride]); | |||||
| AV_COPY32(mv_cache[1][0], cur_frame->motion_val[0][mot_xy - 1]); | |||||
| AV_COPY32(mv_cache[2][0], cur_frame->motion_val[0][mot_xy - 1 + mot_stride]); | |||||
| } | } | ||||
| if (mb_x + 1 >= s->mb_width || IS_INTRA(s->current_picture.f.mb_type[xy + 1])) { | |||||
| if (mb_x + 1 >= s->mb_width || IS_INTRA(cur_frame->mb_type[xy + 1])) { | |||||
| AV_COPY32(mv_cache[1][3], mv_cache[1][2]); | AV_COPY32(mv_cache[1][3], mv_cache[1][2]); | ||||
| AV_COPY32(mv_cache[2][3], mv_cache[2][2]); | AV_COPY32(mv_cache[2][3], mv_cache[2][2]); | ||||
| }else{ | }else{ | ||||
| AV_COPY32(mv_cache[1][3], s->current_picture.f.motion_val[0][mot_xy + 2]); | |||||
| AV_COPY32(mv_cache[2][3], s->current_picture.f.motion_val[0][mot_xy + 2 + mot_stride]); | |||||
| AV_COPY32(mv_cache[1][3], cur_frame->motion_val[0][mot_xy + 2]); | |||||
| AV_COPY32(mv_cache[2][3], cur_frame->motion_val[0][mot_xy + 2 + mot_stride]); | |||||
| } | } | ||||
| mx = 0; | mx = 0; | ||||