From d2f50fb9259a3142fa6b319a7a735a0e19355d01 Mon Sep 17 00:00:00 2001 From: Clyne Sullivan Date: Sat, 8 May 2021 11:55:12 -0400 Subject: [PATCH 01/13] include dsp lib; split timers; user message --- gui/cmsis/arm_conv_f32.c | 647 +++++++++++++++++++++++ gui/cmsis/arm_conv_q15.c | 734 ++++++++++++++++++++++++++ gui/cmsis/arm_conv_q31.c | 565 ++++++++++++++++++++ gui/cmsis/arm_conv_q7.c | 690 ++++++++++++++++++++++++ gui/cmsis/arm_fir_f32.c | 997 +++++++++++++++++++++++++++++++++++ gui/cmsis/arm_fir_init_f32.c | 96 ++++ gui/cmsis/arm_fir_init_q15.c | 154 ++++++ gui/cmsis/arm_fir_init_q31.c | 96 ++++ gui/cmsis/arm_fir_init_q7.c | 94 ++++ gui/cmsis/arm_fir_q15.c | 691 ++++++++++++++++++++++++ gui/cmsis/arm_fir_q31.c | 365 +++++++++++++ gui/cmsis/arm_fir_q7.c | 397 ++++++++++++++ gui/wxmain.cpp | 140 ++--- gui/wxmain.hpp | 8 +- gui/wxmain_devdata.cpp | 5 +- gui/wxmain_mrun.cpp | 16 +- source/main.cpp | 19 + 17 files changed, 5640 insertions(+), 74 deletions(-) create mode 100644 gui/cmsis/arm_conv_f32.c create mode 100644 gui/cmsis/arm_conv_q15.c create mode 100644 gui/cmsis/arm_conv_q31.c create mode 100644 gui/cmsis/arm_conv_q7.c create mode 100644 gui/cmsis/arm_fir_f32.c create mode 100644 gui/cmsis/arm_fir_init_f32.c create mode 100644 gui/cmsis/arm_fir_init_q15.c create mode 100644 gui/cmsis/arm_fir_init_q31.c create mode 100644 gui/cmsis/arm_fir_init_q7.c create mode 100644 gui/cmsis/arm_fir_q15.c create mode 100644 gui/cmsis/arm_fir_q31.c create mode 100644 gui/cmsis/arm_fir_q7.c diff --git a/gui/cmsis/arm_conv_f32.c b/gui/cmsis/arm_conv_f32.c new file mode 100644 index 0000000..65f7ab8 --- /dev/null +++ b/gui/cmsis/arm_conv_f32.c @@ -0,0 +1,647 @@ +/* ---------------------------------------------------------------------------- +* Copyright (C) 2010-2014 ARM Limited. All rights reserved. +* +* $Date: 19. March 2015 +* $Revision: V.1.4.5 +* +* Project: CMSIS DSP Library +* Title: arm_conv_f32.c +* +* Description: Convolution of floating-point sequences. +* +* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0 +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* - Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* - Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* - Neither the name of ARM LIMITED nor the names of its contributors +* may be used to endorse or promote products derived from this +* software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* -------------------------------------------------------------------------- */ + +#include "arm_math.h" + +/** + * @ingroup groupFilters + */ + +/** + * @defgroup Conv Convolution + * + * Convolution is a mathematical operation that operates on two finite length vectors to generate a finite length output vector. + * Convolution is similar to correlation and is frequently used in filtering and data analysis. + * The CMSIS DSP library contains functions for convolving Q7, Q15, Q31, and floating-point data types. + * The library also provides fast versions of the Q15 and Q31 functions on Cortex-M4 and Cortex-M3. + * + * \par Algorithm + * Let a[n] and b[n] be sequences of length srcALen and srcBLen samples respectively. + * Then the convolution + * + *
    
+ *                   c[n] = a[n] * b[n]    
+ * 
+ * + * \par + * is defined as + * \image html ConvolutionEquation.gif + * \par + * Note that c[n] is of length srcALen + srcBLen - 1 and is defined over the interval n=0, 1, 2, ..., srcALen + srcBLen - 2. + * pSrcA points to the first input vector of length srcALen and + * pSrcB points to the second input vector of length srcBLen. + * The output result is written to pDst and the calling function must allocate srcALen+srcBLen-1 words for the result. + * + * \par + * Conceptually, when two signals a[n] and b[n] are convolved, + * the signal b[n] slides over a[n]. + * For each offset \c n, the overlapping portions of a[n] and b[n] are multiplied and summed together. + * + * \par + * Note that convolution is a commutative operation: + * + *
    
+ *                   a[n] * b[n] = b[n] * a[n].    
+ * 
+ * + * \par + * This means that switching the A and B arguments to the convolution functions has no effect. + * + * Fixed-Point Behavior + * + * \par + * Convolution requires summing up a large number of intermediate products. + * As such, the Q7, Q15, and Q31 functions run a risk of overflow and saturation. + * Refer to the function specific documentation below for further details of the particular algorithm used. + * + * + * Fast Versions + * + * \par + * Fast versions are supported for Q31 and Q15. Cycles for Fast versions are less compared to Q31 and Q15 of conv and the design requires + * the input signals should be scaled down to avoid intermediate overflows. + * + * + * Opt Versions + * + * \par + * Opt versions are supported for Q15 and Q7. Design uses internal scratch buffer for getting good optimisation. + * These versions are optimised in cycles and consumes more memory(Scratch memory) compared to Q15 and Q7 versions + */ + +/** + * @addtogroup Conv + * @{ + */ + +/** + * @brief Convolution of floating-point sequences. + * @param[in] *pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] *pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] *pDst points to the location where the output result is written. Length srcALen+srcBLen-1. + * @return none. + */ + +void arm_conv_f32( + float32_t * pSrcA, + uint32_t srcALen, + float32_t * pSrcB, + uint32_t srcBLen, + float32_t * pDst) +{ + + +#ifndef ARM_MATH_CM0_FAMILY + + /* Run the below code for Cortex-M4 and Cortex-M3 */ + + float32_t *pIn1; /* inputA pointer */ + float32_t *pIn2; /* inputB pointer */ + float32_t *pOut = pDst; /* output pointer */ + float32_t *px; /* Intermediate inputA pointer */ + float32_t *py; /* Intermediate inputB pointer */ + float32_t *pSrc1, *pSrc2; /* Intermediate pointers */ + float32_t sum, acc0, acc1, acc2, acc3; /* Accumulator */ + float32_t x0, x1, x2, x3, c0; /* Temporary variables to hold state and coefficient values */ + uint32_t j, k, count, blkCnt, blockSize1, blockSize2, blockSize3; /* loop counters */ + + /* The algorithm implementation is based on the lengths of the inputs. */ + /* srcB is always made to slide across srcA. */ + /* So srcBLen is always considered as shorter or equal to srcALen */ + if(srcALen >= srcBLen) + { + /* Initialization of inputA pointer */ + pIn1 = pSrcA; + + /* Initialization of inputB pointer */ + pIn2 = pSrcB; + } + else + { + /* Initialization of inputA pointer */ + pIn1 = pSrcB; + + /* Initialization of inputB pointer */ + pIn2 = pSrcA; + + /* srcBLen is always considered as shorter or equal to srcALen */ + j = srcBLen; + srcBLen = srcALen; + srcALen = j; + } + + /* conv(x,y) at n = x[n] * y[0] + x[n-1] * y[1] + x[n-2] * y[2] + ...+ x[n-N+1] * y[N -1] */ + /* The function is internally + * divided into three stages according to the number of multiplications that has to be + * taken place between inputA samples and inputB samples. In the first stage of the + * algorithm, the multiplications increase by one for every iteration. + * In the second stage of the algorithm, srcBLen number of multiplications are done. + * In the third stage of the algorithm, the multiplications decrease by one + * for every iteration. */ + + /* The algorithm is implemented in three stages. + The loop counters of each stage is initiated here. */ + blockSize1 = srcBLen - 1u; + blockSize2 = srcALen - (srcBLen - 1u); + blockSize3 = blockSize1; + + /* -------------------------- + * initializations of stage1 + * -------------------------*/ + + /* sum = x[0] * y[0] + * sum = x[0] * y[1] + x[1] * y[0] + * .... + * sum = x[0] * y[srcBlen - 1] + x[1] * y[srcBlen - 2] +...+ x[srcBLen - 1] * y[0] + */ + + /* In this stage the MAC operations are increased by 1 for every iteration. + The count variable holds the number of MAC operations performed */ + count = 1u; + + /* Working pointer of inputA */ + px = pIn1; + + /* Working pointer of inputB */ + py = pIn2; + + + /* ------------------------ + * Stage1 process + * ----------------------*/ + + /* The first stage starts here */ + while(blockSize1 > 0u) + { + /* Accumulator is made zero for every iteration */ + sum = 0.0f; + + /* Apply loop unrolling and compute 4 MACs simultaneously. */ + k = count >> 2u; + + /* First part of the processing with loop unrolling. Compute 4 MACs at a time. + ** a second loop below computes MACs for the remaining 1 to 3 samples. */ + while(k > 0u) + { + /* x[0] * y[srcBLen - 1] */ + sum += *px++ * *py--; + + /* x[1] * y[srcBLen - 2] */ + sum += *px++ * *py--; + + /* x[2] * y[srcBLen - 3] */ + sum += *px++ * *py--; + + /* x[3] * y[srcBLen - 4] */ + sum += *px++ * *py--; + + /* Decrement the loop counter */ + k--; + } + + /* If the count is not a multiple of 4, compute any remaining MACs here. + ** No loop unrolling is used. */ + k = count % 0x4u; + + while(k > 0u) + { + /* Perform the multiply-accumulate */ + sum += *px++ * *py--; + + /* Decrement the loop counter */ + k--; + } + + /* Store the result in the accumulator in the destination buffer. */ + *pOut++ = sum; + + /* Update the inputA and inputB pointers for next MAC calculation */ + py = pIn2 + count; + px = pIn1; + + /* Increment the MAC count */ + count++; + + /* Decrement the loop counter */ + blockSize1--; + } + + /* -------------------------- + * Initializations of stage2 + * ------------------------*/ + + /* sum = x[0] * y[srcBLen-1] + x[1] * y[srcBLen-2] +...+ x[srcBLen-1] * y[0] + * sum = x[1] * y[srcBLen-1] + x[2] * y[srcBLen-2] +...+ x[srcBLen] * y[0] + * .... + * sum = x[srcALen-srcBLen-2] * y[srcBLen-1] + x[srcALen] * y[srcBLen-2] +...+ x[srcALen-1] * y[0] + */ + + /* Working pointer of inputA */ + px = pIn1; + + /* Working pointer of inputB */ + pSrc2 = pIn2 + (srcBLen - 1u); + py = pSrc2; + + /* count is index by which the pointer pIn1 to be incremented */ + count = 0u; + + /* ------------------- + * Stage2 process + * ------------------*/ + + /* Stage2 depends on srcBLen as in this stage srcBLen number of MACS are performed. + * So, to loop unroll over blockSize2, + * srcBLen should be greater than or equal to 4 */ + if(srcBLen >= 4u) + { + /* Loop unroll over blockSize2, by 4 */ + blkCnt = blockSize2 >> 2u; + + while(blkCnt > 0u) + { + /* Set all accumulators to zero */ + acc0 = 0.0f; + acc1 = 0.0f; + acc2 = 0.0f; + acc3 = 0.0f; + + /* read x[0], x[1], x[2] samples */ + x0 = *(px++); + x1 = *(px++); + x2 = *(px++); + + /* Apply loop unrolling and compute 4 MACs simultaneously. */ + k = srcBLen >> 2u; + + /* First part of the processing with loop unrolling. Compute 4 MACs at a time. + ** a second loop below computes MACs for the remaining 1 to 3 samples. */ + do + { + /* Read y[srcBLen - 1] sample */ + c0 = *(py--); + + /* Read x[3] sample */ + x3 = *(px); + + /* Perform the multiply-accumulate */ + /* acc0 += x[0] * y[srcBLen - 1] */ + acc0 += x0 * c0; + + /* acc1 += x[1] * y[srcBLen - 1] */ + acc1 += x1 * c0; + + /* acc2 += x[2] * y[srcBLen - 1] */ + acc2 += x2 * c0; + + /* acc3 += x[3] * y[srcBLen - 1] */ + acc3 += x3 * c0; + + /* Read y[srcBLen - 2] sample */ + c0 = *(py--); + + /* Read x[4] sample */ + x0 = *(px + 1u); + + /* Perform the multiply-accumulate */ + /* acc0 += x[1] * y[srcBLen - 2] */ + acc0 += x1 * c0; + /* acc1 += x[2] * y[srcBLen - 2] */ + acc1 += x2 * c0; + /* acc2 += x[3] * y[srcBLen - 2] */ + acc2 += x3 * c0; + /* acc3 += x[4] * y[srcBLen - 2] */ + acc3 += x0 * c0; + + /* Read y[srcBLen - 3] sample */ + c0 = *(py--); + + /* Read x[5] sample */ + x1 = *(px + 2u); + + /* Perform the multiply-accumulates */ + /* acc0 += x[2] * y[srcBLen - 3] */ + acc0 += x2 * c0; + /* acc1 += x[3] * y[srcBLen - 2] */ + acc1 += x3 * c0; + /* acc2 += x[4] * y[srcBLen - 2] */ + acc2 += x0 * c0; + /* acc3 += x[5] * y[srcBLen - 2] */ + acc3 += x1 * c0; + + /* Read y[srcBLen - 4] sample */ + c0 = *(py--); + + /* Read x[6] sample */ + x2 = *(px + 3u); + px += 4u; + + /* Perform the multiply-accumulates */ + /* acc0 += x[3] * y[srcBLen - 4] */ + acc0 += x3 * c0; + /* acc1 += x[4] * y[srcBLen - 4] */ + acc1 += x0 * c0; + /* acc2 += x[5] * y[srcBLen - 4] */ + acc2 += x1 * c0; + /* acc3 += x[6] * y[srcBLen - 4] */ + acc3 += x2 * c0; + + + } while(--k); + + /* If the srcBLen is not a multiple of 4, compute any remaining MACs here. + ** No loop unrolling is used. */ + k = srcBLen % 0x4u; + + while(k > 0u) + { + /* Read y[srcBLen - 5] sample */ + c0 = *(py--); + + /* Read x[7] sample */ + x3 = *(px++); + + /* Perform the multiply-accumulates */ + /* acc0 += x[4] * y[srcBLen - 5] */ + acc0 += x0 * c0; + /* acc1 += x[5] * y[srcBLen - 5] */ + acc1 += x1 * c0; + /* acc2 += x[6] * y[srcBLen - 5] */ + acc2 += x2 * c0; + /* acc3 += x[7] * y[srcBLen - 5] */ + acc3 += x3 * c0; + + /* Reuse the present samples for the next MAC */ + x0 = x1; + x1 = x2; + x2 = x3; + + /* Decrement the loop counter */ + k--; + } + + /* Store the result in the accumulator in the destination buffer. */ + *pOut++ = acc0; + *pOut++ = acc1; + *pOut++ = acc2; + *pOut++ = acc3; + + /* Increment the pointer pIn1 index, count by 4 */ + count += 4u; + + /* Update the inputA and inputB pointers for next MAC calculation */ + px = pIn1 + count; + py = pSrc2; + + + /* Decrement the loop counter */ + blkCnt--; + } + + + /* If the blockSize2 is not a multiple of 4, compute any remaining output samples here. + ** No loop unrolling is used. */ + blkCnt = blockSize2 % 0x4u; + + while(blkCnt > 0u) + { + /* Accumulator is made zero for every iteration */ + sum = 0.0f; + + /* Apply loop unrolling and compute 4 MACs simultaneously. */ + k = srcBLen >> 2u; + + /* First part of the processing with loop unrolling. Compute 4 MACs at a time. + ** a second loop below computes MACs for the remaining 1 to 3 samples. */ + while(k > 0u) + { + /* Perform the multiply-accumulates */ + sum += *px++ * *py--; + sum += *px++ * *py--; + sum += *px++ * *py--; + sum += *px++ * *py--; + + /* Decrement the loop counter */ + k--; + } + + /* If the srcBLen is not a multiple of 4, compute any remaining MACs here. + ** No loop unrolling is used. */ + k = srcBLen % 0x4u; + + while(k > 0u) + { + /* Perform the multiply-accumulate */ + sum += *px++ * *py--; + + /* Decrement the loop counter */ + k--; + } + + /* Store the result in the accumulator in the destination buffer. */ + *pOut++ = sum; + + /* Increment the MAC count */ + count++; + + /* Update the inputA and inputB pointers for next MAC calculation */ + px = pIn1 + count; + py = pSrc2; + + /* Decrement the loop counter */ + blkCnt--; + } + } + else + { + /* If the srcBLen is not a multiple of 4, + * the blockSize2 loop cannot be unrolled by 4 */ + blkCnt = blockSize2; + + while(blkCnt > 0u) + { + /* Accumulator is made zero for every iteration */ + sum = 0.0f; + + /* srcBLen number of MACS should be performed */ + k = srcBLen; + + while(k > 0u) + { + /* Perform the multiply-accumulate */ + sum += *px++ * *py--; + + /* Decrement the loop counter */ + k--; + } + + /* Store the result in the accumulator in the destination buffer. */ + *pOut++ = sum; + + /* Increment the MAC count */ + count++; + + /* Update the inputA and inputB pointers for next MAC calculation */ + px = pIn1 + count; + py = pSrc2; + + /* Decrement the loop counter */ + blkCnt--; + } + } + + + /* -------------------------- + * Initializations of stage3 + * -------------------------*/ + + /* sum += x[srcALen-srcBLen+1] * y[srcBLen-1] + x[srcALen-srcBLen+2] * y[srcBLen-2] +...+ x[srcALen-1] * y[1] + * sum += x[srcALen-srcBLen+2] * y[srcBLen-1] + x[srcALen-srcBLen+3] * y[srcBLen-2] +...+ x[srcALen-1] * y[2] + * .... + * sum += x[srcALen-2] * y[srcBLen-1] + x[srcALen-1] * y[srcBLen-2] + * sum += x[srcALen-1] * y[srcBLen-1] + */ + + /* In this stage the MAC operations are decreased by 1 for every iteration. + The blockSize3 variable holds the number of MAC operations performed */ + + /* Working pointer of inputA */ + pSrc1 = (pIn1 + srcALen) - (srcBLen - 1u); + px = pSrc1; + + /* Working pointer of inputB */ + pSrc2 = pIn2 + (srcBLen - 1u); + py = pSrc2; + + /* ------------------- + * Stage3 process + * ------------------*/ + + while(blockSize3 > 0u) + { + /* Accumulator is made zero for every iteration */ + sum = 0.0f; + + /* Apply loop unrolling and compute 4 MACs simultaneously. */ + k = blockSize3 >> 2u; + + /* First part of the processing with loop unrolling. Compute 4 MACs at a time. + ** a second loop below computes MACs for the remaining 1 to 3 samples. */ + while(k > 0u) + { + /* sum += x[srcALen - srcBLen + 1] * y[srcBLen - 1] */ + sum += *px++ * *py--; + + /* sum += x[srcALen - srcBLen + 2] * y[srcBLen - 2] */ + sum += *px++ * *py--; + + /* sum += x[srcALen - srcBLen + 3] * y[srcBLen - 3] */ + sum += *px++ * *py--; + + /* sum += x[srcALen - srcBLen + 4] * y[srcBLen - 4] */ + sum += *px++ * *py--; + + /* Decrement the loop counter */ + k--; + } + + /* If the blockSize3 is not a multiple of 4, compute any remaining MACs here. + ** No loop unrolling is used. */ + k = blockSize3 % 0x4u; + + while(k > 0u) + { + /* Perform the multiply-accumulates */ + /* sum += x[srcALen-1] * y[srcBLen-1] */ + sum += *px++ * *py--; + + /* Decrement the loop counter */ + k--; + } + + /* Store the result in the accumulator in the destination buffer. */ + *pOut++ = sum; + + /* Update the inputA and inputB pointers for next MAC calculation */ + px = ++pSrc1; + py = pSrc2; + + /* Decrement the loop counter */ + blockSize3--; + } + +#else + + /* Run the below code for Cortex-M0 */ + + float32_t *pIn1 = pSrcA; /* inputA pointer */ + float32_t *pIn2 = pSrcB; /* inputB pointer */ + float32_t sum; /* Accumulator */ + uint32_t i, j; /* loop counters */ + + /* Loop to calculate convolution for output length number of times */ + for (i = 0u; i < ((srcALen + srcBLen) - 1u); i++) + { + /* Initialize sum with zero to carry out MAC operations */ + sum = 0.0f; + + /* Loop to perform MAC operations according to convolution equation */ + for (j = 0u; j <= i; j++) + { + /* Check the array limitations */ + if((((i - j) < srcBLen) && (j < srcALen))) + { + /* z[i] += x[i-j] * y[j] */ + sum += pIn1[j] * pIn2[i - j]; + } + } + /* Store the output in the destination buffer */ + pDst[i] = sum; + } + +#endif /* #ifndef ARM_MATH_CM0_FAMILY */ + +} + +/** + * @} end of Conv group + */ diff --git a/gui/cmsis/arm_conv_q15.c b/gui/cmsis/arm_conv_q15.c new file mode 100644 index 0000000..8454a94 --- /dev/null +++ b/gui/cmsis/arm_conv_q15.c @@ -0,0 +1,734 @@ +/* ---------------------------------------------------------------------- +* Copyright (C) 2010-2014 ARM Limited. All rights reserved. +* +* $Date: 19. March 2015 +* $Revision: V.1.4.5 +* +* Project: CMSIS DSP Library +* Title: arm_conv_q15.c +* +* Description: Convolution of Q15 sequences. +* +* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0 +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* - Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* - Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* - Neither the name of ARM LIMITED nor the names of its contributors +* may be used to endorse or promote products derived from this +* software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* -------------------------------------------------------------------- */ + +#include "arm_math.h" + +/** + * @ingroup groupFilters + */ + +/** + * @addtogroup Conv + * @{ + */ + +/** + * @brief Convolution of Q15 sequences. + * @param[in] *pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] *pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] *pDst points to the location where the output result is written. Length srcALen+srcBLen-1. + * @return none. + * + * @details + * Scaling and Overflow Behavior: + * + * \par + * The function is implemented using a 64-bit internal accumulator. + * Both inputs are in 1.15 format and multiplications yield a 2.30 result. + * The 2.30 intermediate results are accumulated in a 64-bit accumulator in 34.30 format. + * This approach provides 33 guard bits and there is no risk of overflow. + * The 34.30 result is then truncated to 34.15 format by discarding the low 15 bits and then saturated to 1.15 format. + * + * \par + * Refer to arm_conv_fast_q15() for a faster but less precise version of this function for Cortex-M3 and Cortex-M4. + * + * \par + * Refer the function arm_conv_opt_q15() for a faster implementation of this function using scratch buffers. + * + */ + +void arm_conv_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst) +{ + +#if (defined(ARM_MATH_CM4) || defined(ARM_MATH_CM3)) && !defined(UNALIGNED_SUPPORT_DISABLE) + + /* Run the below code for Cortex-M4 and Cortex-M3 */ + + q15_t *pIn1; /* inputA pointer */ + q15_t *pIn2; /* inputB pointer */ + q15_t *pOut = pDst; /* output pointer */ + q63_t sum, acc0, acc1, acc2, acc3; /* Accumulator */ + q15_t *px; /* Intermediate inputA pointer */ + q15_t *py; /* Intermediate inputB pointer */ + q15_t *pSrc1, *pSrc2; /* Intermediate pointers */ + q31_t x0, x1, x2, x3, c0; /* Temporary variables to hold state and coefficient values */ + uint32_t blockSize1, blockSize2, blockSize3, j, k, count, blkCnt; /* loop counter */ + + /* The algorithm implementation is based on the lengths of the inputs. */ + /* srcB is always made to slide across srcA. */ + /* So srcBLen is always considered as shorter or equal to srcALen */ + if(srcALen >= srcBLen) + { + /* Initialization of inputA pointer */ + pIn1 = pSrcA; + + /* Initialization of inputB pointer */ + pIn2 = pSrcB; + } + else + { + /* Initialization of inputA pointer */ + pIn1 = pSrcB; + + /* Initialization of inputB pointer */ + pIn2 = pSrcA; + + /* srcBLen is always considered as shorter or equal to srcALen */ + j = srcBLen; + srcBLen = srcALen; + srcALen = j; + } + + /* conv(x,y) at n = x[n] * y[0] + x[n-1] * y[1] + x[n-2] * y[2] + ...+ x[n-N+1] * y[N -1] */ + /* The function is internally + * divided into three stages according to the number of multiplications that has to be + * taken place between inputA samples and inputB samples. In the first stage of the + * algorithm, the multiplications increase by one for every iteration. + * In the second stage of the algorithm, srcBLen number of multiplications are done. + * In the third stage of the algorithm, the multiplications decrease by one + * for every iteration. */ + + /* The algorithm is implemented in three stages. + The loop counters of each stage is initiated here. */ + blockSize1 = srcBLen - 1u; + blockSize2 = srcALen - (srcBLen - 1u); + + /* -------------------------- + * Initializations of stage1 + * -------------------------*/ + + /* sum = x[0] * y[0] + * sum = x[0] * y[1] + x[1] * y[0] + * .... + * sum = x[0] * y[srcBlen - 1] + x[1] * y[srcBlen - 2] +...+ x[srcBLen - 1] * y[0] + */ + + /* In this stage the MAC operations are increased by 1 for every iteration. + The count variable holds the number of MAC operations performed */ + count = 1u; + + /* Working pointer of inputA */ + px = pIn1; + + /* Working pointer of inputB */ + py = pIn2; + + + /* ------------------------ + * Stage1 process + * ----------------------*/ + + /* For loop unrolling by 4, this stage is divided into two. */ + /* First part of this stage computes the MAC operations less than 4 */ + /* Second part of this stage computes the MAC operations greater than or equal to 4 */ + + /* The first part of the stage starts here */ + while((count < 4u) && (blockSize1 > 0u)) + { + /* Accumulator is made zero for every iteration */ + sum = 0; + + /* Loop over number of MAC operations between + * inputA samples and inputB samples */ + k = count; + + while(k > 0u) + { + /* Perform the multiply-accumulates */ + sum = __SMLALD(*px++, *py--, sum); + + /* Decrement the loop counter */ + k--; + } + + /* Store the result in the accumulator in the destination buffer. */ + *pOut++ = (q15_t) (__SSAT((sum >> 15), 16)); + + /* Update the inputA and inputB pointers for next MAC calculation */ + py = pIn2 + count; + px = pIn1; + + /* Increment the MAC count */ + count++; + + /* Decrement the loop counter */ + blockSize1--; + } + + /* The second part of the stage starts here */ + /* The internal loop, over count, is unrolled by 4 */ + /* To, read the last two inputB samples using SIMD: + * y[srcBLen] and y[srcBLen-1] coefficients, py is decremented by 1 */ + py = py - 1; + + while(blockSize1 > 0u) + { + /* Accumulator is made zero for every iteration */ + sum = 0; + + /* Apply loop unrolling and compute 4 MACs simultaneously. */ + k = count >> 2u; + + /* First part of the processing with loop unrolling. Compute 4 MACs at a time. + ** a second loop below computes MACs for the remaining 1 to 3 samples. */ + while(k > 0u) + { + /* Perform the multiply-accumulates */ + /* x[0], x[1] are multiplied with y[srcBLen - 1], y[srcBLen - 2] respectively */ + sum = __SMLALDX(*__SIMD32(px)++, *__SIMD32(py)--, sum); + /* x[2], x[3] are multiplied with y[srcBLen - 3], y[srcBLen - 4] respectively */ + sum = __SMLALDX(*__SIMD32(px)++, *__SIMD32(py)--, sum); + + /* Decrement the loop counter */ + k--; + } + + /* For the next MAC operations, the pointer py is used without SIMD + * So, py is incremented by 1 */ + py = py + 1u; + + /* If the count is not a multiple of 4, compute any remaining MACs here. + ** No loop unrolling is used. */ + k = count % 0x4u; + + while(k > 0u) + { + /* Perform the multiply-accumulates */ + sum = __SMLALD(*px++, *py--, sum); + + /* Decrement the loop counter */ + k--; + } + + /* Store the result in the accumulator in the destination buffer. */ + *pOut++ = (q15_t) (__SSAT((sum >> 15), 16)); + + /* Update the inputA and inputB pointers for next MAC calculation */ + py = pIn2 + (count - 1u); + px = pIn1; + + /* Increment the MAC count */ + count++; + + /* Decrement the loop counter */ + blockSize1--; + } + + /* -------------------------- + * Initializations of stage2 + * ------------------------*/ + + /* sum = x[0] * y[srcBLen-1] + x[1] * y[srcBLen-2] +...+ x[srcBLen-1] * y[0] + * sum = x[1] * y[srcBLen-1] + x[2] * y[srcBLen-2] +...+ x[srcBLen] * y[0] + * .... + * sum = x[srcALen-srcBLen-2] * y[srcBLen-1] + x[srcALen] * y[srcBLen-2] +...+ x[srcALen-1] * y[0] + */ + + /* Working pointer of inputA */ + px = pIn1; + + /* Working pointer of inputB */ + pSrc2 = pIn2 + (srcBLen - 1u); + py = pSrc2; + + /* count is the index by which the pointer pIn1 to be incremented */ + count = 0u; + + + /* -------------------- + * Stage2 process + * -------------------*/ + + /* Stage2 depends on srcBLen as in this stage srcBLen number of MACS are performed. + * So, to loop unroll over blockSize2, + * srcBLen should be greater than or equal to 4 */ + if(srcBLen >= 4u) + { + /* Loop unroll over blockSize2, by 4 */ + blkCnt = blockSize2 >> 2u; + + while(blkCnt > 0u) + { + py = py - 1u; + + /* Set all accumulators to zero */ + acc0 = 0; + acc1 = 0; + acc2 = 0; + acc3 = 0; + + + /* read x[0], x[1] samples */ + x0 = *__SIMD32(px); + /* read x[1], x[2] samples */ + x1 = _SIMD32_OFFSET(px+1); + px+= 2u; + + + /* Apply loop unrolling and compute 4 MACs simultaneously. */ + k = srcBLen >> 2u; + + /* First part of the processing with loop unrolling. Compute 4 MACs at a time. + ** a second loop below computes MACs for the remaining 1 to 3 samples. */ + do + { + /* Read the last two inputB samples using SIMD: + * y[srcBLen - 1] and y[srcBLen - 2] */ + c0 = *__SIMD32(py)--; + + /* acc0 += x[0] * y[srcBLen - 1] + x[1] * y[srcBLen - 2] */ + acc0 = __SMLALDX(x0, c0, acc0); + + /* acc1 += x[1] * y[srcBLen - 1] + x[2] * y[srcBLen - 2] */ + acc1 = __SMLALDX(x1, c0, acc1); + + /* Read x[2], x[3] */ + x2 = *__SIMD32(px); + + /* Read x[3], x[4] */ + x3 = _SIMD32_OFFSET(px+1); + + /* acc2 += x[2] * y[srcBLen - 1] + x[3] * y[srcBLen - 2] */ + acc2 = __SMLALDX(x2, c0, acc2); + + /* acc3 += x[3] * y[srcBLen - 1] + x[4] * y[srcBLen - 2] */ + acc3 = __SMLALDX(x3, c0, acc3); + + /* Read y[srcBLen - 3] and y[srcBLen - 4] */ + c0 = *__SIMD32(py)--; + + /* acc0 += x[2] * y[srcBLen - 3] + x[3] * y[srcBLen - 4] */ + acc0 = __SMLALDX(x2, c0, acc0); + + /* acc1 += x[3] * y[srcBLen - 3] + x[4] * y[srcBLen - 4] */ + acc1 = __SMLALDX(x3, c0, acc1); + + /* Read x[4], x[5] */ + x0 = _SIMD32_OFFSET(px+2); + + /* Read x[5], x[6] */ + x1 = _SIMD32_OFFSET(px+3); + px += 4u; + + /* acc2 += x[4] * y[srcBLen - 3] + x[5] * y[srcBLen - 4] */ + acc2 = __SMLALDX(x0, c0, acc2); + + /* acc3 += x[5] * y[srcBLen - 3] + x[6] * y[srcBLen - 4] */ + acc3 = __SMLALDX(x1, c0, acc3); + + } while(--k); + + /* For the next MAC operations, SIMD is not used + * So, the 16 bit pointer if inputB, py is updated */ + + /* If the srcBLen is not a multiple of 4, compute any remaining MACs here. + ** No loop unrolling is used. */ + k = srcBLen % 0x4u; + + if(k == 1u) + { + /* Read y[srcBLen - 5] */ + c0 = *(py+1); + +#ifdef ARM_MATH_BIG_ENDIAN + + c0 = c0 << 16u; + +#else + + c0 = c0 & 0x0000FFFF; + +#endif /* #ifdef ARM_MATH_BIG_ENDIAN */ + /* Read x[7] */ + x3 = *__SIMD32(px); + px++; + + /* Perform the multiply-accumulates */ + acc0 = __SMLALD(x0, c0, acc0); + acc1 = __SMLALD(x1, c0, acc1); + acc2 = __SMLALDX(x1, c0, acc2); + acc3 = __SMLALDX(x3, c0, acc3); + } + + if(k == 2u) + { + /* Read y[srcBLen - 5], y[srcBLen - 6] */ + c0 = _SIMD32_OFFSET(py); + + /* Read x[7], x[8] */ + x3 = *__SIMD32(px); + + /* Read x[9] */ + x2 = _SIMD32_OFFSET(px+1); + px += 2u; + + /* Perform the multiply-accumulates */ + acc0 = __SMLALDX(x0, c0, acc0); + acc1 = __SMLALDX(x1, c0, acc1); + acc2 = __SMLALDX(x3, c0, acc2); + acc3 = __SMLALDX(x2, c0, acc3); + } + + if(k == 3u) + { + /* Read y[srcBLen - 5], y[srcBLen - 6] */ + c0 = _SIMD32_OFFSET(py); + + /* Read x[7], x[8] */ + x3 = *__SIMD32(px); + + /* Read x[9] */ + x2 = _SIMD32_OFFSET(px+1); + + /* Perform the multiply-accumulates */ + acc0 = __SMLALDX(x0, c0, acc0); + acc1 = __SMLALDX(x1, c0, acc1); + acc2 = __SMLALDX(x3, c0, acc2); + acc3 = __SMLALDX(x2, c0, acc3); + + c0 = *(py-1); + +#ifdef ARM_MATH_BIG_ENDIAN + + c0 = c0 << 16u; +#else + + c0 = c0 & 0x0000FFFF; +#endif /* #ifdef ARM_MATH_BIG_ENDIAN */ + /* Read x[10] */ + x3 = _SIMD32_OFFSET(px+2); + px += 3u; + + /* Perform the multiply-accumulates */ + acc0 = __SMLALDX(x1, c0, acc0); + acc1 = __SMLALD(x2, c0, acc1); + acc2 = __SMLALDX(x2, c0, acc2); + acc3 = __SMLALDX(x3, c0, acc3); + } + + + /* Store the results in the accumulators in the destination buffer. */ + +#ifndef ARM_MATH_BIG_ENDIAN + + *__SIMD32(pOut)++ = + __PKHBT(__SSAT((acc0 >> 15), 16), __SSAT((acc1 >> 15), 16), 16); + *__SIMD32(pOut)++ = + __PKHBT(__SSAT((acc2 >> 15), 16), __SSAT((acc3 >> 15), 16), 16); + +#else + + *__SIMD32(pOut)++ = + __PKHBT(__SSAT((acc1 >> 15), 16), __SSAT((acc0 >> 15), 16), 16); + *__SIMD32(pOut)++ = + __PKHBT(__SSAT((acc3 >> 15), 16), __SSAT((acc2 >> 15), 16), 16); + +#endif /* #ifndef ARM_MATH_BIG_ENDIAN */ + + /* Increment the pointer pIn1 index, count by 4 */ + count += 4u; + + /* Update the inputA and inputB pointers for next MAC calculation */ + px = pIn1 + count; + py = pSrc2; + + /* Decrement the loop counter */ + blkCnt--; + } + + /* If the blockSize2 is not a multiple of 4, compute any remaining output samples here. + ** No loop unrolling is used. */ + blkCnt = blockSize2 % 0x4u; + + while(blkCnt > 0u) + { + /* Accumulator is made zero for every iteration */ + sum = 0; + + /* Apply loop unrolling and compute 4 MACs simultaneously. */ + k = srcBLen >> 2u; + + /* First part of the processing with loop unrolling. Compute 4 MACs at a time. + ** a second loop below computes MACs for the remaining 1 to 3 samples. */ + while(k > 0u) + { + /* Perform the multiply-accumulates */ + sum += (q63_t) ((q31_t) * px++ * *py--); + sum += (q63_t) ((q31_t) * px++ * *py--); + sum += (q63_t) ((q31_t) * px++ * *py--); + sum += (q63_t) ((q31_t) * px++ * *py--); + + /* Decrement the loop counter */ + k--; + } + + /* If the srcBLen is not a multiple of 4, compute any remaining MACs here. + ** No loop unrolling is used. */ + k = srcBLen % 0x4u; + + while(k > 0u) + { + /* Perform the multiply-accumulates */ + sum += (q63_t) ((q31_t) * px++ * *py--); + + /* Decrement the loop counter */ + k--; + } + + /* Store the result in the accumulator in the destination buffer. */ + *pOut++ = (q15_t) (__SSAT(sum >> 15, 16)); + + /* Increment the pointer pIn1 index, count by 1 */ + count++; + + /* Update the inputA and inputB pointers for next MAC calculation */ + px = pIn1 + count; + py = pSrc2; + + /* Decrement the loop counter */ + blkCnt--; + } + } + else + { + /* If the srcBLen is not a multiple of 4, + * the blockSize2 loop cannot be unrolled by 4 */ + blkCnt = blockSize2; + + while(blkCnt > 0u) + { + /* Accumulator is made zero for every iteration */ + sum = 0; + + /* srcBLen number of MACS should be performed */ + k = srcBLen; + + while(k > 0u) + { + /* Perform the multiply-accumulate */ + sum += (q63_t) ((q31_t) * px++ * *py--); + + /* Decrement the loop counter */ + k--; + } + + /* Store the result in the accumulator in the destination buffer. */ + *pOut++ = (q15_t) (__SSAT(sum >> 15, 16)); + + /* Increment the MAC count */ + count++; + + /* Update the inputA and inputB pointers for next MAC calculation */ + px = pIn1 + count; + py = pSrc2; + + /* Decrement the loop counter */ + blkCnt--; + } + } + + + /* -------------------------- + * Initializations of stage3 + * -------------------------*/ + + /* sum += x[srcALen-srcBLen+1] * y[srcBLen-1] + x[srcALen-srcBLen+2] * y[srcBLen-2] +...+ x[srcALen-1] * y[1] + * sum += x[srcALen-srcBLen+2] * y[srcBLen-1] + x[srcALen-srcBLen+3] * y[srcBLen-2] +...+ x[srcALen-1] * y[2] + * .... + * sum += x[srcALen-2] * y[srcBLen-1] + x[srcALen-1] * y[srcBLen-2] + * sum += x[srcALen-1] * y[srcBLen-1] + */ + + /* In this stage the MAC operations are decreased by 1 for every iteration. + The blockSize3 variable holds the number of MAC operations performed */ + + blockSize3 = srcBLen - 1u; + + /* Working pointer of inputA */ + pSrc1 = (pIn1 + srcALen) - (srcBLen - 1u); + px = pSrc1; + + /* Working pointer of inputB */ + pSrc2 = pIn2 + (srcBLen - 1u); + pIn2 = pSrc2 - 1u; + py = pIn2; + + /* ------------------- + * Stage3 process + * ------------------*/ + + /* For loop unrolling by 4, this stage is divided into two. */ + /* First part of this stage computes the MAC operations greater than 4 */ + /* Second part of this stage computes the MAC operations less than or equal to 4 */ + + /* The first part of the stage starts here */ + j = blockSize3 >> 2u; + + while((j > 0u) && (blockSize3 > 0u)) + { + /* Accumulator is made zero for every iteration */ + sum = 0; + + /* Apply loop unrolling and compute 4 MACs simultaneously. */ + k = blockSize3 >> 2u; + + /* First part of the processing with loop unrolling. Compute 4 MACs at a time. + ** a second loop below computes MACs for the remaining 1 to 3 samples. */ + while(k > 0u) + { + /* x[srcALen - srcBLen + 1], x[srcALen - srcBLen + 2] are multiplied + * with y[srcBLen - 1], y[srcBLen - 2] respectively */ + sum = __SMLALDX(*__SIMD32(px)++, *__SIMD32(py)--, sum); + /* x[srcALen - srcBLen + 3], x[srcALen - srcBLen + 4] are multiplied + * with y[srcBLen - 3], y[srcBLen - 4] respectively */ + sum = __SMLALDX(*__SIMD32(px)++, *__SIMD32(py)--, sum); + + /* Decrement the loop counter */ + k--; + } + + /* For the next MAC operations, the pointer py is used without SIMD + * So, py is incremented by 1 */ + py = py + 1u; + + /* If the blockSize3 is not a multiple of 4, compute any remaining MACs here. + ** No loop unrolling is used. */ + k = blockSize3 % 0x4u; + + while(k > 0u) + { + /* sum += x[srcALen - srcBLen + 5] * y[srcBLen - 5] */ + sum = __SMLALD(*px++, *py--, sum); + + /* Decrement the loop counter */ + k--; + } + + /* Store the result in the accumulator in the destination buffer. */ + *pOut++ = (q15_t) (__SSAT((sum >> 15), 16)); + + /* Update the inputA and inputB pointers for next MAC calculation */ + px = ++pSrc1; + py = pIn2; + + /* Decrement the loop counter */ + blockSize3--; + + j--; + } + + /* The second part of the stage starts here */ + /* SIMD is not used for the next MAC operations, + * so pointer py is updated to read only one sample at a time */ + py = py + 1u; + + while(blockSize3 > 0u) + { + /* Accumulator is made zero for every iteration */ + sum = 0; + + /* Apply loop unrolling and compute 4 MACs simultaneously. */ + k = blockSize3; + + while(k > 0u) + { + /* Perform the multiply-accumulates */ + /* sum += x[srcALen-1] * y[srcBLen-1] */ + sum = __SMLALD(*px++, *py--, sum); + + /* Decrement the loop counter */ + k--; + } + + /* Store the result in the accumulator in the destination buffer. */ + *pOut++ = (q15_t) (__SSAT((sum >> 15), 16)); + + /* Update the inputA and inputB pointers for next MAC calculation */ + px = ++pSrc1; + py = pSrc2; + + /* Decrement the loop counter */ + blockSize3--; + } + +#else + +/* Run the below code for Cortex-M0 */ + + q15_t *pIn1 = pSrcA; /* input pointer */ + q15_t *pIn2 = pSrcB; /* coefficient pointer */ + q63_t sum; /* Accumulator */ + uint32_t i, j; /* loop counter */ + + /* Loop to calculate output of convolution for output length number of times */ + for (i = 0; i < (srcALen + srcBLen - 1); i++) + { + /* Initialize sum with zero to carry on MAC operations */ + sum = 0; + + /* Loop to perform MAC operations according to convolution equation */ + for (j = 0; j <= i; j++) + { + /* Check the array limitations */ + if(((i - j) < srcBLen) && (j < srcALen)) + { + /* z[i] += x[i-j] * y[j] */ + sum += (q31_t) pIn1[j] * (pIn2[i - j]); + } + } + + /* Store the output in the destination buffer */ + pDst[i] = (q15_t) __SSAT((sum >> 15u), 16u); + } + +#endif /* #if (defined(ARM_MATH_CM4) || defined(ARM_MATH_CM3)) && !defined(UNALIGNED_SUPPORT_DISABLE)*/ + +} + +/** + * @} end of Conv group + */ diff --git a/gui/cmsis/arm_conv_q31.c b/gui/cmsis/arm_conv_q31.c new file mode 100644 index 0000000..ffa972f --- /dev/null +++ b/gui/cmsis/arm_conv_q31.c @@ -0,0 +1,565 @@ +/* ---------------------------------------------------------------------- +* Copyright (C) 2010-2014 ARM Limited. All rights reserved. +* +* $Date: 19. March 2015 +* $Revision: V.1.4.5 +* +* Project: CMSIS DSP Library +* Title: arm_conv_q31.c +* +* Description: Convolution of Q31 sequences. +* +* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0 +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* - Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* - Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* - Neither the name of ARM LIMITED nor the names of its contributors +* may be used to endorse or promote products derived from this +* software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* -------------------------------------------------------------------- */ + +#include "arm_math.h" + +/** + * @ingroup groupFilters + */ + +/** + * @addtogroup Conv + * @{ + */ + +/** + * @brief Convolution of Q31 sequences. + * @param[in] *pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] *pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] *pDst points to the location where the output result is written. Length srcALen+srcBLen-1. + * @return none. + * + * @details + * Scaling and Overflow Behavior: + * + * \par + * The function is implemented using an internal 64-bit accumulator. + * The accumulator has a 2.62 format and maintains full precision of the intermediate multiplication results but provides only a single guard bit. + * There is no saturation on intermediate additions. + * Thus, if the accumulator overflows it wraps around and distorts the result. + * The input signals should be scaled down to avoid intermediate overflows. + * Scale down the inputs by log2(min(srcALen, srcBLen)) (log2 is read as log to the base 2) times to avoid overflows, + * as maximum of min(srcALen, srcBLen) number of additions are carried internally. + * The 2.62 accumulator is right shifted by 31 bits and saturated to 1.31 format to yield the final result. + * + * \par + * See arm_conv_fast_q31() for a faster but less precise implementation of this function for Cortex-M3 and Cortex-M4. + */ + +void arm_conv_q31( + q31_t * pSrcA, + uint32_t srcALen, + q31_t * pSrcB, + uint32_t srcBLen, + q31_t * pDst) +{ + + +#ifndef ARM_MATH_CM0_FAMILY + + /* Run the below code for Cortex-M4 and Cortex-M3 */ + + q31_t *pIn1; /* inputA pointer */ + q31_t *pIn2; /* inputB pointer */ + q31_t *pOut = pDst; /* output pointer */ + q31_t *px; /* Intermediate inputA pointer */ + q31_t *py; /* Intermediate inputB pointer */ + q31_t *pSrc1, *pSrc2; /* Intermediate pointers */ + q63_t sum; /* Accumulator */ + q63_t acc0, acc1, acc2; /* Accumulator */ + q31_t x0, x1, x2, c0; /* Temporary variables to hold state and coefficient values */ + uint32_t j, k, count, blkCnt, blockSize1, blockSize2, blockSize3; /* loop counter */ + + /* The algorithm implementation is based on the lengths of the inputs. */ + /* srcB is always made to slide across srcA. */ + /* So srcBLen is always considered as shorter or equal to srcALen */ + if(srcALen >= srcBLen) + { + /* Initialization of inputA pointer */ + pIn1 = pSrcA; + + /* Initialization of inputB pointer */ + pIn2 = pSrcB; + } + else + { + /* Initialization of inputA pointer */ + pIn1 = (q31_t *) pSrcB; + + /* Initialization of inputB pointer */ + pIn2 = (q31_t *) pSrcA; + + /* srcBLen is always considered as shorter or equal to srcALen */ + j = srcBLen; + srcBLen = srcALen; + srcALen = j; + } + + /* conv(x,y) at n = x[n] * y[0] + x[n-1] * y[1] + x[n-2] * y[2] + ...+ x[n-N+1] * y[N -1] */ + /* The function is internally + * divided into three stages according to the number of multiplications that has to be + * taken place between inputA samples and inputB samples. In the first stage of the + * algorithm, the multiplications increase by one for every iteration. + * In the second stage of the algorithm, srcBLen number of multiplications are done. + * In the third stage of the algorithm, the multiplications decrease by one + * for every iteration. */ + + /* The algorithm is implemented in three stages. + The loop counters of each stage is initiated here. */ + blockSize1 = srcBLen - 1u; + blockSize2 = srcALen - (srcBLen - 1u); + blockSize3 = blockSize1; + + /* -------------------------- + * Initializations of stage1 + * -------------------------*/ + + /* sum = x[0] * y[0] + * sum = x[0] * y[1] + x[1] * y[0] + * .... + * sum = x[0] * y[srcBlen - 1] + x[1] * y[srcBlen - 2] +...+ x[srcBLen - 1] * y[0] + */ + + /* In this stage the MAC operations are increased by 1 for every iteration. + The count variable holds the number of MAC operations performed */ + count = 1u; + + /* Working pointer of inputA */ + px = pIn1; + + /* Working pointer of inputB */ + py = pIn2; + + + /* ------------------------ + * Stage1 process + * ----------------------*/ + + /* The first stage starts here */ + while(blockSize1 > 0u) + { + /* Accumulator is made zero for every iteration */ + sum = 0; + + /* Apply loop unrolling and compute 4 MACs simultaneously. */ + k = count >> 2u; + + /* First part of the processing with loop unrolling. Compute 4 MACs at a time. + ** a second loop below computes MACs for the remaining 1 to 3 samples. */ + while(k > 0u) + { + /* x[0] * y[srcBLen - 1] */ + sum += (q63_t) * px++ * (*py--); + /* x[1] * y[srcBLen - 2] */ + sum += (q63_t) * px++ * (*py--); + /* x[2] * y[srcBLen - 3] */ + sum += (q63_t) * px++ * (*py--); + /* x[3] * y[srcBLen - 4] */ + sum += (q63_t) * px++ * (*py--); + + /* Decrement the loop counter */ + k--; + } + + /* If the count is not a multiple of 4, compute any remaining MACs here. + ** No loop unrolling is used. */ + k = count % 0x4u; + + while(k > 0u) + { + /* Perform the multiply-accumulate */ + sum += (q63_t) * px++ * (*py--); + + /* Decrement the loop counter */ + k--; + } + + /* Store the result in the accumulator in the destination buffer. */ + *pOut++ = (q31_t) (sum >> 31); + + /* Update the inputA and inputB pointers for next MAC calculation */ + py = pIn2 + count; + px = pIn1; + + /* Increment the MAC count */ + count++; + + /* Decrement the loop counter */ + blockSize1--; + } + + /* -------------------------- + * Initializations of stage2 + * ------------------------*/ + + /* sum = x[0] * y[srcBLen-1] + x[1] * y[srcBLen-2] +...+ x[srcBLen-1] * y[0] + * sum = x[1] * y[srcBLen-1] + x[2] * y[srcBLen-2] +...+ x[srcBLen] * y[0] + * .... + * sum = x[srcALen-srcBLen-2] * y[srcBLen-1] + x[srcALen] * y[srcBLen-2] +...+ x[srcALen-1] * y[0] + */ + + /* Working pointer of inputA */ + px = pIn1; + + /* Working pointer of inputB */ + pSrc2 = pIn2 + (srcBLen - 1u); + py = pSrc2; + + /* count is index by which the pointer pIn1 to be incremented */ + count = 0u; + + /* ------------------- + * Stage2 process + * ------------------*/ + + /* Stage2 depends on srcBLen as in this stage srcBLen number of MACS are performed. + * So, to loop unroll over blockSize2, + * srcBLen should be greater than or equal to 4 */ + if(srcBLen >= 4u) + { + /* Loop unroll by 3 */ + blkCnt = blockSize2 / 3; + + while(blkCnt > 0u) + { + /* Set all accumulators to zero */ + acc0 = 0; + acc1 = 0; + acc2 = 0; + + /* read x[0], x[1], x[2] samples */ + x0 = *(px++); + x1 = *(px++); + + /* Apply loop unrolling and compute 3 MACs simultaneously. */ + k = srcBLen / 3; + + /* First part of the processing with loop unrolling. Compute 3 MACs at a time. + ** a second loop below computes MACs for the remaining 1 to 2 samples. */ + do + { + /* Read y[srcBLen - 1] sample */ + c0 = *(py); + + /* Read x[3] sample */ + x2 = *(px); + + /* Perform the multiply-accumulates */ + /* acc0 += x[0] * y[srcBLen - 1] */ + acc0 += ((q63_t) x0 * c0); + /* acc1 += x[1] * y[srcBLen - 1] */ + acc1 += ((q63_t) x1 * c0); + /* acc2 += x[2] * y[srcBLen - 1] */ + acc2 += ((q63_t) x2 * c0); + + /* Read y[srcBLen - 2] sample */ + c0 = *(py - 1u); + + /* Read x[4] sample */ + x0 = *(px + 1u); + + /* Perform the multiply-accumulate */ + /* acc0 += x[1] * y[srcBLen - 2] */ + acc0 += ((q63_t) x1 * c0); + /* acc1 += x[2] * y[srcBLen - 2] */ + acc1 += ((q63_t) x2 * c0); + /* acc2 += x[3] * y[srcBLen - 2] */ + acc2 += ((q63_t) x0 * c0); + + /* Read y[srcBLen - 3] sample */ + c0 = *(py - 2u); + + /* Read x[5] sample */ + x1 = *(px + 2u); + + /* Perform the multiply-accumulates */ + /* acc0 += x[2] * y[srcBLen - 3] */ + acc0 += ((q63_t) x2 * c0); + /* acc1 += x[3] * y[srcBLen - 2] */ + acc1 += ((q63_t) x0 * c0); + /* acc2 += x[4] * y[srcBLen - 2] */ + acc2 += ((q63_t) x1 * c0); + + /* update scratch pointers */ + px += 3u; + py -= 3u; + + } while(--k); + + /* If the srcBLen is not a multiple of 3, compute any remaining MACs here. + ** No loop unrolling is used. */ + k = srcBLen - (3 * (srcBLen / 3)); + + while(k > 0u) + { + /* Read y[srcBLen - 5] sample */ + c0 = *(py--); + + /* Read x[7] sample */ + x2 = *(px++); + + /* Perform the multiply-accumulates */ + /* acc0 += x[4] * y[srcBLen - 5] */ + acc0 += ((q63_t) x0 * c0); + /* acc1 += x[5] * y[srcBLen - 5] */ + acc1 += ((q63_t) x1 * c0); + /* acc2 += x[6] * y[srcBLen - 5] */ + acc2 += ((q63_t) x2 * c0); + + /* Reuse the present samples for the next MAC */ + x0 = x1; + x1 = x2; + + /* Decrement the loop counter */ + k--; + } + + /* Store the results in the accumulators in the destination buffer. */ + *pOut++ = (q31_t) (acc0 >> 31); + *pOut++ = (q31_t) (acc1 >> 31); + *pOut++ = (q31_t) (acc2 >> 31); + + /* Increment the pointer pIn1 index, count by 3 */ + count += 3u; + + /* Update the inputA and inputB pointers for next MAC calculation */ + px = pIn1 + count; + py = pSrc2; + + /* Decrement the loop counter */ + blkCnt--; + } + + /* If the blockSize2 is not a multiple of 3, compute any remaining output samples here. + ** No loop unrolling is used. */ + blkCnt = blockSize2 - 3 * (blockSize2 / 3); + + while(blkCnt > 0u) + { + /* Accumulator is made zero for every iteration */ + sum = 0; + + /* Apply loop unrolling and compute 4 MACs simultaneously. */ + k = srcBLen >> 2u; + + /* First part of the processing with loop unrolling. Compute 4 MACs at a time. + ** a second loop below computes MACs for the remaining 1 to 3 samples. */ + while(k > 0u) + { + /* Perform the multiply-accumulates */ + sum += (q63_t) * px++ * (*py--); + sum += (q63_t) * px++ * (*py--); + sum += (q63_t) * px++ * (*py--); + sum += (q63_t) * px++ * (*py--); + + /* Decrement the loop counter */ + k--; + } + + /* If the srcBLen is not a multiple of 4, compute any remaining MACs here. + ** No loop unrolling is used. */ + k = srcBLen % 0x4u; + + while(k > 0u) + { + /* Perform the multiply-accumulate */ + sum += (q63_t) * px++ * (*py--); + + /* Decrement the loop counter */ + k--; + } + + /* Store the result in the accumulator in the destination buffer. */ + *pOut++ = (q31_t) (sum >> 31); + + /* Increment the MAC count */ + count++; + + /* Update the inputA and inputB pointers for next MAC calculation */ + px = pIn1 + count; + py = pSrc2; + + /* Decrement the loop counter */ + blkCnt--; + } + } + else + { + /* If the srcBLen is not a multiple of 4, + * the blockSize2 loop cannot be unrolled by 4 */ + blkCnt = blockSize2; + + while(blkCnt > 0u) + { + /* Accumulator is made zero for every iteration */ + sum = 0; + + /* srcBLen number of MACS should be performed */ + k = srcBLen; + + while(k > 0u) + { + /* Perform the multiply-accumulate */ + sum += (q63_t) * px++ * (*py--); + + /* Decrement the loop counter */ + k--; + } + + /* Store the result in the accumulator in the destination buffer. */ + *pOut++ = (q31_t) (sum >> 31); + + /* Increment the MAC count */ + count++; + + /* Update the inputA and inputB pointers for next MAC calculation */ + px = pIn1 + count; + py = pSrc2; + + /* Decrement the loop counter */ + blkCnt--; + } + } + + + /* -------------------------- + * Initializations of stage3 + * -------------------------*/ + + /* sum += x[srcALen-srcBLen+1] * y[srcBLen-1] + x[srcALen-srcBLen+2] * y[srcBLen-2] +...+ x[srcALen-1] * y[1] + * sum += x[srcALen-srcBLen+2] * y[srcBLen-1] + x[srcALen-srcBLen+3] * y[srcBLen-2] +...+ x[srcALen-1] * y[2] + * .... + * sum += x[srcALen-2] * y[srcBLen-1] + x[srcALen-1] * y[srcBLen-2] + * sum += x[srcALen-1] * y[srcBLen-1] + */ + + /* In this stage the MAC operations are decreased by 1 for every iteration. + The blockSize3 variable holds the number of MAC operations performed */ + + /* Working pointer of inputA */ + pSrc1 = (pIn1 + srcALen) - (srcBLen - 1u); + px = pSrc1; + + /* Working pointer of inputB */ + pSrc2 = pIn2 + (srcBLen - 1u); + py = pSrc2; + + /* ------------------- + * Stage3 process + * ------------------*/ + + while(blockSize3 > 0u) + { + /* Accumulator is made zero for every iteration */ + sum = 0; + + /* Apply loop unrolling and compute 4 MACs simultaneously. */ + k = blockSize3 >> 2u; + + /* First part of the processing with loop unrolling. Compute 4 MACs at a time. + ** a second loop below computes MACs for the remaining 1 to 3 samples. */ + while(k > 0u) + { + /* sum += x[srcALen - srcBLen + 1] * y[srcBLen - 1] */ + sum += (q63_t) * px++ * (*py--); + /* sum += x[srcALen - srcBLen + 2] * y[srcBLen - 2] */ + sum += (q63_t) * px++ * (*py--); + /* sum += x[srcALen - srcBLen + 3] * y[srcBLen - 3] */ + sum += (q63_t) * px++ * (*py--); + /* sum += x[srcALen - srcBLen + 4] * y[srcBLen - 4] */ + sum += (q63_t) * px++ * (*py--); + + /* Decrement the loop counter */ + k--; + } + + /* If the blockSize3 is not a multiple of 4, compute any remaining MACs here. + ** No loop unrolling is used. */ + k = blockSize3 % 0x4u; + + while(k > 0u) + { + /* Perform the multiply-accumulate */ + sum += (q63_t) * px++ * (*py--); + + /* Decrement the loop counter */ + k--; + } + + /* Store the result in the accumulator in the destination buffer. */ + *pOut++ = (q31_t) (sum >> 31); + + /* Update the inputA and inputB pointers for next MAC calculation */ + px = ++pSrc1; + py = pSrc2; + + /* Decrement the loop counter */ + blockSize3--; + } + +#else + + /* Run the below code for Cortex-M0 */ + + q31_t *pIn1 = pSrcA; /* input pointer */ + q31_t *pIn2 = pSrcB; /* coefficient pointer */ + q63_t sum; /* Accumulator */ + uint32_t i, j; /* loop counter */ + + /* Loop to calculate output of convolution for output length number of times */ + for (i = 0; i < (srcALen + srcBLen - 1); i++) + { + /* Initialize sum with zero to carry on MAC operations */ + sum = 0; + + /* Loop to perform MAC operations according to convolution equation */ + for (j = 0; j <= i; j++) + { + /* Check the array limitations */ + if(((i - j) < srcBLen) && (j < srcALen)) + { + /* z[i] += x[i-j] * y[j] */ + sum += ((q63_t) pIn1[j] * (pIn2[i - j])); + } + } + + /* Store the output in the destination buffer */ + pDst[i] = (q31_t) (sum >> 31u); + } + +#endif /* #ifndef ARM_MATH_CM0_FAMILY */ + +} + +/** + * @} end of Conv group + */ diff --git a/gui/cmsis/arm_conv_q7.c b/gui/cmsis/arm_conv_q7.c new file mode 100644 index 0000000..79b08fc --- /dev/null +++ b/gui/cmsis/arm_conv_q7.c @@ -0,0 +1,690 @@ +/* ---------------------------------------------------------------------- +* Copyright (C) 2010-2014 ARM Limited. All rights reserved. +* +* $Date: 19. March 2015 +* $Revision: V.1.4.5 +* +* Project: CMSIS DSP Library +* Title: arm_conv_q7.c +* +* Description: Convolution of Q7 sequences. +* +* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0 +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* - Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* - Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* - Neither the name of ARM LIMITED nor the names of its contributors +* may be used to endorse or promote products derived from this +* software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* -------------------------------------------------------------------- */ + +#include "arm_math.h" + +/** + * @ingroup groupFilters + */ + +/** + * @addtogroup Conv + * @{ + */ + +/** + * @brief Convolution of Q7 sequences. + * @param[in] *pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] *pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] *pDst points to the location where the output result is written. Length srcALen+srcBLen-1. + * @return none. + * + * @details + * Scaling and Overflow Behavior: + * + * \par + * The function is implemented using a 32-bit internal accumulator. + * Both the inputs are represented in 1.7 format and multiplications yield a 2.14 result. + * The 2.14 intermediate results are accumulated in a 32-bit accumulator in 18.14 format. + * This approach provides 17 guard bits and there is no risk of overflow as long as max(srcALen, srcBLen)<131072. + * The 18.14 result is then truncated to 18.7 format by discarding the low 7 bits and then saturated to 1.7 format. + * + * \par + * Refer the function arm_conv_opt_q7() for a faster implementation of this function. + * + */ + +void arm_conv_q7( + q7_t * pSrcA, + uint32_t srcALen, + q7_t * pSrcB, + uint32_t srcBLen, + q7_t * pDst) +{ + + +#ifndef ARM_MATH_CM0_FAMILY + + /* Run the below code for Cortex-M4 and Cortex-M3 */ + + q7_t *pIn1; /* inputA pointer */ + q7_t *pIn2; /* inputB pointer */ + q7_t *pOut = pDst; /* output pointer */ + q7_t *px; /* Intermediate inputA pointer */ + q7_t *py; /* Intermediate inputB pointer */ + q7_t *pSrc1, *pSrc2; /* Intermediate pointers */ + q7_t x0, x1, x2, x3, c0, c1; /* Temporary variables to hold state and coefficient values */ + q31_t sum, acc0, acc1, acc2, acc3; /* Accumulator */ + q31_t input1, input2; /* Temporary input variables */ + q15_t in1, in2; /* Temporary input variables */ + uint32_t j, k, count, blkCnt, blockSize1, blockSize2, blockSize3; /* loop counter */ + + /* The algorithm implementation is based on the lengths of the inputs. */ + /* srcB is always made to slide across srcA. */ + /* So srcBLen is always considered as shorter or equal to srcALen */ + if(srcALen >= srcBLen) + { + /* Initialization of inputA pointer */ + pIn1 = pSrcA; + + /* Initialization of inputB pointer */ + pIn2 = pSrcB; + } + else + { + /* Initialization of inputA pointer */ + pIn1 = pSrcB; + + /* Initialization of inputB pointer */ + pIn2 = pSrcA; + + /* srcBLen is always considered as shorter or equal to srcALen */ + j = srcBLen; + srcBLen = srcALen; + srcALen = j; + } + + /* conv(x,y) at n = x[n] * y[0] + x[n-1] * y[1] + x[n-2] * y[2] + ...+ x[n-N+1] * y[N -1] */ + /* The function is internally + * divided into three stages according to the number of multiplications that has to be + * taken place between inputA samples and inputB samples. In the first stage of the + * algorithm, the multiplications increase by one for every iteration. + * In the second stage of the algorithm, srcBLen number of multiplications are done. + * In the third stage of the algorithm, the multiplications decrease by one + * for every iteration. */ + + /* The algorithm is implemented in three stages. + The loop counters of each stage is initiated here. */ + blockSize1 = srcBLen - 1u; + blockSize2 = (srcALen - srcBLen) + 1u; + blockSize3 = blockSize1; + + /* -------------------------- + * Initializations of stage1 + * -------------------------*/ + + /* sum = x[0] * y[0] + * sum = x[0] * y[1] + x[1] * y[0] + * .... + * sum = x[0] * y[srcBlen - 1] + x[1] * y[srcBlen - 2] +...+ x[srcBLen - 1] * y[0] + */ + + /* In this stage the MAC operations are increased by 1 for every iteration. + The count variable holds the number of MAC operations performed */ + count = 1u; + + /* Working pointer of inputA */ + px = pIn1; + + /* Working pointer of inputB */ + py = pIn2; + + + /* ------------------------ + * Stage1 process + * ----------------------*/ + + /* The first stage starts here */ + while(blockSize1 > 0u) + { + /* Accumulator is made zero for every iteration */ + sum = 0; + + /* Apply loop unrolling and compute 4 MACs simultaneously. */ + k = count >> 2u; + + /* First part of the processing with loop unrolling. Compute 4 MACs at a time. + ** a second loop below computes MACs for the remaining 1 to 3 samples. */ + while(k > 0u) + { + /* x[0] , x[1] */ + in1 = (q15_t) * px++; + in2 = (q15_t) * px++; + input1 = ((q31_t) in1 & 0x0000FFFF) | ((q31_t) in2 << 16u); + + /* y[srcBLen - 1] , y[srcBLen - 2] */ + in1 = (q15_t) * py--; + in2 = (q15_t) * py--; + input2 = ((q31_t) in1 & 0x0000FFFF) | ((q31_t) in2 << 16u); + + /* x[0] * y[srcBLen - 1] */ + /* x[1] * y[srcBLen - 2] */ + sum = __SMLAD(input1, input2, sum); + + /* x[2] , x[3] */ + in1 = (q15_t) * px++; + in2 = (q15_t) * px++; + input1 = ((q31_t) in1 & 0x0000FFFF) | ((q31_t) in2 << 16u); + + /* y[srcBLen - 3] , y[srcBLen - 4] */ + in1 = (q15_t) * py--; + in2 = (q15_t) * py--; + input2 = ((q31_t) in1 & 0x0000FFFF) | ((q31_t) in2 << 16u); + + /* x[2] * y[srcBLen - 3] */ + /* x[3] * y[srcBLen - 4] */ + sum = __SMLAD(input1, input2, sum); + + /* Decrement the loop counter */ + k--; + } + + /* If the count is not a multiple of 4, compute any remaining MACs here. + ** No loop unrolling is used. */ + k = count % 0x4u; + + while(k > 0u) + { + /* Perform the multiply-accumulates */ + sum += ((q15_t) * px++ * *py--); + + /* Decrement the loop counter */ + k--; + } + + /* Store the result in the accumulator in the destination buffer. */ + *pOut++ = (q7_t) (__SSAT(sum >> 7u, 8)); + + /* Update the inputA and inputB pointers for next MAC calculation */ + py = pIn2 + count; + px = pIn1; + + /* Increment the MAC count */ + count++; + + /* Decrement the loop counter */ + blockSize1--; + } + + /* -------------------------- + * Initializations of stage2 + * ------------------------*/ + + /* sum = x[0] * y[srcBLen-1] + x[1] * y[srcBLen-2] +...+ x[srcBLen-1] * y[0] + * sum = x[1] * y[srcBLen-1] + x[2] * y[srcBLen-2] +...+ x[srcBLen] * y[0] + * .... + * sum = x[srcALen-srcBLen-2] * y[srcBLen-1] + x[srcALen] * y[srcBLen-2] +...+ x[srcALen-1] * y[0] + */ + + /* Working pointer of inputA */ + px = pIn1; + + /* Working pointer of inputB */ + pSrc2 = pIn2 + (srcBLen - 1u); + py = pSrc2; + + /* count is index by which the pointer pIn1 to be incremented */ + count = 0u; + + /* ------------------- + * Stage2 process + * ------------------*/ + + /* Stage2 depends on srcBLen as in this stage srcBLen number of MACS are performed. + * So, to loop unroll over blockSize2, + * srcBLen should be greater than or equal to 4 */ + if(srcBLen >= 4u) + { + /* Loop unroll over blockSize2, by 4 */ + blkCnt = blockSize2 >> 2u; + + while(blkCnt > 0u) + { + /* Set all accumulators to zero */ + acc0 = 0; + acc1 = 0; + acc2 = 0; + acc3 = 0; + + /* read x[0], x[1], x[2] samples */ + x0 = *(px++); + x1 = *(px++); + x2 = *(px++); + + /* Apply loop unrolling and compute 4 MACs simultaneously. */ + k = srcBLen >> 2u; + + /* First part of the processing with loop unrolling. Compute 4 MACs at a time. + ** a second loop below computes MACs for the remaining 1 to 3 samples. */ + do + { + /* Read y[srcBLen - 1] sample */ + c0 = *(py--); + /* Read y[srcBLen - 2] sample */ + c1 = *(py--); + + /* Read x[3] sample */ + x3 = *(px++); + + /* x[0] and x[1] are packed */ + in1 = (q15_t) x0; + in2 = (q15_t) x1; + + input1 = ((q31_t) in1 & 0x0000FFFF) | ((q31_t) in2 << 16u); + + /* y[srcBLen - 1] and y[srcBLen - 2] are packed */ + in1 = (q15_t) c0; + in2 = (q15_t) c1; + + input2 = ((q31_t) in1 & 0x0000FFFF) | ((q31_t) in2 << 16u); + + /* acc0 += x[0] * y[srcBLen - 1] + x[1] * y[srcBLen - 2] */ + acc0 = __SMLAD(input1, input2, acc0); + + /* x[1] and x[2] are packed */ + in1 = (q15_t) x1; + in2 = (q15_t) x2; + + input1 = ((q31_t) in1 & 0x0000FFFF) | ((q31_t) in2 << 16u); + + /* acc1 += x[1] * y[srcBLen - 1] + x[2] * y[srcBLen - 2] */ + acc1 = __SMLAD(input1, input2, acc1); + + /* x[2] and x[3] are packed */ + in1 = (q15_t) x2; + in2 = (q15_t) x3; + + input1 = ((q31_t) in1 & 0x0000FFFF) | ((q31_t) in2 << 16u); + + /* acc2 += x[2] * y[srcBLen - 1] + x[3] * y[srcBLen - 2] */ + acc2 = __SMLAD(input1, input2, acc2); + + /* Read x[4] sample */ + x0 = *(px++); + + /* x[3] and x[4] are packed */ + in1 = (q15_t) x3; + in2 = (q15_t) x0; + + input1 = ((q31_t) in1 & 0x0000FFFF) | ((q31_t) in2 << 16u); + + /* acc3 += x[3] * y[srcBLen - 1] + x[4] * y[srcBLen - 2] */ + acc3 = __SMLAD(input1, input2, acc3); + + /* Read y[srcBLen - 3] sample */ + c0 = *(py--); + /* Read y[srcBLen - 4] sample */ + c1 = *(py--); + + /* Read x[5] sample */ + x1 = *(px++); + + /* x[2] and x[3] are packed */ + in1 = (q15_t) x2; + in2 = (q15_t) x3; + + input1 = ((q31_t) in1 & 0x0000FFFF) | ((q31_t) in2 << 16u); + + /* y[srcBLen - 3] and y[srcBLen - 4] are packed */ + in1 = (q15_t) c0; + in2 = (q15_t) c1; + + input2 = ((q31_t) in1 & 0x0000FFFF) | ((q31_t) in2 << 16u); + + /* acc0 += x[2] * y[srcBLen - 3] + x[3] * y[srcBLen - 4] */ + acc0 = __SMLAD(input1, input2, acc0); + + /* x[3] and x[4] are packed */ + in1 = (q15_t) x3; + in2 = (q15_t) x0; + + input1 = ((q31_t) in1 & 0x0000FFFF) | ((q31_t) in2 << 16u); + + /* acc1 += x[3] * y[srcBLen - 3] + x[4] * y[srcBLen - 4] */ + acc1 = __SMLAD(input1, input2, acc1); + + /* x[4] and x[5] are packed */ + in1 = (q15_t) x0; + in2 = (q15_t) x1; + + input1 = ((q31_t) in1 & 0x0000FFFF) | ((q31_t) in2 << 16u); + + /* acc2 += x[4] * y[srcBLen - 3] + x[5] * y[srcBLen - 4] */ + acc2 = __SMLAD(input1, input2, acc2); + + /* Read x[6] sample */ + x2 = *(px++); + + /* x[5] and x[6] are packed */ + in1 = (q15_t) x1; + in2 = (q15_t) x2; + + input1 = ((q31_t) in1 & 0x0000FFFF) | ((q31_t) in2 << 16u); + + /* acc3 += x[5] * y[srcBLen - 3] + x[6] * y[srcBLen - 4] */ + acc3 = __SMLAD(input1, input2, acc3); + + } while(--k); + + /* If the srcBLen is not a multiple of 4, compute any remaining MACs here. + ** No loop unrolling is used. */ + k = srcBLen % 0x4u; + + while(k > 0u) + { + /* Read y[srcBLen - 5] sample */ + c0 = *(py--); + + /* Read x[7] sample */ + x3 = *(px++); + + /* Perform the multiply-accumulates */ + /* acc0 += x[4] * y[srcBLen - 5] */ + acc0 += ((q15_t) x0 * c0); + /* acc1 += x[5] * y[srcBLen - 5] */ + acc1 += ((q15_t) x1 * c0); + /* acc2 += x[6] * y[srcBLen - 5] */ + acc2 += ((q15_t) x2 * c0); + /* acc3 += x[7] * y[srcBLen - 5] */ + acc3 += ((q15_t) x3 * c0); + + /* Reuse the present samples for the next MAC */ + x0 = x1; + x1 = x2; + x2 = x3; + + /* Decrement the loop counter */ + k--; + } + + + /* Store the result in the accumulator in the destination buffer. */ + *pOut++ = (q7_t) (__SSAT(acc0 >> 7u, 8)); + *pOut++ = (q7_t) (__SSAT(acc1 >> 7u, 8)); + *pOut++ = (q7_t) (__SSAT(acc2 >> 7u, 8)); + *pOut++ = (q7_t) (__SSAT(acc3 >> 7u, 8)); + + /* Increment the pointer pIn1 index, count by 4 */ + count += 4u; + + /* Update the inputA and inputB pointers for next MAC calculation */ + px = pIn1 + count; + py = pSrc2; + + /* Decrement the loop counter */ + blkCnt--; + } + + /* If the blockSize2 is not a multiple of 4, compute any remaining output samples here. + ** No loop unrolling is used. */ + blkCnt = blockSize2 % 0x4u; + + while(blkCnt > 0u) + { + /* Accumulator is made zero for every iteration */ + sum = 0; + + /* Apply loop unrolling and compute 4 MACs simultaneously. */ + k = srcBLen >> 2u; + + /* First part of the processing with loop unrolling. Compute 4 MACs at a time. + ** a second loop below computes MACs for the remaining 1 to 3 samples. */ + while(k > 0u) + { + + /* Reading two inputs of SrcA buffer and packing */ + in1 = (q15_t) * px++; + in2 = (q15_t) * px++; + input1 = ((q31_t) in1 & 0x0000FFFF) | ((q31_t) in2 << 16u); + + /* Reading two inputs of SrcB buffer and packing */ + in1 = (q15_t) * py--; + in2 = (q15_t) * py--; + input2 = ((q31_t) in1 & 0x0000FFFF) | ((q31_t) in2 << 16u); + + /* Perform the multiply-accumulates */ + sum = __SMLAD(input1, input2, sum); + + /* Reading two inputs of SrcA buffer and packing */ + in1 = (q15_t) * px++; + in2 = (q15_t) * px++; + input1 = ((q31_t) in1 & 0x0000FFFF) | ((q31_t) in2 << 16u); + + /* Reading two inputs of SrcB buffer and packing */ + in1 = (q15_t) * py--; + in2 = (q15_t) * py--; + input2 = ((q31_t) in1 & 0x0000FFFF) | ((q31_t) in2 << 16u); + + /* Perform the multiply-accumulates */ + sum = __SMLAD(input1, input2, sum); + + /* Decrement the loop counter */ + k--; + } + + /* If the srcBLen is not a multiple of 4, compute any remaining MACs here. + ** No loop unrolling is used. */ + k = srcBLen % 0x4u; + + while(k > 0u) + { + /* Perform the multiply-accumulates */ + sum += ((q15_t) * px++ * *py--); + + /* Decrement the loop counter */ + k--; + } + + /* Store the result in the accumulator in the destination buffer. */ + *pOut++ = (q7_t) (__SSAT(sum >> 7u, 8)); + + /* Increment the pointer pIn1 index, count by 1 */ + count++; + + /* Update the inputA and inputB pointers for next MAC calculation */ + px = pIn1 + count; + py = pSrc2; + + /* Decrement the loop counter */ + blkCnt--; + } + } + else + { + /* If the srcBLen is not a multiple of 4, + * the blockSize2 loop cannot be unrolled by 4 */ + blkCnt = blockSize2; + + while(blkCnt > 0u) + { + /* Accumulator is made zero for every iteration */ + sum = 0; + + /* srcBLen number of MACS should be performed */ + k = srcBLen; + + while(k > 0u) + { + /* Perform the multiply-accumulate */ + sum += ((q15_t) * px++ * *py--); + + /* Decrement the loop counter */ + k--; + } + + /* Store the result in the accumulator in the destination buffer. */ + *pOut++ = (q7_t) (__SSAT(sum >> 7u, 8)); + + /* Increment the MAC count */ + count++; + + /* Update the inputA and inputB pointers for next MAC calculation */ + px = pIn1 + count; + py = pSrc2; + + /* Decrement the loop counter */ + blkCnt--; + } + } + + + /* -------------------------- + * Initializations of stage3 + * -------------------------*/ + + /* sum += x[srcALen-srcBLen+1] * y[srcBLen-1] + x[srcALen-srcBLen+2] * y[srcBLen-2] +...+ x[srcALen-1] * y[1] + * sum += x[srcALen-srcBLen+2] * y[srcBLen-1] + x[srcALen-srcBLen+3] * y[srcBLen-2] +...+ x[srcALen-1] * y[2] + * .... + * sum += x[srcALen-2] * y[srcBLen-1] + x[srcALen-1] * y[srcBLen-2] + * sum += x[srcALen-1] * y[srcBLen-1] + */ + + /* In this stage the MAC operations are decreased by 1 for every iteration. + The blockSize3 variable holds the number of MAC operations performed */ + + /* Working pointer of inputA */ + pSrc1 = pIn1 + (srcALen - (srcBLen - 1u)); + px = pSrc1; + + /* Working pointer of inputB */ + pSrc2 = pIn2 + (srcBLen - 1u); + py = pSrc2; + + /* ------------------- + * Stage3 process + * ------------------*/ + + while(blockSize3 > 0u) + { + /* Accumulator is made zero for every iteration */ + sum = 0; + + /* Apply loop unrolling and compute 4 MACs simultaneously. */ + k = blockSize3 >> 2u; + + /* First part of the processing with loop unrolling. Compute 4 MACs at a time. + ** a second loop below computes MACs for the remaining 1 to 3 samples. */ + while(k > 0u) + { + /* Reading two inputs, x[srcALen - srcBLen + 1] and x[srcALen - srcBLen + 2] of SrcA buffer and packing */ + in1 = (q15_t) * px++; + in2 = (q15_t) * px++; + input1 = ((q31_t) in1 & 0x0000FFFF) | ((q31_t) in2 << 16u); + + /* Reading two inputs, y[srcBLen - 1] and y[srcBLen - 2] of SrcB buffer and packing */ + in1 = (q15_t) * py--; + in2 = (q15_t) * py--; + input2 = ((q31_t) in1 & 0x0000FFFF) | ((q31_t) in2 << 16u); + + /* sum += x[srcALen - srcBLen + 1] * y[srcBLen - 1] */ + /* sum += x[srcALen - srcBLen + 2] * y[srcBLen - 2] */ + sum = __SMLAD(input1, input2, sum); + + /* Reading two inputs, x[srcALen - srcBLen + 3] and x[srcALen - srcBLen + 4] of SrcA buffer and packing */ + in1 = (q15_t) * px++; + in2 = (q15_t) * px++; + input1 = ((q31_t) in1 & 0x0000FFFF) | ((q31_t) in2 << 16u); + + /* Reading two inputs, y[srcBLen - 3] and y[srcBLen - 4] of SrcB buffer and packing */ + in1 = (q15_t) * py--; + in2 = (q15_t) * py--; + input2 = ((q31_t) in1 & 0x0000FFFF) | ((q31_t) in2 << 16u); + + /* sum += x[srcALen - srcBLen + 3] * y[srcBLen - 3] */ + /* sum += x[srcALen - srcBLen + 4] * y[srcBLen - 4] */ + sum = __SMLAD(input1, input2, sum); + + /* Decrement the loop counter */ + k--; + } + + /* If the blockSize3 is not a multiple of 4, compute any remaining MACs here. + ** No loop unrolling is used. */ + k = blockSize3 % 0x4u; + + while(k > 0u) + { + /* Perform the multiply-accumulates */ + sum += ((q15_t) * px++ * *py--); + + /* Decrement the loop counter */ + k--; + } + + /* Store the result in the accumulator in the destination buffer. */ + *pOut++ = (q7_t) (__SSAT(sum >> 7u, 8)); + + /* Update the inputA and inputB pointers for next MAC calculation */ + px = ++pSrc1; + py = pSrc2; + + /* Decrement the loop counter */ + blockSize3--; + } + +#else + + /* Run the below code for Cortex-M0 */ + + q7_t *pIn1 = pSrcA; /* input pointer */ + q7_t *pIn2 = pSrcB; /* coefficient pointer */ + q31_t sum; /* Accumulator */ + uint32_t i, j; /* loop counter */ + + /* Loop to calculate output of convolution for output length number of times */ + for (i = 0; i < (srcALen + srcBLen - 1); i++) + { + /* Initialize sum with zero to carry on MAC operations */ + sum = 0; + + /* Loop to perform MAC operations according to convolution equation */ + for (j = 0; j <= i; j++) + { + /* Check the array limitations */ + if(((i - j) < srcBLen) && (j < srcALen)) + { + /* z[i] += x[i-j] * y[j] */ + sum += (q15_t) pIn1[j] * (pIn2[i - j]); + } + } + + /* Store the output in the destination buffer */ + pDst[i] = (q7_t) __SSAT((sum >> 7u), 8u); + } + +#endif /* #ifndef ARM_MATH_CM0_FAMILY */ + +} + +/** + * @} end of Conv group + */ diff --git a/gui/cmsis/arm_fir_f32.c b/gui/cmsis/arm_fir_f32.c new file mode 100644 index 0000000..3ecb7b5 --- /dev/null +++ b/gui/cmsis/arm_fir_f32.c @@ -0,0 +1,997 @@ +/* ---------------------------------------------------------------------- +* Copyright (C) 2010-2014 ARM Limited. All rights reserved. +* +* $Date: 19. March 2015 +* $Revision: V.1.4.5 +* +* Project: CMSIS DSP Library +* Title: arm_fir_f32.c +* +* Description: Floating-point FIR filter processing function. +* +* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0 +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* - Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* - Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* - Neither the name of ARM LIMITED nor the names of its contributors +* may be used to endorse or promote products derived from this +* software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* -------------------------------------------------------------------- */ + +#include "arm_math.h" + +/** +* @ingroup groupFilters +*/ + +/** +* @defgroup FIR Finite Impulse Response (FIR) Filters +* +* This set of functions implements Finite Impulse Response (FIR) filters +* for Q7, Q15, Q31, and floating-point data types. Fast versions of Q15 and Q31 are also provided. +* The functions operate on blocks of input and output data and each call to the function processes +* blockSize samples through the filter. pSrc and +* pDst points to input and output arrays containing blockSize values. +* +* \par Algorithm: +* The FIR filter algorithm is based upon a sequence of multiply-accumulate (MAC) operations. +* Each filter coefficient b[n] is multiplied by a state variable which equals a previous input sample x[n]. +*
  
+*    y[n] = b[0] * x[n] + b[1] * x[n-1] + b[2] * x[n-2] + ...+ b[numTaps-1] * x[n-numTaps+1]  
+* 
+* \par +* \image html FIR.gif "Finite Impulse Response filter" +* \par +* pCoeffs points to a coefficient array of size numTaps. +* Coefficients are stored in time reversed order. +* \par +*
  
+*    {b[numTaps-1], b[numTaps-2], b[N-2], ..., b[1], b[0]}  
+* 
+* \par +* pState points to a state array of size numTaps + blockSize - 1. +* Samples in the state buffer are stored in the following order. +* \par +*
  
+*    {x[n-numTaps+1], x[n-numTaps], x[n-numTaps-1], x[n-numTaps-2]....x[0], x[1], ..., x[blockSize-1]}  
+* 
+* \par +* Note that the length of the state buffer exceeds the length of the coefficient array by blockSize-1. +* The increased state buffer length allows circular addressing, which is traditionally used in the FIR filters, +* to be avoided and yields a significant speed improvement. +* The state variables are updated after each block of data is processed; the coefficients are untouched. +* \par Instance Structure +* The coefficients and state variables for a filter are stored together in an instance data structure. +* A separate instance structure must be defined for each filter. +* Coefficient arrays may be shared among several instances while state variable arrays cannot be shared. +* There are separate instance structure declarations for each of the 4 supported data types. +* +* \par Initialization Functions +* There is also an associated initialization function for each data type. +* The initialization function performs the following operations: +* - Sets the values of the internal structure fields. +* - Zeros out the values in the state buffer. +* To do this manually without calling the init function, assign the follow subfields of the instance structure: +* numTaps, pCoeffs, pState. Also set all of the values in pState to zero. +* +* \par +* Use of the initialization function is optional. +* However, if the initialization function is used, then the instance structure cannot be placed into a const data section. +* To place an instance structure into a const data section, the instance structure must be manually initialized. +* Set the values in the state buffer to zeros before static initialization. +* The code below statically initializes each of the 4 different data type filter instance structures +*
  
+*arm_fir_instance_f32 S = {numTaps, pState, pCoeffs};  
+*arm_fir_instance_q31 S = {numTaps, pState, pCoeffs};  
+*arm_fir_instance_q15 S = {numTaps, pState, pCoeffs};  
+*arm_fir_instance_q7 S =  {numTaps, pState, pCoeffs};  
+* 
+* +* where numTaps is the number of filter coefficients in the filter; pState is the address of the state buffer; +* pCoeffs is the address of the coefficient buffer. +* +* \par Fixed-Point Behavior +* Care must be taken when using the fixed-point versions of the FIR filter functions. +* In particular, the overflow and saturation behavior of the accumulator used in each function must be considered. +* Refer to the function specific documentation below for usage guidelines. +*/ + +/** +* @addtogroup FIR +* @{ +*/ + +/** +* +* @param[in] *S points to an instance of the floating-point FIR filter structure. +* @param[in] *pSrc points to the block of input data. +* @param[out] *pDst points to the block of output data. +* @param[in] blockSize number of samples to process per call. +* @return none. +* +*/ + +#if defined(ARM_MATH_CM7) + +void arm_fir_f32( +const arm_fir_instance_f32 * S, +float32_t * pSrc, +float32_t * pDst, +uint32_t blockSize) +{ + float32_t *pState = S->pState; /* State pointer */ + float32_t *pCoeffs = S->pCoeffs; /* Coefficient pointer */ + float32_t *pStateCurnt; /* Points to the current sample of the state */ + float32_t *px, *pb; /* Temporary pointers for state and coefficient buffers */ + float32_t acc0, acc1, acc2, acc3, acc4, acc5, acc6, acc7; /* Accumulators */ + float32_t x0, x1, x2, x3, x4, x5, x6, x7, c0; /* Temporary variables to hold state and coefficient values */ + uint32_t numTaps = S->numTaps; /* Number of filter coefficients in the filter */ + uint32_t i, tapCnt, blkCnt; /* Loop counters */ + + /* S->pState points to state array which contains previous frame (numTaps - 1) samples */ + /* pStateCurnt points to the location where the new input data should be written */ + pStateCurnt = &(S->pState[(numTaps - 1u)]); + + /* Apply loop unrolling and compute 8 output values simultaneously. + * The variables acc0 ... acc7 hold output values that are being computed: + * + * acc0 = b[numTaps-1] * x[n-numTaps-1] + b[numTaps-2] * x[n-numTaps-2] + b[numTaps-3] * x[n-numTaps-3] +...+ b[0] * x[0] + * acc1 = b[numTaps-1] * x[n-numTaps] + b[numTaps-2] * x[n-numTaps-1] + b[numTaps-3] * x[n-numTaps-2] +...+ b[0] * x[1] + * acc2 = b[numTaps-1] * x[n-numTaps+1] + b[numTaps-2] * x[n-numTaps] + b[numTaps-3] * x[n-numTaps-1] +...+ b[0] * x[2] + * acc3 = b[numTaps-1] * x[n-numTaps+2] + b[numTaps-2] * x[n-numTaps+1] + b[numTaps-3] * x[n-numTaps] +...+ b[0] * x[3] + */ + blkCnt = blockSize >> 3; + + /* First part of the processing with loop unrolling. Compute 8 outputs at a time. + ** a second loop below computes the remaining 1 to 7 samples. */ + while(blkCnt > 0u) + { + /* Copy four new input samples into the state buffer */ + *pStateCurnt++ = *pSrc++; + *pStateCurnt++ = *pSrc++; + *pStateCurnt++ = *pSrc++; + *pStateCurnt++ = *pSrc++; + + /* Set all accumulators to zero */ + acc0 = 0.0f; + acc1 = 0.0f; + acc2 = 0.0f; + acc3 = 0.0f; + acc4 = 0.0f; + acc5 = 0.0f; + acc6 = 0.0f; + acc7 = 0.0f; + + /* Initialize state pointer */ + px = pState; + + /* Initialize coeff pointer */ + pb = (pCoeffs); + + /* This is separated from the others to avoid + * a call to __aeabi_memmove which would be slower + */ + *pStateCurnt++ = *pSrc++; + *pStateCurnt++ = *pSrc++; + *pStateCurnt++ = *pSrc++; + *pStateCurnt++ = *pSrc++; + + /* Read the first seven samples from the state buffer: x[n-numTaps], x[n-numTaps-1], x[n-numTaps-2] */ + x0 = *px++; + x1 = *px++; + x2 = *px++; + x3 = *px++; + x4 = *px++; + x5 = *px++; + x6 = *px++; + + /* Loop unrolling. Process 8 taps at a time. */ + tapCnt = numTaps >> 3u; + + /* Loop over the number of taps. Unroll by a factor of 8. + ** Repeat until we've computed numTaps-8 coefficients. */ + while(tapCnt > 0u) + { + /* Read the b[numTaps-1] coefficient */ + c0 = *(pb++); + + /* Read x[n-numTaps-3] sample */ + x7 = *(px++); + + /* acc0 += b[numTaps-1] * x[n-numTaps] */ + acc0 += x0 * c0; + + /* acc1 += b[numTaps-1] * x[n-numTaps-1] */ + acc1 += x1 * c0; + + /* acc2 += b[numTaps-1] * x[n-numTaps-2] */ + acc2 += x2 * c0; + + /* acc3 += b[numTaps-1] * x[n-numTaps-3] */ + acc3 += x3 * c0; + + /* acc4 += b[numTaps-1] * x[n-numTaps-4] */ + acc4 += x4 * c0; + + /* acc1 += b[numTaps-1] * x[n-numTaps-5] */ + acc5 += x5 * c0; + + /* acc2 += b[numTaps-1] * x[n-numTaps-6] */ + acc6 += x6 * c0; + + /* acc3 += b[numTaps-1] * x[n-numTaps-7] */ + acc7 += x7 * c0; + + /* Read the b[numTaps-2] coefficient */ + c0 = *(pb++); + + /* Read x[n-numTaps-4] sample */ + x0 = *(px++); + + /* Perform the multiply-accumulate */ + acc0 += x1 * c0; + acc1 += x2 * c0; + acc2 += x3 * c0; + acc3 += x4 * c0; + acc4 += x5 * c0; + acc5 += x6 * c0; + acc6 += x7 * c0; + acc7 += x0 * c0; + + /* Read the b[numTaps-3] coefficient */ + c0 = *(pb++); + + /* Read x[n-numTaps-5] sample */ + x1 = *(px++); + + /* Perform the multiply-accumulates */ + acc0 += x2 * c0; + acc1 += x3 * c0; + acc2 += x4 * c0; + acc3 += x5 * c0; + acc4 += x6 * c0; + acc5 += x7 * c0; + acc6 += x0 * c0; + acc7 += x1 * c0; + + /* Read the b[numTaps-4] coefficient */ + c0 = *(pb++); + + /* Read x[n-numTaps-6] sample */ + x2 = *(px++); + + /* Perform the multiply-accumulates */ + acc0 += x3 * c0; + acc1 += x4 * c0; + acc2 += x5 * c0; + acc3 += x6 * c0; + acc4 += x7 * c0; + acc5 += x0 * c0; + acc6 += x1 * c0; + acc7 += x2 * c0; + + /* Read the b[numTaps-4] coefficient */ + c0 = *(pb++); + + /* Read x[n-numTaps-6] sample */ + x3 = *(px++); + /* Perform the multiply-accumulates */ + acc0 += x4 * c0; + acc1 += x5 * c0; + acc2 += x6 * c0; + acc3 += x7 * c0; + acc4 += x0 * c0; + acc5 += x1 * c0; + acc6 += x2 * c0; + acc7 += x3 * c0; + + /* Read the b[numTaps-4] coefficient */ + c0 = *(pb++); + + /* Read x[n-numTaps-6] sample */ + x4 = *(px++); + + /* Perform the multiply-accumulates */ + acc0 += x5 * c0; + acc1 += x6 * c0; + acc2 += x7 * c0; + acc3 += x0 * c0; + acc4 += x1 * c0; + acc5 += x2 * c0; + acc6 += x3 * c0; + acc7 += x4 * c0; + + /* Read the b[numTaps-4] coefficient */ + c0 = *(pb++); + + /* Read x[n-numTaps-6] sample */ + x5 = *(px++); + + /* Perform the multiply-accumulates */ + acc0 += x6 * c0; + acc1 += x7 * c0; + acc2 += x0 * c0; + acc3 += x1 * c0; + acc4 += x2 * c0; + acc5 += x3 * c0; + acc6 += x4 * c0; + acc7 += x5 * c0; + + /* Read the b[numTaps-4] coefficient */ + c0 = *(pb++); + + /* Read x[n-numTaps-6] sample */ + x6 = *(px++); + + /* Perform the multiply-accumulates */ + acc0 += x7 * c0; + acc1 += x0 * c0; + acc2 += x1 * c0; + acc3 += x2 * c0; + acc4 += x3 * c0; + acc5 += x4 * c0; + acc6 += x5 * c0; + acc7 += x6 * c0; + + tapCnt--; + } + + /* If the filter length is not a multiple of 8, compute the remaining filter taps */ + tapCnt = numTaps % 0x8u; + + while(tapCnt > 0u) + { + /* Read coefficients */ + c0 = *(pb++); + + /* Fetch 1 state variable */ + x7 = *(px++); + + /* Perform the multiply-accumulates */ + acc0 += x0 * c0; + acc1 += x1 * c0; + acc2 += x2 * c0; + acc3 += x3 * c0; + acc4 += x4 * c0; + acc5 += x5 * c0; + acc6 += x6 * c0; + acc7 += x7 * c0; + + /* Reuse the present sample states for next sample */ + x0 = x1; + x1 = x2; + x2 = x3; + x3 = x4; + x4 = x5; + x5 = x6; + x6 = x7; + + /* Decrement the loop counter */ + tapCnt--; + } + + /* Advance the state pointer by 8 to process the next group of 8 samples */ + pState = pState + 8; + + /* The results in the 8 accumulators, store in the destination buffer. */ + *pDst++ = acc0; + *pDst++ = acc1; + *pDst++ = acc2; + *pDst++ = acc3; + *pDst++ = acc4; + *pDst++ = acc5; + *pDst++ = acc6; + *pDst++ = acc7; + + blkCnt--; + } + + /* If the blockSize is not a multiple of 8, compute any remaining output samples here. + ** No loop unrolling is used. */ + blkCnt = blockSize % 0x8u; + + while(blkCnt > 0u) + { + /* Copy one sample at a time into state buffer */ + *pStateCurnt++ = *pSrc++; + + /* Set the accumulator to zero */ + acc0 = 0.0f; + + /* Initialize state pointer */ + px = pState; + + /* Initialize Coefficient pointer */ + pb = (pCoeffs); + + i = numTaps; + + /* Perform the multiply-accumulates */ + do + { + acc0 += *px++ * *pb++; + i--; + + } while(i > 0u); + + /* The result is store in the destination buffer. */ + *pDst++ = acc0; + + /* Advance state pointer by 1 for the next sample */ + pState = pState + 1; + + blkCnt--; + } + + /* Processing is complete. + ** Now copy the last numTaps - 1 samples to the start of the state buffer. + ** This prepares the state buffer for the next function call. */ + + /* Points to the start of the state buffer */ + pStateCurnt = S->pState; + + tapCnt = (numTaps - 1u) >> 2u; + + /* copy data */ + while(tapCnt > 0u) + { + *pStateCurnt++ = *pState++; + *pStateCurnt++ = *pState++; + *pStateCurnt++ = *pState++; + *pStateCurnt++ = *pState++; + + /* Decrement the loop counter */ + tapCnt--; + } + + /* Calculate remaining number of copies */ + tapCnt = (numTaps - 1u) % 0x4u; + + /* Copy the remaining q31_t data */ + while(tapCnt > 0u) + { + *pStateCurnt++ = *pState++; + + /* Decrement the loop counter */ + tapCnt--; + } +} + +#elif defined(ARM_MATH_CM0_FAMILY) + +void arm_fir_f32( +const arm_fir_instance_f32 * S, +float32_t * pSrc, +float32_t * pDst, +uint32_t blockSize) +{ + float32_t *pState = S->pState; /* State pointer */ + float32_t *pCoeffs = S->pCoeffs; /* Coefficient pointer */ + float32_t *pStateCurnt; /* Points to the current sample of the state */ + float32_t *px, *pb; /* Temporary pointers for state and coefficient buffers */ + uint32_t numTaps = S->numTaps; /* Number of filter coefficients in the filter */ + uint32_t i, tapCnt, blkCnt; /* Loop counters */ + + /* Run the below code for Cortex-M0 */ + + float32_t acc; + + /* S->pState points to state array which contains previous frame (numTaps - 1) samples */ + /* pStateCurnt points to the location where the new input data should be written */ + pStateCurnt = &(S->pState[(numTaps - 1u)]); + + /* Initialize blkCnt with blockSize */ + blkCnt = blockSize; + + while(blkCnt > 0u) + { + /* Copy one sample at a time into state buffer */ + *pStateCurnt++ = *pSrc++; + + /* Set the accumulator to zero */ + acc = 0.0f; + + /* Initialize state pointer */ + px = pState; + + /* Initialize Coefficient pointer */ + pb = pCoeffs; + + i = numTaps; + + /* Perform the multiply-accumulates */ + do + { + /* acc = b[numTaps-1] * x[n-numTaps-1] + b[numTaps-2] * x[n-numTaps-2] + b[numTaps-3] * x[n-numTaps-3] +...+ b[0] * x[0] */ + acc += *px++ * *pb++; + i--; + + } while(i > 0u); + + /* The result is store in the destination buffer. */ + *pDst++ = acc; + + /* Advance state pointer by 1 for the next sample */ + pState = pState + 1; + + blkCnt--; + } + + /* Processing is complete. + ** Now copy the last numTaps - 1 samples to the starting of the state buffer. + ** This prepares the state buffer for the next function call. */ + + /* Points to the start of the state buffer */ + pStateCurnt = S->pState; + + /* Copy numTaps number of values */ + tapCnt = numTaps - 1u; + + /* Copy data */ + while(tapCnt > 0u) + { + *pStateCurnt++ = *pState++; + + /* Decrement the loop counter */ + tapCnt--; + } + +} + +#else + +/* Run the below code for Cortex-M4 and Cortex-M3 */ + +void arm_fir_f32( +const arm_fir_instance_f32 * S, +float32_t * pSrc, +float32_t * pDst, +uint32_t blockSize) +{ + float32_t *pState = S->pState; /* State pointer */ + float32_t *pCoeffs = S->pCoeffs; /* Coefficient pointer */ + float32_t *pStateCurnt; /* Points to the current sample of the state */ + float32_t *px, *pb; /* Temporary pointers for state and coefficient buffers */ + float32_t acc0, acc1, acc2, acc3, acc4, acc5, acc6, acc7; /* Accumulators */ + float32_t x0, x1, x2, x3, x4, x5, x6, x7, c0; /* Temporary variables to hold state and coefficient values */ + uint32_t numTaps = S->numTaps; /* Number of filter coefficients in the filter */ + uint32_t i, tapCnt, blkCnt; /* Loop counters */ + float32_t p0,p1,p2,p3,p4,p5,p6,p7; /* Temporary product values */ + + /* S->pState points to state array which contains previous frame (numTaps - 1) samples */ + /* pStateCurnt points to the location where the new input data should be written */ + pStateCurnt = &(S->pState[(numTaps - 1u)]); + + /* Apply loop unrolling and compute 8 output values simultaneously. + * The variables acc0 ... acc7 hold output values that are being computed: + * + * acc0 = b[numTaps-1] * x[n-numTaps-1] + b[numTaps-2] * x[n-numTaps-2] + b[numTaps-3] * x[n-numTaps-3] +...+ b[0] * x[0] + * acc1 = b[numTaps-1] * x[n-numTaps] + b[numTaps-2] * x[n-numTaps-1] + b[numTaps-3] * x[n-numTaps-2] +...+ b[0] * x[1] + * acc2 = b[numTaps-1] * x[n-numTaps+1] + b[numTaps-2] * x[n-numTaps] + b[numTaps-3] * x[n-numTaps-1] +...+ b[0] * x[2] + * acc3 = b[numTaps-1] * x[n-numTaps+2] + b[numTaps-2] * x[n-numTaps+1] + b[numTaps-3] * x[n-numTaps] +...+ b[0] * x[3] + */ + blkCnt = blockSize >> 3; + + /* First part of the processing with loop unrolling. Compute 8 outputs at a time. + ** a second loop below computes the remaining 1 to 7 samples. */ + while(blkCnt > 0u) + { + /* Copy four new input samples into the state buffer */ + *pStateCurnt++ = *pSrc++; + *pStateCurnt++ = *pSrc++; + *pStateCurnt++ = *pSrc++; + *pStateCurnt++ = *pSrc++; + + /* Set all accumulators to zero */ + acc0 = 0.0f; + acc1 = 0.0f; + acc2 = 0.0f; + acc3 = 0.0f; + acc4 = 0.0f; + acc5 = 0.0f; + acc6 = 0.0f; + acc7 = 0.0f; + + /* Initialize state pointer */ + px = pState; + + /* Initialize coeff pointer */ + pb = (pCoeffs); + + /* This is separated from the others to avoid + * a call to __aeabi_memmove which would be slower + */ + *pStateCurnt++ = *pSrc++; + *pStateCurnt++ = *pSrc++; + *pStateCurnt++ = *pSrc++; + *pStateCurnt++ = *pSrc++; + + /* Read the first seven samples from the state buffer: x[n-numTaps], x[n-numTaps-1], x[n-numTaps-2] */ + x0 = *px++; + x1 = *px++; + x2 = *px++; + x3 = *px++; + x4 = *px++; + x5 = *px++; + x6 = *px++; + + /* Loop unrolling. Process 8 taps at a time. */ + tapCnt = numTaps >> 3u; + + /* Loop over the number of taps. Unroll by a factor of 8. + ** Repeat until we've computed numTaps-8 coefficients. */ + while(tapCnt > 0u) + { + /* Read the b[numTaps-1] coefficient */ + c0 = *(pb++); + + /* Read x[n-numTaps-3] sample */ + x7 = *(px++); + + /* acc0 += b[numTaps-1] * x[n-numTaps] */ + p0 = x0 * c0; + + /* acc1 += b[numTaps-1] * x[n-numTaps-1] */ + p1 = x1 * c0; + + /* acc2 += b[numTaps-1] * x[n-numTaps-2] */ + p2 = x2 * c0; + + /* acc3 += b[numTaps-1] * x[n-numTaps-3] */ + p3 = x3 * c0; + + /* acc4 += b[numTaps-1] * x[n-numTaps-4] */ + p4 = x4 * c0; + + /* acc1 += b[numTaps-1] * x[n-numTaps-5] */ + p5 = x5 * c0; + + /* acc2 += b[numTaps-1] * x[n-numTaps-6] */ + p6 = x6 * c0; + + /* acc3 += b[numTaps-1] * x[n-numTaps-7] */ + p7 = x7 * c0; + + /* Read the b[numTaps-2] coefficient */ + c0 = *(pb++); + + /* Read x[n-numTaps-4] sample */ + x0 = *(px++); + + acc0 += p0; + acc1 += p1; + acc2 += p2; + acc3 += p3; + acc4 += p4; + acc5 += p5; + acc6 += p6; + acc7 += p7; + + + /* Perform the multiply-accumulate */ + p0 = x1 * c0; + p1 = x2 * c0; + p2 = x3 * c0; + p3 = x4 * c0; + p4 = x5 * c0; + p5 = x6 * c0; + p6 = x7 * c0; + p7 = x0 * c0; + + /* Read the b[numTaps-3] coefficient */ + c0 = *(pb++); + + /* Read x[n-numTaps-5] sample */ + x1 = *(px++); + + acc0 += p0; + acc1 += p1; + acc2 += p2; + acc3 += p3; + acc4 += p4; + acc5 += p5; + acc6 += p6; + acc7 += p7; + + /* Perform the multiply-accumulates */ + p0 = x2 * c0; + p1 = x3 * c0; + p2 = x4 * c0; + p3 = x5 * c0; + p4 = x6 * c0; + p5 = x7 * c0; + p6 = x0 * c0; + p7 = x1 * c0; + + /* Read the b[numTaps-4] coefficient */ + c0 = *(pb++); + + /* Read x[n-numTaps-6] sample */ + x2 = *(px++); + + acc0 += p0; + acc1 += p1; + acc2 += p2; + acc3 += p3; + acc4 += p4; + acc5 += p5; + acc6 += p6; + acc7 += p7; + + /* Perform the multiply-accumulates */ + p0 = x3 * c0; + p1 = x4 * c0; + p2 = x5 * c0; + p3 = x6 * c0; + p4 = x7 * c0; + p5 = x0 * c0; + p6 = x1 * c0; + p7 = x2 * c0; + + /* Read the b[numTaps-4] coefficient */ + c0 = *(pb++); + + /* Read x[n-numTaps-6] sample */ + x3 = *(px++); + + acc0 += p0; + acc1 += p1; + acc2 += p2; + acc3 += p3; + acc4 += p4; + acc5 += p5; + acc6 += p6; + acc7 += p7; + + /* Perform the multiply-accumulates */ + p0 = x4 * c0; + p1 = x5 * c0; + p2 = x6 * c0; + p3 = x7 * c0; + p4 = x0 * c0; + p5 = x1 * c0; + p6 = x2 * c0; + p7 = x3 * c0; + + /* Read the b[numTaps-4] coefficient */ + c0 = *(pb++); + + /* Read x[n-numTaps-6] sample */ + x4 = *(px++); + + acc0 += p0; + acc1 += p1; + acc2 += p2; + acc3 += p3; + acc4 += p4; + acc5 += p5; + acc6 += p6; + acc7 += p7; + + /* Perform the multiply-accumulates */ + p0 = x5 * c0; + p1 = x6 * c0; + p2 = x7 * c0; + p3 = x0 * c0; + p4 = x1 * c0; + p5 = x2 * c0; + p6 = x3 * c0; + p7 = x4 * c0; + + /* Read the b[numTaps-4] coefficient */ + c0 = *(pb++); + + /* Read x[n-numTaps-6] sample */ + x5 = *(px++); + + acc0 += p0; + acc1 += p1; + acc2 += p2; + acc3 += p3; + acc4 += p4; + acc5 += p5; + acc6 += p6; + acc7 += p7; + + /* Perform the multiply-accumulates */ + p0 = x6 * c0; + p1 = x7 * c0; + p2 = x0 * c0; + p3 = x1 * c0; + p4 = x2 * c0; + p5 = x3 * c0; + p6 = x4 * c0; + p7 = x5 * c0; + + /* Read the b[numTaps-4] coefficient */ + c0 = *(pb++); + + /* Read x[n-numTaps-6] sample */ + x6 = *(px++); + + acc0 += p0; + acc1 += p1; + acc2 += p2; + acc3 += p3; + acc4 += p4; + acc5 += p5; + acc6 += p6; + acc7 += p7; + + /* Perform the multiply-accumulates */ + p0 = x7 * c0; + p1 = x0 * c0; + p2 = x1 * c0; + p3 = x2 * c0; + p4 = x3 * c0; + p5 = x4 * c0; + p6 = x5 * c0; + p7 = x6 * c0; + + tapCnt--; + + acc0 += p0; + acc1 += p1; + acc2 += p2; + acc3 += p3; + acc4 += p4; + acc5 += p5; + acc6 += p6; + acc7 += p7; + } + + /* If the filter length is not a multiple of 8, compute the remaining filter taps */ + tapCnt = numTaps % 0x8u; + + while(tapCnt > 0u) + { + /* Read coefficients */ + c0 = *(pb++); + + /* Fetch 1 state variable */ + x7 = *(px++); + + /* Perform the multiply-accumulates */ + p0 = x0 * c0; + p1 = x1 * c0; + p2 = x2 * c0; + p3 = x3 * c0; + p4 = x4 * c0; + p5 = x5 * c0; + p6 = x6 * c0; + p7 = x7 * c0; + + /* Reuse the present sample states for next sample */ + x0 = x1; + x1 = x2; + x2 = x3; + x3 = x4; + x4 = x5; + x5 = x6; + x6 = x7; + + acc0 += p0; + acc1 += p1; + acc2 += p2; + acc3 += p3; + acc4 += p4; + acc5 += p5; + acc6 += p6; + acc7 += p7; + + /* Decrement the loop counter */ + tapCnt--; + } + + /* Advance the state pointer by 8 to process the next group of 8 samples */ + pState = pState + 8; + + /* The results in the 8 accumulators, store in the destination buffer. */ + *pDst++ = acc0; + *pDst++ = acc1; + *pDst++ = acc2; + *pDst++ = acc3; + *pDst++ = acc4; + *pDst++ = acc5; + *pDst++ = acc6; + *pDst++ = acc7; + + blkCnt--; + } + + /* If the blockSize is not a multiple of 8, compute any remaining output samples here. + ** No loop unrolling is used. */ + blkCnt = blockSize % 0x8u; + + while(blkCnt > 0u) + { + /* Copy one sample at a time into state buffer */ + *pStateCurnt++ = *pSrc++; + + /* Set the accumulator to zero */ + acc0 = 0.0f; + + /* Initialize state pointer */ + px = pState; + + /* Initialize Coefficient pointer */ + pb = (pCoeffs); + + i = numTaps; + + /* Perform the multiply-accumulates */ + do + { + acc0 += *px++ * *pb++; + i--; + + } while(i > 0u); + + /* The result is store in the destination buffer. */ + *pDst++ = acc0; + + /* Advance state pointer by 1 for the next sample */ + pState = pState + 1; + + blkCnt--; + } + + /* Processing is complete. + ** Now copy the last numTaps - 1 samples to the start of the state buffer. + ** This prepares the state buffer for the next function call. */ + + /* Points to the start of the state buffer */ + pStateCurnt = S->pState; + + tapCnt = (numTaps - 1u) >> 2u; + + /* copy data */ + while(tapCnt > 0u) + { + *pStateCurnt++ = *pState++; + *pStateCurnt++ = *pState++; + *pStateCurnt++ = *pState++; + *pStateCurnt++ = *pState++; + + /* Decrement the loop counter */ + tapCnt--; + } + + /* Calculate remaining number of copies */ + tapCnt = (numTaps - 1u) % 0x4u; + + /* Copy the remaining q31_t data */ + while(tapCnt > 0u) + { + *pStateCurnt++ = *pState++; + + /* Decrement the loop counter */ + tapCnt--; + } +} + +#endif + +/** +* @} end of FIR group +*/ diff --git a/gui/cmsis/arm_fir_init_f32.c b/gui/cmsis/arm_fir_init_f32.c new file mode 100644 index 0000000..92bdc9e --- /dev/null +++ b/gui/cmsis/arm_fir_init_f32.c @@ -0,0 +1,96 @@ +/*----------------------------------------------------------------------------- +* Copyright (C) 2010-2014 ARM Limited. All rights reserved. +* +* $Date: 19. March 2015 +* $Revision: V.1.4.5 +* +* Project: CMSIS DSP Library +* Title: arm_fir_init_f32.c +* +* Description: Floating-point FIR filter initialization function. +* +* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0 +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* - Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* - Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* - Neither the name of ARM LIMITED nor the names of its contributors +* may be used to endorse or promote products derived from this +* software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* ---------------------------------------------------------------------------*/ + +#include "arm_math.h" + +/** + * @ingroup groupFilters + */ + +/** + * @addtogroup FIR + * @{ + */ + +/** + * @details + * + * @param[in,out] *S points to an instance of the floating-point FIR filter structure. + * @param[in] numTaps Number of filter coefficients in the filter. + * @param[in] *pCoeffs points to the filter coefficients buffer. + * @param[in] *pState points to the state buffer. + * @param[in] blockSize number of samples that are processed per call. + * @return none. + * + * Description: + * \par + * pCoeffs points to the array of filter coefficients stored in time reversed order: + *
    
+ *    {b[numTaps-1], b[numTaps-2], b[N-2], ..., b[1], b[0]}    
+ * 
+ * \par + * pState points to the array of state variables. + * pState is of length numTaps+blockSize-1 samples, where blockSize is the number of input samples processed by each call to arm_fir_f32(). + */ + +void arm_fir_init_f32( + arm_fir_instance_f32 * S, + uint16_t numTaps, + float32_t * pCoeffs, + float32_t * pState, + uint32_t blockSize) +{ + /* Assign filter taps */ + S->numTaps = numTaps; + + /* Assign coefficient pointer */ + S->pCoeffs = pCoeffs; + + /* Clear state buffer and the size of state buffer is (blockSize + numTaps - 1) */ + memset(pState, 0, (numTaps + (blockSize - 1u)) * sizeof(float32_t)); + + /* Assign state pointer */ + S->pState = pState; + +} + +/** + * @} end of FIR group + */ diff --git a/gui/cmsis/arm_fir_init_q15.c b/gui/cmsis/arm_fir_init_q15.c new file mode 100644 index 0000000..d976d73 --- /dev/null +++ b/gui/cmsis/arm_fir_init_q15.c @@ -0,0 +1,154 @@ +/* ---------------------------------------------------------------------- +* Copyright (C) 2010-2014 ARM Limited. All rights reserved. +* +* $Date: 19. March 2015 +* $Revision: V.1.4.5 +* +* Project: CMSIS DSP Library +* Title: arm_fir_init_q15.c +* +* Description: Q15 FIR filter initialization function. +* +* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0 +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* - Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* - Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* - Neither the name of ARM LIMITED nor the names of its contributors +* may be used to endorse or promote products derived from this +* software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* ------------------------------------------------------------------- */ + +#include "arm_math.h" + +/** + * @ingroup groupFilters + */ + +/** + * @addtogroup FIR + * @{ + */ + +/** + * @param[in,out] *S points to an instance of the Q15 FIR filter structure. + * @param[in] numTaps Number of filter coefficients in the filter. Must be even and greater than or equal to 4. + * @param[in] *pCoeffs points to the filter coefficients buffer. + * @param[in] *pState points to the state buffer. + * @param[in] blockSize is number of samples processed per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if + * numTaps is not greater than or equal to 4 and even. + * + * Description: + * \par + * pCoeffs points to the array of filter coefficients stored in time reversed order: + *
    
+ *    {b[numTaps-1], b[numTaps-2], b[N-2], ..., b[1], b[0]}    
+ * 
+ * Note that numTaps must be even and greater than or equal to 4. + * To implement an odd length filter simply increase numTaps by 1 and set the last coefficient to zero. + * For example, to implement a filter with numTaps=3 and coefficients + *
    
+ *     {0.3, -0.8, 0.3}    
+ * 
+ * set numTaps=4 and use the coefficients: + *
    
+ *     {0.3, -0.8, 0.3, 0}.    
+ * 
+ * Similarly, to implement a two point filter + *
    
+ *     {0.3, -0.3}    
+ * 
+ * set numTaps=4 and use the coefficients: + *
    
+ *     {0.3, -0.3, 0, 0}.    
+ * 
+ * \par + * pState points to the array of state variables. + * pState is of length numTaps+blockSize, when running on Cortex-M4 and Cortex-M3 and is of length numTaps+blockSize-1, when running on Cortex-M0 where blockSize is the number of input samples processed by each call to arm_fir_q15(). + */ + +arm_status arm_fir_init_q15( + arm_fir_instance_q15 * S, + uint16_t numTaps, + q15_t * pCoeffs, + q15_t * pState, + uint32_t blockSize) +{ + arm_status status; + + +#ifndef ARM_MATH_CM0_FAMILY + + /* Run the below code for Cortex-M4 and Cortex-M3 */ + + /* The Number of filter coefficients in the filter must be even and at least 4 */ + if(numTaps & 0x1u) + { + status = ARM_MATH_ARGUMENT_ERROR; + } + else + { + /* Assign filter taps */ + S->numTaps = numTaps; + + /* Assign coefficient pointer */ + S->pCoeffs = pCoeffs; + + /* Clear the state buffer. The size is always (blockSize + numTaps ) */ + memset(pState, 0, (numTaps + (blockSize)) * sizeof(q15_t)); + + /* Assign state pointer */ + S->pState = pState; + + status = ARM_MATH_SUCCESS; + } + + return (status); + +#else + + /* Run the below code for Cortex-M0 */ + + /* Assign filter taps */ + S->numTaps = numTaps; + + /* Assign coefficient pointer */ + S->pCoeffs = pCoeffs; + + /* Clear the state buffer. The size is always (blockSize + numTaps - 1) */ + memset(pState, 0, (numTaps + (blockSize - 1u)) * sizeof(q15_t)); + + /* Assign state pointer */ + S->pState = pState; + + status = ARM_MATH_SUCCESS; + + return (status); + +#endif /* #ifndef ARM_MATH_CM0_FAMILY */ + +} + +/** + * @} end of FIR group + */ diff --git a/gui/cmsis/arm_fir_init_q31.c b/gui/cmsis/arm_fir_init_q31.c new file mode 100644 index 0000000..726cdfc --- /dev/null +++ b/gui/cmsis/arm_fir_init_q31.c @@ -0,0 +1,96 @@ +/* ---------------------------------------------------------------------- +* Copyright (C) 2010-2014 ARM Limited. All rights reserved. +* +* $Date: 19. March 2015 +* $Revision: V.1.4.5 +* +* Project: CMSIS DSP Library +* Title: arm_fir_init_q31.c +* +* Description: Q31 FIR filter initialization function. +* +* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0 +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* - Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* - Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* - Neither the name of ARM LIMITED nor the names of its contributors +* may be used to endorse or promote products derived from this +* software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* -------------------------------------------------------------------- */ + +#include "arm_math.h" + +/** + * @ingroup groupFilters + */ + +/** + * @addtogroup FIR + * @{ + */ + +/** + * @details + * + * @param[in,out] *S points to an instance of the Q31 FIR filter structure. + * @param[in] numTaps Number of filter coefficients in the filter. + * @param[in] *pCoeffs points to the filter coefficients buffer. + * @param[in] *pState points to the state buffer. + * @param[in] blockSize number of samples that are processed per call. + * @return none. + * + * Description: + * \par + * pCoeffs points to the array of filter coefficients stored in time reversed order: + *
    
+ *    {b[numTaps-1], b[numTaps-2], b[N-2], ..., b[1], b[0]}    
+ * 
+ * \par + * pState points to the array of state variables. + * pState is of length numTaps+blockSize-1 samples, where blockSize is the number of input samples processed by each call to arm_fir_q31(). + */ + +void arm_fir_init_q31( + arm_fir_instance_q31 * S, + uint16_t numTaps, + q31_t * pCoeffs, + q31_t * pState, + uint32_t blockSize) +{ + /* Assign filter taps */ + S->numTaps = numTaps; + + /* Assign coefficient pointer */ + S->pCoeffs = pCoeffs; + + /* Clear state buffer and state array size is (blockSize + numTaps - 1) */ + memset(pState, 0, (blockSize + ((uint32_t) numTaps - 1u)) * sizeof(q31_t)); + + /* Assign state pointer */ + S->pState = pState; + +} + +/** + * @} end of FIR group + */ diff --git a/gui/cmsis/arm_fir_init_q7.c b/gui/cmsis/arm_fir_init_q7.c new file mode 100644 index 0000000..083d58e --- /dev/null +++ b/gui/cmsis/arm_fir_init_q7.c @@ -0,0 +1,94 @@ +/* ---------------------------------------------------------------------- +* Copyright (C) 2010-2014 ARM Limited. All rights reserved. +* +* $Date: 19. March 2015 +* $Revision: V.1.4.5 +* +* Project: CMSIS DSP Library +* Title: arm_fir_init_q7.c +* +* Description: Q7 FIR filter initialization function. +* +* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0 +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* - Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* - Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* - Neither the name of ARM LIMITED nor the names of its contributors +* may be used to endorse or promote products derived from this +* software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* ------------------------------------------------------------------- */ + +#include "arm_math.h" + +/** + * @ingroup groupFilters + */ + +/** + * @addtogroup FIR + * @{ + */ +/** + * @param[in,out] *S points to an instance of the Q7 FIR filter structure. + * @param[in] numTaps Number of filter coefficients in the filter. + * @param[in] *pCoeffs points to the filter coefficients buffer. + * @param[in] *pState points to the state buffer. + * @param[in] blockSize number of samples that are processed per call. + * @return none + * + * Description: + * \par + * pCoeffs points to the array of filter coefficients stored in time reversed order: + *
    
+ *    {b[numTaps-1], b[numTaps-2], b[N-2], ..., b[1], b[0]}    
+ * 
+ * \par + * pState points to the array of state variables. + * pState is of length numTaps+blockSize-1 samples, where blockSize is the number of input samples processed by each call to arm_fir_q7(). + */ + +void arm_fir_init_q7( + arm_fir_instance_q7 * S, + uint16_t numTaps, + q7_t * pCoeffs, + q7_t * pState, + uint32_t blockSize) +{ + + /* Assign filter taps */ + S->numTaps = numTaps; + + /* Assign coefficient pointer */ + S->pCoeffs = pCoeffs; + + /* Clear the state buffer. The size is always (blockSize + numTaps - 1) */ + memset(pState, 0, (numTaps + (blockSize - 1u)) * sizeof(q7_t)); + + /* Assign state pointer */ + S->pState = pState; + +} + +/** + * @} end of FIR group + */ diff --git a/gui/cmsis/arm_fir_q15.c b/gui/cmsis/arm_fir_q15.c new file mode 100644 index 0000000..f3c595f --- /dev/null +++ b/gui/cmsis/arm_fir_q15.c @@ -0,0 +1,691 @@ +/* ---------------------------------------------------------------------- +* Copyright (C) 2010-2014 ARM Limited. All rights reserved. +* +* $Date: 19. March 2015 +* $Revision: V.1.4.5 +* +* Project: CMSIS DSP Library +* Title: arm_fir_q15.c +* +* Description: Q15 FIR filter processing function. +* +* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0 +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* - Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* - Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* - Neither the name of ARM LIMITED nor the names of its contributors +* may be used to endorse or promote products derived from this +* software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* -------------------------------------------------------------------- */ + +#include "arm_math.h" + +/** + * @ingroup groupFilters + */ + +/** + * @addtogroup FIR + * @{ + */ + +/** + * @brief Processing function for the Q15 FIR filter. + * @param[in] *S points to an instance of the Q15 FIR structure. + * @param[in] *pSrc points to the block of input data. + * @param[out] *pDst points to the block of output data. + * @param[in] blockSize number of samples to process per call. + * @return none. + * + * + * \par Restrictions + * If the silicon does not support unaligned memory access enable the macro UNALIGNED_SUPPORT_DISABLE + * In this case input, output, state buffers should be aligned by 32-bit + * + * Scaling and Overflow Behavior: + * \par + * The function is implemented using a 64-bit internal accumulator. + * Both coefficients and state variables are represented in 1.15 format and multiplications yield a 2.30 result. + * The 2.30 intermediate results are accumulated in a 64-bit accumulator in 34.30 format. + * There is no risk of internal overflow with this approach and the full precision of intermediate multiplications is preserved. + * After all additions have been performed, the accumulator is truncated to 34.15 format by discarding low 15 bits. + * Lastly, the accumulator is saturated to yield a result in 1.15 format. + * + * \par + * Refer to the function arm_fir_fast_q15() for a faster but less precise implementation of this function. + */ + +#ifndef ARM_MATH_CM0_FAMILY + +/* Run the below code for Cortex-M4 and Cortex-M3 */ + +#ifndef UNALIGNED_SUPPORT_DISABLE + + +void arm_fir_q15( + const arm_fir_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize) +{ + q15_t *pState = S->pState; /* State pointer */ + q15_t *pCoeffs = S->pCoeffs; /* Coefficient pointer */ + q15_t *pStateCurnt; /* Points to the current sample of the state */ + q15_t *px1; /* Temporary q15 pointer for state buffer */ + q15_t *pb; /* Temporary pointer for coefficient buffer */ + q31_t x0, x1, x2, x3, c0; /* Temporary variables to hold SIMD state and coefficient values */ + q63_t acc0, acc1, acc2, acc3; /* Accumulators */ + uint32_t numTaps = S->numTaps; /* Number of taps in the filter */ + uint32_t tapCnt, blkCnt; /* Loop counters */ + + + /* S->pState points to state array which contains previous frame (numTaps - 1) samples */ + /* pStateCurnt points to the location where the new input data should be written */ + pStateCurnt = &(S->pState[(numTaps - 1u)]); + + /* Apply loop unrolling and compute 4 output values simultaneously. + * The variables acc0 ... acc3 hold output values that are being computed: + * + * acc0 = b[numTaps-1] * x[n-numTaps-1] + b[numTaps-2] * x[n-numTaps-2] + b[numTaps-3] * x[n-numTaps-3] +...+ b[0] * x[0] + * acc1 = b[numTaps-1] * x[n-numTaps] + b[numTaps-2] * x[n-numTaps-1] + b[numTaps-3] * x[n-numTaps-2] +...+ b[0] * x[1] + * acc2 = b[numTaps-1] * x[n-numTaps+1] + b[numTaps-2] * x[n-numTaps] + b[numTaps-3] * x[n-numTaps-1] +...+ b[0] * x[2] + * acc3 = b[numTaps-1] * x[n-numTaps+2] + b[numTaps-2] * x[n-numTaps+1] + b[numTaps-3] * x[n-numTaps] +...+ b[0] * x[3] + */ + + blkCnt = blockSize >> 2; + + /* First part of the processing with loop unrolling. Compute 4 outputs at a time. + ** a second loop below computes the remaining 1 to 3 samples. */ + while(blkCnt > 0u) + { + /* Copy four new input samples into the state buffer. + ** Use 32-bit SIMD to move the 16-bit data. Only requires two copies. */ + *__SIMD32(pStateCurnt)++ = *__SIMD32(pSrc)++; + *__SIMD32(pStateCurnt)++ = *__SIMD32(pSrc)++; + + /* Set all accumulators to zero */ + acc0 = 0; + acc1 = 0; + acc2 = 0; + acc3 = 0; + + /* Initialize state pointer of type q15 */ + px1 = pState; + + /* Initialize coeff pointer of type q31 */ + pb = pCoeffs; + + /* Read the first two samples from the state buffer: x[n-N], x[n-N-1] */ + x0 = _SIMD32_OFFSET(px1); + + /* Read the third and forth samples from the state buffer: x[n-N-1], x[n-N-2] */ + x1 = _SIMD32_OFFSET(px1 + 1u); + + px1 += 2u; + + /* Loop over the number of taps. Unroll by a factor of 4. + ** Repeat until we've computed numTaps-4 coefficients. */ + tapCnt = numTaps >> 2; + + while(tapCnt > 0u) + { + /* Read the first two coefficients using SIMD: b[N] and b[N-1] coefficients */ + c0 = *__SIMD32(pb)++; + + /* acc0 += b[N] * x[n-N] + b[N-1] * x[n-N-1] */ + acc0 = __SMLALD(x0, c0, acc0); + + /* acc1 += b[N] * x[n-N-1] + b[N-1] * x[n-N-2] */ + acc1 = __SMLALD(x1, c0, acc1); + + /* Read state x[n-N-2], x[n-N-3] */ + x2 = _SIMD32_OFFSET(px1); + + /* Read state x[n-N-3], x[n-N-4] */ + x3 = _SIMD32_OFFSET(px1 + 1u); + + /* acc2 += b[N] * x[n-N-2] + b[N-1] * x[n-N-3] */ + acc2 = __SMLALD(x2, c0, acc2); + + /* acc3 += b[N] * x[n-N-3] + b[N-1] * x[n-N-4] */ + acc3 = __SMLALD(x3, c0, acc3); + + /* Read coefficients b[N-2], b[N-3] */ + c0 = *__SIMD32(pb)++; + + /* acc0 += b[N-2] * x[n-N-2] + b[N-3] * x[n-N-3] */ + acc0 = __SMLALD(x2, c0, acc0); + + /* acc1 += b[N-2] * x[n-N-3] + b[N-3] * x[n-N-4] */ + acc1 = __SMLALD(x3, c0, acc1); + + /* Read state x[n-N-4], x[n-N-5] */ + x0 = _SIMD32_OFFSET(px1 + 2u); + + /* Read state x[n-N-5], x[n-N-6] */ + x1 = _SIMD32_OFFSET(px1 + 3u); + + /* acc2 += b[N-2] * x[n-N-4] + b[N-3] * x[n-N-5] */ + acc2 = __SMLALD(x0, c0, acc2); + + /* acc3 += b[N-2] * x[n-N-5] + b[N-3] * x[n-N-6] */ + acc3 = __SMLALD(x1, c0, acc3); + + px1 += 4u; + + tapCnt--; + + } + + + /* If the filter length is not a multiple of 4, compute the remaining filter taps. + ** This is always be 2 taps since the filter length is even. */ + if((numTaps & 0x3u) != 0u) + { + /* Read 2 coefficients */ + c0 = *__SIMD32(pb)++; + + /* Fetch 4 state variables */ + x2 = _SIMD32_OFFSET(px1); + + x3 = _SIMD32_OFFSET(px1 + 1u); + + /* Perform the multiply-accumulates */ + acc0 = __SMLALD(x0, c0, acc0); + + px1 += 2u; + + acc1 = __SMLALD(x1, c0, acc1); + acc2 = __SMLALD(x2, c0, acc2); + acc3 = __SMLALD(x3, c0, acc3); + } + + /* The results in the 4 accumulators are in 2.30 format. Convert to 1.15 with saturation. + ** Then store the 4 outputs in the destination buffer. */ + +#ifndef ARM_MATH_BIG_ENDIAN + + *__SIMD32(pDst)++ = + __PKHBT(__SSAT((acc0 >> 15), 16), __SSAT((acc1 >> 15), 16), 16); + *__SIMD32(pDst)++ = + __PKHBT(__SSAT((acc2 >> 15), 16), __SSAT((acc3 >> 15), 16), 16); + +#else + + *__SIMD32(pDst)++ = + __PKHBT(__SSAT((acc1 >> 15), 16), __SSAT((acc0 >> 15), 16), 16); + *__SIMD32(pDst)++ = + __PKHBT(__SSAT((acc3 >> 15), 16), __SSAT((acc2 >> 15), 16), 16); + +#endif /* #ifndef ARM_MATH_BIG_ENDIAN */ + + + + /* Advance the state pointer by 4 to process the next group of 4 samples */ + pState = pState + 4; + + /* Decrement the loop counter */ + blkCnt--; + } + + /* If the blockSize is not a multiple of 4, compute any remaining output samples here. + ** No loop unrolling is used. */ + blkCnt = blockSize % 0x4u; + while(blkCnt > 0u) + { + /* Copy two samples into state buffer */ + *pStateCurnt++ = *pSrc++; + + /* Set the accumulator to zero */ + acc0 = 0; + + /* Initialize state pointer of type q15 */ + px1 = pState; + + /* Initialize coeff pointer of type q31 */ + pb = pCoeffs; + + tapCnt = numTaps >> 1; + + do + { + + c0 = *__SIMD32(pb)++; + x0 = *__SIMD32(px1)++; + + acc0 = __SMLALD(x0, c0, acc0); + tapCnt--; + } + while(tapCnt > 0u); + + /* The result is in 2.30 format. Convert to 1.15 with saturation. + ** Then store the output in the destination buffer. */ + *pDst++ = (q15_t) (__SSAT((acc0 >> 15), 16)); + + /* Advance state pointer by 1 for the next sample */ + pState = pState + 1; + + /* Decrement the loop counter */ + blkCnt--; + } + + /* Processing is complete. + ** Now copy the last numTaps - 1 samples to the satrt of the state buffer. + ** This prepares the state buffer for the next function call. */ + + /* Points to the start of the state buffer */ + pStateCurnt = S->pState; + + /* Calculation of count for copying integer writes */ + tapCnt = (numTaps - 1u) >> 2; + + while(tapCnt > 0u) + { + + /* Copy state values to start of state buffer */ + *__SIMD32(pStateCurnt)++ = *__SIMD32(pState)++; + *__SIMD32(pStateCurnt)++ = *__SIMD32(pState)++; + + tapCnt--; + + } + + /* Calculation of count for remaining q15_t data */ + tapCnt = (numTaps - 1u) % 0x4u; + + /* copy remaining data */ + while(tapCnt > 0u) + { + *pStateCurnt++ = *pState++; + + /* Decrement the loop counter */ + tapCnt--; + } +} + +#else /* UNALIGNED_SUPPORT_DISABLE */ + +void arm_fir_q15( + const arm_fir_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize) +{ + q15_t *pState = S->pState; /* State pointer */ + q15_t *pCoeffs = S->pCoeffs; /* Coefficient pointer */ + q15_t *pStateCurnt; /* Points to the current sample of the state */ + q63_t acc0, acc1, acc2, acc3; /* Accumulators */ + q15_t *pb; /* Temporary pointer for coefficient buffer */ + q15_t *px; /* Temporary q31 pointer for SIMD state buffer accesses */ + q31_t x0, x1, x2, c0; /* Temporary variables to hold SIMD state and coefficient values */ + uint32_t numTaps = S->numTaps; /* Number of taps in the filter */ + uint32_t tapCnt, blkCnt; /* Loop counters */ + + + /* S->pState points to state array which contains previous frame (numTaps - 1) samples */ + /* pStateCurnt points to the location where the new input data should be written */ + pStateCurnt = &(S->pState[(numTaps - 1u)]); + + /* Apply loop unrolling and compute 4 output values simultaneously. + * The variables acc0 ... acc3 hold output values that are being computed: + * + * acc0 = b[numTaps-1] * x[n-numTaps-1] + b[numTaps-2] * x[n-numTaps-2] + b[numTaps-3] * x[n-numTaps-3] +...+ b[0] * x[0] + * acc1 = b[numTaps-1] * x[n-numTaps] + b[numTaps-2] * x[n-numTaps-1] + b[numTaps-3] * x[n-numTaps-2] +...+ b[0] * x[1] + * acc2 = b[numTaps-1] * x[n-numTaps+1] + b[numTaps-2] * x[n-numTaps] + b[numTaps-3] * x[n-numTaps-1] +...+ b[0] * x[2] + * acc3 = b[numTaps-1] * x[n-numTaps+2] + b[numTaps-2] * x[n-numTaps+1] + b[numTaps-3] * x[n-numTaps] +...+ b[0] * x[3] + */ + + blkCnt = blockSize >> 2; + + /* First part of the processing with loop unrolling. Compute 4 outputs at a time. + ** a second loop below computes the remaining 1 to 3 samples. */ + while(blkCnt > 0u) + { + /* Copy four new input samples into the state buffer. + ** Use 32-bit SIMD to move the 16-bit data. Only requires two copies. */ + *pStateCurnt++ = *pSrc++; + *pStateCurnt++ = *pSrc++; + *pStateCurnt++ = *pSrc++; + *pStateCurnt++ = *pSrc++; + + + /* Set all accumulators to zero */ + acc0 = 0; + acc1 = 0; + acc2 = 0; + acc3 = 0; + + /* Typecast q15_t pointer to q31_t pointer for state reading in q31_t */ + px = pState; + + /* Typecast q15_t pointer to q31_t pointer for coefficient reading in q31_t */ + pb = pCoeffs; + + /* Read the first two samples from the state buffer: x[n-N], x[n-N-1] */ + x0 = *__SIMD32(px)++; + + /* Read the third and forth samples from the state buffer: x[n-N-2], x[n-N-3] */ + x2 = *__SIMD32(px)++; + + /* Loop over the number of taps. Unroll by a factor of 4. + ** Repeat until we've computed numTaps-(numTaps%4) coefficients. */ + tapCnt = numTaps >> 2; + + while(tapCnt > 0) + { + /* Read the first two coefficients using SIMD: b[N] and b[N-1] coefficients */ + c0 = *__SIMD32(pb)++; + + /* acc0 += b[N] * x[n-N] + b[N-1] * x[n-N-1] */ + acc0 = __SMLALD(x0, c0, acc0); + + /* acc2 += b[N] * x[n-N-2] + b[N-1] * x[n-N-3] */ + acc2 = __SMLALD(x2, c0, acc2); + + /* pack x[n-N-1] and x[n-N-2] */ +#ifndef ARM_MATH_BIG_ENDIAN + x1 = __PKHBT(x2, x0, 0); +#else + x1 = __PKHBT(x0, x2, 0); +#endif + + /* Read state x[n-N-4], x[n-N-5] */ + x0 = _SIMD32_OFFSET(px); + + /* acc1 += b[N] * x[n-N-1] + b[N-1] * x[n-N-2] */ + acc1 = __SMLALDX(x1, c0, acc1); + + /* pack x[n-N-3] and x[n-N-4] */ +#ifndef ARM_MATH_BIG_ENDIAN + x1 = __PKHBT(x0, x2, 0); +#else + x1 = __PKHBT(x2, x0, 0); +#endif + + /* acc3 += b[N] * x[n-N-3] + b[N-1] * x[n-N-4] */ + acc3 = __SMLALDX(x1, c0, acc3); + + /* Read coefficients b[N-2], b[N-3] */ + c0 = *__SIMD32(pb)++; + + /* acc0 += b[N-2] * x[n-N-2] + b[N-3] * x[n-N-3] */ + acc0 = __SMLALD(x2, c0, acc0); + + /* Read state x[n-N-6], x[n-N-7] with offset */ + x2 = _SIMD32_OFFSET(px + 2u); + + /* acc2 += b[N-2] * x[n-N-4] + b[N-3] * x[n-N-5] */ + acc2 = __SMLALD(x0, c0, acc2); + + /* acc1 += b[N-2] * x[n-N-3] + b[N-3] * x[n-N-4] */ + acc1 = __SMLALDX(x1, c0, acc1); + + /* pack x[n-N-5] and x[n-N-6] */ +#ifndef ARM_MATH_BIG_ENDIAN + x1 = __PKHBT(x2, x0, 0); +#else + x1 = __PKHBT(x0, x2, 0); +#endif + + /* acc3 += b[N-2] * x[n-N-5] + b[N-3] * x[n-N-6] */ + acc3 = __SMLALDX(x1, c0, acc3); + + /* Update state pointer for next state reading */ + px += 4u; + + /* Decrement tap count */ + tapCnt--; + + } + + /* If the filter length is not a multiple of 4, compute the remaining filter taps. + ** This is always be 2 taps since the filter length is even. */ + if((numTaps & 0x3u) != 0u) + { + + /* Read last two coefficients */ + c0 = *__SIMD32(pb)++; + + /* Perform the multiply-accumulates */ + acc0 = __SMLALD(x0, c0, acc0); + acc2 = __SMLALD(x2, c0, acc2); + + /* pack state variables */ +#ifndef ARM_MATH_BIG_ENDIAN + x1 = __PKHBT(x2, x0, 0); +#else + x1 = __PKHBT(x0, x2, 0); +#endif + + /* Read last state variables */ + x0 = *__SIMD32(px); + + /* Perform the multiply-accumulates */ + acc1 = __SMLALDX(x1, c0, acc1); + + /* pack state variables */ +#ifndef ARM_MATH_BIG_ENDIAN + x1 = __PKHBT(x0, x2, 0); +#else + x1 = __PKHBT(x2, x0, 0); +#endif + + /* Perform the multiply-accumulates */ + acc3 = __SMLALDX(x1, c0, acc3); + } + + /* The results in the 4 accumulators are in 2.30 format. Convert to 1.15 with saturation. + ** Then store the 4 outputs in the destination buffer. */ + +#ifndef ARM_MATH_BIG_ENDIAN + + *__SIMD32(pDst)++ = + __PKHBT(__SSAT((acc0 >> 15), 16), __SSAT((acc1 >> 15), 16), 16); + + *__SIMD32(pDst)++ = + __PKHBT(__SSAT((acc2 >> 15), 16), __SSAT((acc3 >> 15), 16), 16); + +#else + + *__SIMD32(pDst)++ = + __PKHBT(__SSAT((acc1 >> 15), 16), __SSAT((acc0 >> 15), 16), 16); + + *__SIMD32(pDst)++ = + __PKHBT(__SSAT((acc3 >> 15), 16), __SSAT((acc2 >> 15), 16), 16); + +#endif /* #ifndef ARM_MATH_BIG_ENDIAN */ + + /* Advance the state pointer by 4 to process the next group of 4 samples */ + pState = pState + 4; + + /* Decrement the loop counter */ + blkCnt--; + } + + /* If the blockSize is not a multiple of 4, compute any remaining output samples here. + ** No loop unrolling is used. */ + blkCnt = blockSize % 0x4u; + while(blkCnt > 0u) + { + /* Copy two samples into state buffer */ + *pStateCurnt++ = *pSrc++; + + /* Set the accumulator to zero */ + acc0 = 0; + + /* Use SIMD to hold states and coefficients */ + px = pState; + pb = pCoeffs; + + tapCnt = numTaps >> 1u; + + do + { + acc0 += (q31_t) * px++ * *pb++; + acc0 += (q31_t) * px++ * *pb++; + tapCnt--; + } + while(tapCnt > 0u); + + /* The result is in 2.30 format. Convert to 1.15 with saturation. + ** Then store the output in the destination buffer. */ + *pDst++ = (q15_t) (__SSAT((acc0 >> 15), 16)); + + /* Advance state pointer by 1 for the next sample */ + pState = pState + 1u; + + /* Decrement the loop counter */ + blkCnt--; + } + + /* Processing is complete. + ** Now copy the last numTaps - 1 samples to the satrt of the state buffer. + ** This prepares the state buffer for the next function call. */ + + /* Points to the start of the state buffer */ + pStateCurnt = S->pState; + + /* Calculation of count for copying integer writes */ + tapCnt = (numTaps - 1u) >> 2; + + while(tapCnt > 0u) + { + *pStateCurnt++ = *pState++; + *pStateCurnt++ = *pState++; + *pStateCurnt++ = *pState++; + *pStateCurnt++ = *pState++; + + tapCnt--; + + } + + /* Calculation of count for remaining q15_t data */ + tapCnt = (numTaps - 1u) % 0x4u; + + /* copy remaining data */ + while(tapCnt > 0u) + { + *pStateCurnt++ = *pState++; + + /* Decrement the loop counter */ + tapCnt--; + } +} + + +#endif /* #ifndef UNALIGNED_SUPPORT_DISABLE */ + +#else /* ARM_MATH_CM0_FAMILY */ + + +/* Run the below code for Cortex-M0 */ + +void arm_fir_q15( + const arm_fir_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize) +{ + q15_t *pState = S->pState; /* State pointer */ + q15_t *pCoeffs = S->pCoeffs; /* Coefficient pointer */ + q15_t *pStateCurnt; /* Points to the current sample of the state */ + + + + q15_t *px; /* Temporary pointer for state buffer */ + q15_t *pb; /* Temporary pointer for coefficient buffer */ + q63_t acc; /* Accumulator */ + uint32_t numTaps = S->numTaps; /* Number of nTaps in the filter */ + uint32_t tapCnt, blkCnt; /* Loop counters */ + + /* S->pState buffer contains previous frame (numTaps - 1) samples */ + /* pStateCurnt points to the location where the new input data should be written */ + pStateCurnt = &(S->pState[(numTaps - 1u)]); + + /* Initialize blkCnt with blockSize */ + blkCnt = blockSize; + + while(blkCnt > 0u) + { + /* Copy one sample at a time into state buffer */ + *pStateCurnt++ = *pSrc++; + + /* Set the accumulator to zero */ + acc = 0; + + /* Initialize state pointer */ + px = pState; + + /* Initialize Coefficient pointer */ + pb = pCoeffs; + + tapCnt = numTaps; + + /* Perform the multiply-accumulates */ + do + { + /* acc = b[numTaps-1] * x[n-numTaps-1] + b[numTaps-2] * x[n-numTaps-2] + b[numTaps-3] * x[n-numTaps-3] +...+ b[0] * x[0] */ + acc += (q31_t) * px++ * *pb++; + tapCnt--; + } while(tapCnt > 0u); + + /* The result is in 2.30 format. Convert to 1.15 + ** Then store the output in the destination buffer. */ + *pDst++ = (q15_t) __SSAT((acc >> 15u), 16); + + /* Advance state pointer by 1 for the next sample */ + pState = pState + 1; + + /* Decrement the samples loop counter */ + blkCnt--; + } + + /* Processing is complete. + ** Now copy the last numTaps - 1 samples to the satrt of the state buffer. + ** This prepares the state buffer for the next function call. */ + + /* Points to the start of the state buffer */ + pStateCurnt = S->pState; + + /* Copy numTaps number of values */ + tapCnt = (numTaps - 1u); + + /* copy data */ + while(tapCnt > 0u) + { + *pStateCurnt++ = *pState++; + + /* Decrement the loop counter */ + tapCnt--; + } + +} + +#endif /* #ifndef ARM_MATH_CM0_FAMILY */ + + + + +/** + * @} end of FIR group + */ diff --git a/gui/cmsis/arm_fir_q31.c b/gui/cmsis/arm_fir_q31.c new file mode 100644 index 0000000..af5707f --- /dev/null +++ b/gui/cmsis/arm_fir_q31.c @@ -0,0 +1,365 @@ +/* ---------------------------------------------------------------------- +* Copyright (C) 2010-2014 ARM Limited. All rights reserved. +* +* $Date: 19. March 2015 +* $Revision: V.1.4.5 +* +* Project: CMSIS DSP Library +* Title: arm_fir_q31.c +* +* Description: Q31 FIR filter processing function. +* +* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0 +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* - Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* - Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* - Neither the name of ARM LIMITED nor the names of its contributors +* may be used to endorse or promote products derived from this +* software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* -------------------------------------------------------------------- */ + +#include "arm_math.h" + +/** + * @ingroup groupFilters + */ + +/** + * @addtogroup FIR + * @{ + */ + +/** + * @param[in] *S points to an instance of the Q31 FIR filter structure. + * @param[in] *pSrc points to the block of input data. + * @param[out] *pDst points to the block of output data. + * @param[in] blockSize number of samples to process per call. + * @return none. + * + * @details + * Scaling and Overflow Behavior: + * \par + * The function is implemented using an internal 64-bit accumulator. + * The accumulator has a 2.62 format and maintains full precision of the intermediate multiplication results but provides only a single guard bit. + * Thus, if the accumulator result overflows it wraps around rather than clip. + * In order to avoid overflows completely the input signal must be scaled down by log2(numTaps) bits. + * After all multiply-accumulates are performed, the 2.62 accumulator is right shifted by 31 bits and saturated to 1.31 format to yield the final result. + * + * \par + * Refer to the function arm_fir_fast_q31() for a faster but less precise implementation of this filter for Cortex-M3 and Cortex-M4. + */ + +void arm_fir_q31( + const arm_fir_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize) +{ + q31_t *pState = S->pState; /* State pointer */ + q31_t *pCoeffs = S->pCoeffs; /* Coefficient pointer */ + q31_t *pStateCurnt; /* Points to the current sample of the state */ + + +#ifndef ARM_MATH_CM0_FAMILY + + /* Run the below code for Cortex-M4 and Cortex-M3 */ + + q31_t x0, x1, x2; /* Temporary variables to hold state */ + q31_t c0; /* Temporary variable to hold coefficient value */ + q31_t *px; /* Temporary pointer for state */ + q31_t *pb; /* Temporary pointer for coefficient buffer */ + q63_t acc0, acc1, acc2; /* Accumulators */ + uint32_t numTaps = S->numTaps; /* Number of filter coefficients in the filter */ + uint32_t i, tapCnt, blkCnt, tapCntN3; /* Loop counters */ + + /* S->pState points to state array which contains previous frame (numTaps - 1) samples */ + /* pStateCurnt points to the location where the new input data should be written */ + pStateCurnt = &(S->pState[(numTaps - 1u)]); + + /* Apply loop unrolling and compute 4 output values simultaneously. + * The variables acc0 ... acc3 hold output values that are being computed: + * + * acc0 = b[numTaps-1] * x[n-numTaps-1] + b[numTaps-2] * x[n-numTaps-2] + b[numTaps-3] * x[n-numTaps-3] +...+ b[0] * x[0] + * acc1 = b[numTaps-1] * x[n-numTaps] + b[numTaps-2] * x[n-numTaps-1] + b[numTaps-3] * x[n-numTaps-2] +...+ b[0] * x[1] + * acc2 = b[numTaps-1] * x[n-numTaps+1] + b[numTaps-2] * x[n-numTaps] + b[numTaps-3] * x[n-numTaps-1] +...+ b[0] * x[2] + * acc3 = b[numTaps-1] * x[n-numTaps+2] + b[numTaps-2] * x[n-numTaps+1] + b[numTaps-3] * x[n-numTaps] +...+ b[0] * x[3] + */ + blkCnt = blockSize / 3; + blockSize = blockSize - (3 * blkCnt); + + tapCnt = numTaps / 3; + tapCntN3 = numTaps - (3 * tapCnt); + + /* First part of the processing with loop unrolling. Compute 4 outputs at a time. + ** a second loop below computes the remaining 1 to 3 samples. */ + while(blkCnt > 0u) + { + /* Copy three new input samples into the state buffer */ + *pStateCurnt++ = *pSrc++; + *pStateCurnt++ = *pSrc++; + *pStateCurnt++ = *pSrc++; + + /* Set all accumulators to zero */ + acc0 = 0; + acc1 = 0; + acc2 = 0; + + /* Initialize state pointer */ + px = pState; + + /* Initialize coefficient pointer */ + pb = pCoeffs; + + /* Read the first two samples from the state buffer: + * x[n-numTaps], x[n-numTaps-1] */ + x0 = *(px++); + x1 = *(px++); + + /* Loop unrolling. Process 3 taps at a time. */ + i = tapCnt; + + while(i > 0u) + { + /* Read the b[numTaps] coefficient */ + c0 = *pb; + + /* Read x[n-numTaps-2] sample */ + x2 = *(px++); + + /* Perform the multiply-accumulates */ + acc0 += ((q63_t) x0 * c0); + acc1 += ((q63_t) x1 * c0); + acc2 += ((q63_t) x2 * c0); + + /* Read the coefficient and state */ + c0 = *(pb + 1u); + x0 = *(px++); + + /* Perform the multiply-accumulates */ + acc0 += ((q63_t) x1 * c0); + acc1 += ((q63_t) x2 * c0); + acc2 += ((q63_t) x0 * c0); + + /* Read the coefficient and state */ + c0 = *(pb + 2u); + x1 = *(px++); + + /* update coefficient pointer */ + pb += 3u; + + /* Perform the multiply-accumulates */ + acc0 += ((q63_t) x2 * c0); + acc1 += ((q63_t) x0 * c0); + acc2 += ((q63_t) x1 * c0); + + /* Decrement the loop counter */ + i--; + } + + /* If the filter length is not a multiple of 3, compute the remaining filter taps */ + + i = tapCntN3; + + while(i > 0u) + { + /* Read coefficients */ + c0 = *(pb++); + + /* Fetch 1 state variable */ + x2 = *(px++); + + /* Perform the multiply-accumulates */ + acc0 += ((q63_t) x0 * c0); + acc1 += ((q63_t) x1 * c0); + acc2 += ((q63_t) x2 * c0); + + /* Reuse the present sample states for next sample */ + x0 = x1; + x1 = x2; + + /* Decrement the loop counter */ + i--; + } + + /* Advance the state pointer by 3 to process the next group of 3 samples */ + pState = pState + 3; + + /* The results in the 3 accumulators are in 2.30 format. Convert to 1.31 + ** Then store the 3 outputs in the destination buffer. */ + *pDst++ = (q31_t) (acc0 >> 31u); + *pDst++ = (q31_t) (acc1 >> 31u); + *pDst++ = (q31_t) (acc2 >> 31u); + + /* Decrement the samples loop counter */ + blkCnt--; + } + + /* If the blockSize is not a multiple of 3, compute any remaining output samples here. + ** No loop unrolling is used. */ + + while(blockSize > 0u) + { + /* Copy one sample at a time into state buffer */ + *pStateCurnt++ = *pSrc++; + + /* Set the accumulator to zero */ + acc0 = 0; + + /* Initialize state pointer */ + px = pState; + + /* Initialize Coefficient pointer */ + pb = (pCoeffs); + + i = numTaps; + + /* Perform the multiply-accumulates */ + do + { + acc0 += (q63_t) * (px++) * (*(pb++)); + i--; + } while(i > 0u); + + /* The result is in 2.62 format. Convert to 1.31 + ** Then store the output in the destination buffer. */ + *pDst++ = (q31_t) (acc0 >> 31u); + + /* Advance state pointer by 1 for the next sample */ + pState = pState + 1; + + /* Decrement the samples loop counter */ + blockSize--; + } + + /* Processing is complete. + ** Now copy the last numTaps - 1 samples to the satrt of the state buffer. + ** This prepares the state buffer for the next function call. */ + + /* Points to the start of the state buffer */ + pStateCurnt = S->pState; + + tapCnt = (numTaps - 1u) >> 2u; + + /* copy data */ + while(tapCnt > 0u) + { + *pStateCurnt++ = *pState++; + *pStateCurnt++ = *pState++; + *pStateCurnt++ = *pState++; + *pStateCurnt++ = *pState++; + + /* Decrement the loop counter */ + tapCnt--; + } + + /* Calculate remaining number of copies */ + tapCnt = (numTaps - 1u) % 0x4u; + + /* Copy the remaining q31_t data */ + while(tapCnt > 0u) + { + *pStateCurnt++ = *pState++; + + /* Decrement the loop counter */ + tapCnt--; + } + +#else + +/* Run the below code for Cortex-M0 */ + + q31_t *px; /* Temporary pointer for state */ + q31_t *pb; /* Temporary pointer for coefficient buffer */ + q63_t acc; /* Accumulator */ + uint32_t numTaps = S->numTaps; /* Length of the filter */ + uint32_t i, tapCnt, blkCnt; /* Loop counters */ + + /* S->pState buffer contains previous frame (numTaps - 1) samples */ + /* pStateCurnt points to the location where the new input data should be written */ + pStateCurnt = &(S->pState[(numTaps - 1u)]); + + /* Initialize blkCnt with blockSize */ + blkCnt = blockSize; + + while(blkCnt > 0u) + { + /* Copy one sample at a time into state buffer */ + *pStateCurnt++ = *pSrc++; + + /* Set the accumulator to zero */ + acc = 0; + + /* Initialize state pointer */ + px = pState; + + /* Initialize Coefficient pointer */ + pb = pCoeffs; + + i = numTaps; + + /* Perform the multiply-accumulates */ + do + { + /* acc = b[numTaps-1] * x[n-numTaps-1] + b[numTaps-2] * x[n-numTaps-2] + b[numTaps-3] * x[n-numTaps-3] +...+ b[0] * x[0] */ + acc += (q63_t) * px++ * *pb++; + i--; + } while(i > 0u); + + /* The result is in 2.62 format. Convert to 1.31 + ** Then store the output in the destination buffer. */ + *pDst++ = (q31_t) (acc >> 31u); + + /* Advance state pointer by 1 for the next sample */ + pState = pState + 1; + + /* Decrement the samples loop counter */ + blkCnt--; + } + + /* Processing is complete. + ** Now copy the last numTaps - 1 samples to the starting of the state buffer. + ** This prepares the state buffer for the next function call. */ + + /* Points to the start of the state buffer */ + pStateCurnt = S->pState; + + /* Copy numTaps number of values */ + tapCnt = numTaps - 1u; + + /* Copy the data */ + while(tapCnt > 0u) + { + *pStateCurnt++ = *pState++; + + /* Decrement the loop counter */ + tapCnt--; + } + + +#endif /* #ifndef ARM_MATH_CM0_FAMILY */ + +} + +/** + * @} end of FIR group + */ diff --git a/gui/cmsis/arm_fir_q7.c b/gui/cmsis/arm_fir_q7.c new file mode 100644 index 0000000..54a30e2 --- /dev/null +++ b/gui/cmsis/arm_fir_q7.c @@ -0,0 +1,397 @@ +/* ---------------------------------------------------------------------- +* Copyright (C) 2010-2014 ARM Limited. All rights reserved. +* +* $Date: 19. March 2015 +* $Revision: V.1.4.5 +* +* Project: CMSIS DSP Library +* Title: arm_fir_q7.c +* +* Description: Q7 FIR filter processing function. +* +* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0 +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* - Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* - Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* - Neither the name of ARM LIMITED nor the names of its contributors +* may be used to endorse or promote products derived from this +* software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* -------------------------------------------------------------------- */ + +#include "arm_math.h" + +/** + * @ingroup groupFilters + */ + +/** + * @addtogroup FIR + * @{ + */ + +/** + * @param[in] *S points to an instance of the Q7 FIR filter structure. + * @param[in] *pSrc points to the block of input data. + * @param[out] *pDst points to the block of output data. + * @param[in] blockSize number of samples to process per call. + * @return none. + * + * Scaling and Overflow Behavior: + * \par + * The function is implemented using a 32-bit internal accumulator. + * Both coefficients and state variables are represented in 1.7 format and multiplications yield a 2.14 result. + * The 2.14 intermediate results are accumulated in a 32-bit accumulator in 18.14 format. + * There is no risk of internal overflow with this approach and the full precision of intermediate multiplications is preserved. + * The accumulator is converted to 18.7 format by discarding the low 7 bits. + * Finally, the result is truncated to 1.7 format. + */ + +void arm_fir_q7( + const arm_fir_instance_q7 * S, + q7_t * pSrc, + q7_t * pDst, + uint32_t blockSize) +{ + +#ifndef ARM_MATH_CM0_FAMILY + + /* Run the below code for Cortex-M4 and Cortex-M3 */ + + q7_t *pState = S->pState; /* State pointer */ + q7_t *pCoeffs = S->pCoeffs; /* Coefficient pointer */ + q7_t *pStateCurnt; /* Points to the current sample of the state */ + q7_t x0, x1, x2, x3; /* Temporary variables to hold state */ + q7_t c0; /* Temporary variable to hold coefficient value */ + q7_t *px; /* Temporary pointer for state */ + q7_t *pb; /* Temporary pointer for coefficient buffer */ + q31_t acc0, acc1, acc2, acc3; /* Accumulators */ + uint32_t numTaps = S->numTaps; /* Number of filter coefficients in the filter */ + uint32_t i, tapCnt, blkCnt; /* Loop counters */ + + /* S->pState points to state array which contains previous frame (numTaps - 1) samples */ + /* pStateCurnt points to the location where the new input data should be written */ + pStateCurnt = &(S->pState[(numTaps - 1u)]); + + /* Apply loop unrolling and compute 4 output values simultaneously. + * The variables acc0 ... acc3 hold output values that are being computed: + * + * acc0 = b[numTaps-1] * x[n-numTaps-1] + b[numTaps-2] * x[n-numTaps-2] + b[numTaps-3] * x[n-numTaps-3] +...+ b[0] * x[0] + * acc1 = b[numTaps-1] * x[n-numTaps] + b[numTaps-2] * x[n-numTaps-1] + b[numTaps-3] * x[n-numTaps-2] +...+ b[0] * x[1] + * acc2 = b[numTaps-1] * x[n-numTaps+1] + b[numTaps-2] * x[n-numTaps] + b[numTaps-3] * x[n-numTaps-1] +...+ b[0] * x[2] + * acc3 = b[numTaps-1] * x[n-numTaps+2] + b[numTaps-2] * x[n-numTaps+1] + b[numTaps-3] * x[n-numTaps] +...+ b[0] * x[3] + */ + blkCnt = blockSize >> 2; + + /* First part of the processing with loop unrolling. Compute 4 outputs at a time. + ** a second loop below computes the remaining 1 to 3 samples. */ + while(blkCnt > 0u) + { + /* Copy four new input samples into the state buffer */ + *pStateCurnt++ = *pSrc++; + *pStateCurnt++ = *pSrc++; + *pStateCurnt++ = *pSrc++; + *pStateCurnt++ = *pSrc++; + + /* Set all accumulators to zero */ + acc0 = 0; + acc1 = 0; + acc2 = 0; + acc3 = 0; + + /* Initialize state pointer */ + px = pState; + + /* Initialize coefficient pointer */ + pb = pCoeffs; + + /* Read the first three samples from the state buffer: + * x[n-numTaps], x[n-numTaps-1], x[n-numTaps-2] */ + x0 = *(px++); + x1 = *(px++); + x2 = *(px++); + + /* Loop unrolling. Process 4 taps at a time. */ + tapCnt = numTaps >> 2; + i = tapCnt; + + while(i > 0u) + { + /* Read the b[numTaps] coefficient */ + c0 = *pb; + + /* Read x[n-numTaps-3] sample */ + x3 = *px; + + /* acc0 += b[numTaps] * x[n-numTaps] */ + acc0 += ((q15_t) x0 * c0); + + /* acc1 += b[numTaps] * x[n-numTaps-1] */ + acc1 += ((q15_t) x1 * c0); + + /* acc2 += b[numTaps] * x[n-numTaps-2] */ + acc2 += ((q15_t) x2 * c0); + + /* acc3 += b[numTaps] * x[n-numTaps-3] */ + acc3 += ((q15_t) x3 * c0); + + /* Read the b[numTaps-1] coefficient */ + c0 = *(pb + 1u); + + /* Read x[n-numTaps-4] sample */ + x0 = *(px + 1u); + + /* Perform the multiply-accumulates */ + acc0 += ((q15_t) x1 * c0); + acc1 += ((q15_t) x2 * c0); + acc2 += ((q15_t) x3 * c0); + acc3 += ((q15_t) x0 * c0); + + /* Read the b[numTaps-2] coefficient */ + c0 = *(pb + 2u); + + /* Read x[n-numTaps-5] sample */ + x1 = *(px + 2u); + + /* Perform the multiply-accumulates */ + acc0 += ((q15_t) x2 * c0); + acc1 += ((q15_t) x3 * c0); + acc2 += ((q15_t) x0 * c0); + acc3 += ((q15_t) x1 * c0); + + /* Read the b[numTaps-3] coefficients */ + c0 = *(pb + 3u); + + /* Read x[n-numTaps-6] sample */ + x2 = *(px + 3u); + + /* Perform the multiply-accumulates */ + acc0 += ((q15_t) x3 * c0); + acc1 += ((q15_t) x0 * c0); + acc2 += ((q15_t) x1 * c0); + acc3 += ((q15_t) x2 * c0); + + /* update coefficient pointer */ + pb += 4u; + px += 4u; + + /* Decrement the loop counter */ + i--; + } + + /* If the filter length is not a multiple of 4, compute the remaining filter taps */ + + i = numTaps - (tapCnt * 4u); + while(i > 0u) + { + /* Read coefficients */ + c0 = *(pb++); + + /* Fetch 1 state variable */ + x3 = *(px++); + + /* Perform the multiply-accumulates */ + acc0 += ((q15_t) x0 * c0); + acc1 += ((q15_t) x1 * c0); + acc2 += ((q15_t) x2 * c0); + acc3 += ((q15_t) x3 * c0); + + /* Reuse the present sample states for next sample */ + x0 = x1; + x1 = x2; + x2 = x3; + + /* Decrement the loop counter */ + i--; + } + + /* Advance the state pointer by 4 to process the next group of 4 samples */ + pState = pState + 4; + + /* The results in the 4 accumulators are in 2.62 format. Convert to 1.31 + ** Then store the 4 outputs in the destination buffer. */ + acc0 = __SSAT((acc0 >> 7u), 8); + *pDst++ = acc0; + acc1 = __SSAT((acc1 >> 7u), 8); + *pDst++ = acc1; + acc2 = __SSAT((acc2 >> 7u), 8); + *pDst++ = acc2; + acc3 = __SSAT((acc3 >> 7u), 8); + *pDst++ = acc3; + + /* Decrement the samples loop counter */ + blkCnt--; + } + + + /* If the blockSize is not a multiple of 4, compute any remaining output samples here. + ** No loop unrolling is used. */ + blkCnt = blockSize % 4u; + + while(blkCnt > 0u) + { + /* Copy one sample at a time into state buffer */ + *pStateCurnt++ = *pSrc++; + + /* Set the accumulator to zero */ + acc0 = 0; + + /* Initialize state pointer */ + px = pState; + + /* Initialize Coefficient pointer */ + pb = (pCoeffs); + + i = numTaps; + + /* Perform the multiply-accumulates */ + do + { + acc0 += (q15_t) * (px++) * (*(pb++)); + i--; + } while(i > 0u); + + /* The result is in 2.14 format. Convert to 1.7 + ** Then store the output in the destination buffer. */ + *pDst++ = __SSAT((acc0 >> 7u), 8); + + /* Advance state pointer by 1 for the next sample */ + pState = pState + 1; + + /* Decrement the samples loop counter */ + blkCnt--; + } + + /* Processing is complete. + ** Now copy the last numTaps - 1 samples to the satrt of the state buffer. + ** This prepares the state buffer for the next function call. */ + + /* Points to the start of the state buffer */ + pStateCurnt = S->pState; + + tapCnt = (numTaps - 1u) >> 2u; + + /* copy data */ + while(tapCnt > 0u) + { + *pStateCurnt++ = *pState++; + *pStateCurnt++ = *pState++; + *pStateCurnt++ = *pState++; + *pStateCurnt++ = *pState++; + + /* Decrement the loop counter */ + tapCnt--; + } + + /* Calculate remaining number of copies */ + tapCnt = (numTaps - 1u) % 0x4u; + + /* Copy the remaining q31_t data */ + while(tapCnt > 0u) + { + *pStateCurnt++ = *pState++; + + /* Decrement the loop counter */ + tapCnt--; + } + +#else + +/* Run the below code for Cortex-M0 */ + + uint32_t numTaps = S->numTaps; /* Number of taps in the filter */ + uint32_t i, blkCnt; /* Loop counters */ + q7_t *pState = S->pState; /* State pointer */ + q7_t *pCoeffs = S->pCoeffs; /* Coefficient pointer */ + q7_t *px, *pb; /* Temporary pointers to state and coeff */ + q31_t acc = 0; /* Accumlator */ + q7_t *pStateCurnt; /* Points to the current sample of the state */ + + + /* S->pState points to state array which contains previous frame (numTaps - 1) samples */ + /* pStateCurnt points to the location where the new input data should be written */ + pStateCurnt = S->pState + (numTaps - 1u); + + /* Initialize blkCnt with blockSize */ + blkCnt = blockSize; + + /* Perform filtering upto BlockSize - BlockSize%4 */ + while(blkCnt > 0u) + { + /* Copy one sample at a time into state buffer */ + *pStateCurnt++ = *pSrc++; + + /* Set accumulator to zero */ + acc = 0; + + /* Initialize state pointer of type q7 */ + px = pState; + + /* Initialize coeff pointer of type q7 */ + pb = pCoeffs; + + + i = numTaps; + + while(i > 0u) + { + /* acc = b[numTaps-1] * x[n-numTaps-1] + b[numTaps-2] * x[n-numTaps-2] + b[numTaps-3] * x[n-numTaps-3] +...+ b[0] * x[0] */ + acc += (q15_t) * px++ * *pb++; + i--; + } + + /* Store the 1.7 format filter output in destination buffer */ + *pDst++ = (q7_t) __SSAT((acc >> 7), 8); + + /* Advance the state pointer by 1 to process the next sample */ + pState = pState + 1; + + /* Decrement the loop counter */ + blkCnt--; + } + + /* Processing is complete. + ** Now copy the last numTaps - 1 samples to the satrt of the state buffer. + ** This prepares the state buffer for the next function call. */ + + + /* Points to the start of the state buffer */ + pStateCurnt = S->pState; + + + /* Copy numTaps number of values */ + i = (numTaps - 1u); + + /* Copy q7_t data */ + while(i > 0u) + { + *pStateCurnt++ = *pState++; + i--; + } + +#endif /* #ifndef ARM_MATH_CM0_FAMILY */ + +} + +/** + * @} end of FIR group + */ diff --git a/gui/wxmain.cpp b/gui/wxmain.cpp index 02dc4c0..75eedb6 100644 --- a/gui/wxmain.cpp +++ b/gui/wxmain.cpp @@ -29,14 +29,17 @@ #include #include -#ifndef WIN32 +#ifndef STMDSP_WIN32 #include +#include #endif #include "wxmain_devdata.h" enum Id { - MeasureTimer = 1, + TimerPerformance = 1, + TimerRecord, + TimerWavClip, MFileNew, MFileOpen, @@ -56,7 +59,7 @@ enum Id { MRunGenStart, MCodeCompile, MCodeDisassemble, - CompileOutput + CompileOutput }; MainFrame::MainFrame() : @@ -87,14 +90,16 @@ MainFrame::MainFrame() : wxEmptyString, wxDefaultPosition, wxSize(620, 250), wxTE_READONLY | wxTE_MULTILINE | wxHSCROLL | wxTE_RICH2); - m_measure_timer = new wxTimer(this, Id::MeasureTimer); + m_timer_performance = new wxTimer(this, Id::TimerPerformance); + m_timer_record = new wxTimer(this, Id::TimerRecord); + m_timer_wavclip = new wxTimer(this, Id::TimerWavClip); m_menu_bar = new wxMenuBar; m_rate_select = new wxComboBox(panelToolbar, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, srateValues.size(), srateValues.data(), wxCB_READONLY); -#ifndef WIN32 +#ifndef STMDSP_WIN32 m_device_samples = reinterpret_cast(::mmap( nullptr, stmdsp::SAMPLES_MAX * sizeof(stmdsp::adcsample_t), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0)); @@ -102,8 +107,8 @@ MainFrame::MainFrame() : nullptr, stmdsp::SAMPLES_MAX * sizeof(stmdsp::adcsample_t), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0)); #else - m_device_samples = new stmdsp::adcsample_t[stmdsp::SAMPLES_MAX]; - m_device_samples_input = new stmdsp::adcsample_t[stmdsp::SAMPLES_MAX]; + m_device_samples = new stmdsp::adcsample_t[stmdsp::SAMPLES_MAX]; + m_device_samples_input = new stmdsp::adcsample_t[stmdsp::SAMPLES_MAX]; #endif m_menu_bar->Append(menuFile, "&File"); @@ -143,10 +148,12 @@ MainFrame::MainFrame() : // Binds: // General - Bind(wxEVT_TIMER, &MainFrame::onMeasureTimer, this, Id::MeasureTimer); - Bind(wxEVT_CLOSE_WINDOW, &MainFrame::onCloseEvent, this, wxID_ANY); + Bind(wxEVT_TIMER, &MainFrame::onTimerPerformance, this, Id::TimerPerformance); + Bind(wxEVT_TIMER, &MainFrame::onTimerRecord, this, Id::TimerRecord); + Bind(wxEVT_TIMER, &MainFrame::onTimerWavClip, this, Id::TimerWavClip); + Bind(wxEVT_CLOSE_WINDOW, &MainFrame::onCloseEvent, this, wxID_ANY); m_compile_output-> - Bind(wxEVT_PAINT, &MainFrame::onPaint, this, Id::CompileOutput); + Bind(wxEVT_PAINT, &MainFrame::onPaint, this, Id::CompileOutput); // Toolbar actions Bind(wxEVT_BUTTON, &MainFrame::onRunCompile, this, wxID_ANY, wxID_ANY, comp); @@ -192,7 +199,9 @@ void MainFrame::onCloseEvent(wxCloseEvent& event) //delete m_menu_bar->Remove(1); //delete m_menu_bar->Remove(0); //delete m_menu_bar; - delete m_measure_timer; + delete m_timer_performance; + delete m_timer_record; + delete m_timer_wavclip; delete m_device; Unbind(wxEVT_COMBOBOX, &MainFrame::onToolbarSampleRate, this, wxID_ANY, wxID_ANY); @@ -201,46 +210,45 @@ void MainFrame::onCloseEvent(wxCloseEvent& event) event.Skip(); } -// Measure timer tick handler -// Only called while connected and running. -void MainFrame::onMeasureTimer(wxTimerEvent&) +void MainFrame::onTimerPerformance(wxTimerEvent&) { - if (m_conv_result_log || m_run_draw_samples->IsChecked()) { - auto samples = m_device->continuous_read(); - if (samples.size() > 0) { - std::copy(samples.cbegin(), samples.cend(), m_device_samples); - - if (m_conv_result_log) { - for (auto& s : samples) { - auto str = std::to_string(s) + ','; - m_conv_result_log->Write(str.c_str(), str.size()); - } - m_conv_result_log->Write("\n", 1); - } - if (m_run_draw_samples->IsChecked()) { - samples = m_device->continuous_read_input(); - std::copy(samples.cbegin(), samples.cend(), m_device_samples_input); - m_compile_output->Refresh(); + // Show execution time + m_status_bar->SetStatusText(wxString::Format(wxT("Execution time: %u cycles"), + m_device->continuous_start_get_measurement())); +} + +void MainFrame::onTimerRecord(wxTimerEvent&) +{ + auto samples = m_device->continuous_read(); + if (samples.size() > 0) { + std::copy(samples.cbegin(), samples.cend(), m_device_samples); + + if (m_conv_result_log) { + for (auto& s : samples) { + auto str = std::to_string(s) + ','; + m_conv_result_log->Write(str.c_str(), str.size()); } + m_conv_result_log->Write("\n", 1); } - } - if (m_wav_clip) { - // Stream out next WAV chunk - auto size = m_device->get_buffer_size(); - auto chunk = new stmdsp::adcsample_t[size]; - auto src = reinterpret_cast(m_wav_clip->next(size)); - for (unsigned int i = 0; i < size; i++) - chunk[i] = ((uint32_t)*src++) / 16 + 2048; - m_device->siggen_upload(chunk, size); - delete[] chunk; + if (m_run_draw_samples->IsChecked()) { + samples = m_device->continuous_read_input(); + std::copy(samples.cbegin(), samples.cend(), m_device_samples_input); + m_compile_output->Refresh(); + } } +} - if (m_run_measure->IsChecked()) { - // Show execution time - m_status_bar->SetStatusText(wxString::Format(wxT("Execution time: %u cycles"), - m_device->continuous_start_get_measurement())); - } +void MainFrame::onTimerWavClip(wxTimerEvent&) +{ + // Stream out next WAV chunk + auto size = m_device->get_buffer_size(); + auto chunk = new stmdsp::adcsample_t[size]; + auto src = reinterpret_cast(m_wav_clip->next(size)); + for (unsigned int i = 0; i < size; i++) + chunk[i] = ((uint32_t)*src++) / 16 + 2048; + m_device->siggen_upload(chunk, size); + delete[] chunk; } void MainFrame::onPaint(wxPaintEvent&) @@ -248,9 +256,9 @@ void MainFrame::onPaint(wxPaintEvent&) if (!m_is_running || !m_run_draw_samples->IsChecked()) return; - const auto& dim = m_compile_output->GetSize(); + const auto& dim = m_compile_output->GetSize(); wxRect rect { - 0, 0, dim.GetWidth(), dim.GetHeight() + 0, 0, dim.GetWidth(), dim.GetHeight() }; wxBufferedPaintDC dc (m_compile_output); @@ -323,10 +331,10 @@ void MainFrame::prepareEditor() wxString MainFrame::compileEditorCode() { - stmdsp::platform platform; + stmdsp::platform platform; if (m_device != nullptr) { - platform = m_device->get_platform(); - } else { + platform = m_device->get_platform(); + } else { m_status_bar->SetStatusText("Assuming L4 platform..."); platform = stmdsp::platform::L4; } @@ -342,17 +350,19 @@ wxString MainFrame::compileEditorCode() file.Write(wxString(file_text) + m_text_editor->GetText()); file.Close(); - constexpr const char *script_ext = + constexpr const char *script_ext = #ifndef STMDSP_WIN32 - ".sh"; + ".sh"; #else - ".bat"; + ".bat"; #endif wxFile makefile (m_temp_file_name + script_ext, wxFile::write); wxString make_text (platform == stmdsp::platform::L4 ? makefile_text_l4 : makefile_text_h7); make_text.Replace("$0", m_temp_file_name); + char cwd[PATH_MAX]; + make_text.Replace("$1", getcwd(cwd, sizeof(cwd))); makefile.Write(make_text); makefile.Close(); @@ -363,12 +373,12 @@ wxString MainFrame::compileEditorCode() #ifndef STMDSP_WIN32 system(wxString("chmod +x ") + m_temp_file_name + script_ext); #endif - int result = system(make_command.ToAscii()); - wxFile result_file (make_output); - wxString result_text; - result_file.ReadAll(&result_text); - result_file.Close(); - m_compile_output->Clear(); + int result = system(make_command.ToAscii()); + wxFile result_file (make_output); + wxString result_text; + result_file.ReadAll(&result_text); + result_file.Close(); + m_compile_output->Clear(); m_compile_output->WriteText(result_text); wxRemoveFile(m_temp_file_name); @@ -401,12 +411,12 @@ void MainFrame::onCodeDisassemble(wxCommandEvent&) if (system(command.ToAscii()) == 0) { wxFile result_file (output); - wxString result_text; - result_file.ReadAll(&result_text); - result_file.Close(); - m_compile_output->Clear(); - m_compile_output->WriteText(result_text); - wxRemoveFile(output); + wxString result_text; + result_file.ReadAll(&result_text); + result_file.Close(); + m_compile_output->Clear(); + m_compile_output->WriteText(result_text); + wxRemoveFile(output); m_status_bar->SetStatusText(wxString::Format(wxT("Done. Line count: %u."), m_compile_output->GetNumberOfLines())); } else { diff --git a/gui/wxmain.hpp b/gui/wxmain.hpp index 9b3db1e..11131eb 100644 --- a/gui/wxmain.hpp +++ b/gui/wxmain.hpp @@ -59,7 +59,9 @@ public: void onCodeDisassemble(wxCommandEvent&); void onPaint(wxPaintEvent&); - void onMeasureTimer(wxTimerEvent&); + void onTimerPerformance(wxTimerEvent&); + void onTimerRecord(wxTimerEvent&); + void onTimerWavClip(wxTimerEvent&); private: // Set to true if connected and running @@ -71,7 +73,9 @@ private: wxControl *m_signal_area = nullptr; wxMenuItem *m_run_measure = nullptr; wxMenuItem *m_run_draw_samples = nullptr; - wxTimer *m_measure_timer = nullptr; + wxTimer *m_timer_performance = nullptr; + wxTimer *m_timer_record = nullptr; + wxTimer *m_timer_wavclip = nullptr; wxStatusBar *m_status_bar = nullptr; wxMenuBar *m_menu_bar = nullptr; wxComboBox *m_rate_select = nullptr; diff --git a/gui/wxmain_devdata.cpp b/gui/wxmain_devdata.cpp index 0f384fa..551f6cc 100644 --- a/gui/wxmain_devdata.cpp +++ b/gui/wxmain_devdata.cpp @@ -26,13 +26,14 @@ const std::array srateNums { #endif // $0 = temp file name +// TODO try -ffunction-sections -fdata-sections -Wl,--gc-sections const char *makefile_text_h7 = #ifdef STMDSP_WIN32 "echo off" NEWLINE #endif "arm-none-eabi-g++ -x c++ -Os -std=c++20 -fno-exceptions -fno-rtti " "-mcpu=cortex-m7 -mthumb -mfloat-abi=hard -mfpu=fpv5-d16 -mtune=cortex-m7 " - "-nostartfiles " + "-nostartfiles " "-Wl,-Ttext-segment=0x00000000 -Wl,-zmax-page-size=512 -Wl,-eprocess_data_entry " "$0 -o $0.o" NEWLINE COPY " $0.o $0.orig.o" NEWLINE @@ -48,7 +49,7 @@ const char *makefile_text_l4 = #endif "arm-none-eabi-g++ -x c++ -Os -std=c++20 -fno-exceptions -fno-rtti " "-mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mtune=cortex-m4 " - "-nostartfiles " + "-nostartfiles -I$1/cmsis" "-Wl,-Ttext-segment=0x10000000 -Wl,-zmax-page-size=512 -Wl,-eprocess_data_entry " "$0 -o $0.o" NEWLINE COPY " $0.o $0.orig.o" NEWLINE diff --git a/gui/wxmain_mrun.cpp b/gui/wxmain_mrun.cpp index 5661832..58b1873 100644 --- a/gui/wxmain_mrun.cpp +++ b/gui/wxmain_mrun.cpp @@ -46,15 +46,19 @@ void MainFrame::onRunStart(wxCommandEvent& ce) if (!m_is_running) { if (m_run_measure->IsChecked()) { m_device->continuous_start_measure(); - m_measure_timer->StartOnce(1000); + m_timer_performance->StartOnce(1000); } else { if (m_device->is_siggening() && m_wav_clip) { - m_measure_timer->Start(m_device->get_buffer_size() * 500 / + // TODO Confirm need for factor of 500 + m_timer_wavclip->Start(m_device->get_buffer_size() * 500 / srateNums[m_rate_select->GetSelection()]); } else if (m_conv_result_log) { - m_measure_timer->Start(15); + m_timer_record->Start(m_device->get_buffer_size() / + srateNums[m_rate_select->GetSelection()] * + 800 / 1000); } else if (m_run_draw_samples->IsChecked()) { - m_measure_timer->Start(300); + m_timer_record->Start(m_device->get_buffer_size() / + srateNums[m_rate_select->GetSelection()]); } m_device->continuous_start(); @@ -66,7 +70,9 @@ void MainFrame::onRunStart(wxCommandEvent& ce) m_is_running = true; } else { m_device->continuous_stop(); - m_measure_timer->Stop(); + m_timer_performance->Stop(); + m_timer_record->Stop(); + m_timer_wavclip->Stop(); m_rate_select->Enable(true); menuItem->SetItemLabel("&Start"); diff --git a/source/main.cpp b/source/main.cpp index e151a3d..aaf268a 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -99,6 +99,9 @@ static unsigned char elf_file_store[MAX_ELF_FILE_SIZE]; __attribute__((section(".convdata"))) static ELF::Entry elf_entry = nullptr; +static char userMessageBuffer[128]; +static unsigned char userMessageSize = 0; + __attribute__((section(".convcode"))) static void conversion_unprivileged_main(); @@ -187,6 +190,7 @@ THD_FUNCTION(communicationThread, arg) // 'S' - Stop conversion. // 's' - Get latest block of conversion results. // 't' - Get latest block of conversion input. + // 'u' - Get user message. // 'W' - Start signal generator (siggen). // 'w' - Stop siggen. @@ -361,6 +365,10 @@ THD_FUNCTION(communicationThread, arg) } break; + case 'u': + USBSerial::write(reinterpret_cast(userMessageBuffer), userMessageSize); + break; + case 'W': DAC::start(1, samplesSigGen.data(), samplesSigGen.size()); break; @@ -648,6 +656,17 @@ void port_syscall(struct port_extctx *ctxp, uint32_t n) case 3: ctxp->r0 = ADC::readAlt(0); break; + case 4: + { + const char *str = reinterpret_cast(ctxp->r0); + auto src = str; + auto dst = userMessageBuffer; + while (*src) + *dst++ = *src++; + *dst = '\0'; + userMessageSize = src - str; + } + break; default: while (1); break; From f1773b634eb6cf4e1312379dcc7bcbab7291c60b Mon Sep 17 00:00:00 2001 From: Clyne Sullivan Date: Sun, 23 May 2021 13:19:09 -0400 Subject: [PATCH 02/13] 2nd pot; some doc; smooth WAV playback --- gui/wxmain_devdata.cpp | 24 +++++-- gui/wxmain_mrun.cpp | 22 +++--- source/adc.cpp | 19 ++--- source/adc.hpp | 2 +- source/dac.cpp | 18 ++++- source/dac.hpp | 4 +- source/elf_load.cpp | 2 +- source/elf_load.hpp | 2 +- source/main.cpp | 156 +++++++++++++++++++++++----------------- source/samplebuffer.cpp | 11 +++ source/samplebuffer.hpp | 11 +++ source/sclock.cpp | 11 +++ source/sclock.hpp | 11 +++ source/usbserial.cpp | 4 +- source/usbserial.hpp | 2 +- 15 files changed, 198 insertions(+), 101 deletions(-) diff --git a/gui/wxmain_devdata.cpp b/gui/wxmain_devdata.cpp index 551f6cc..7f736a2 100644 --- a/gui/wxmain_devdata.cpp +++ b/gui/wxmain_devdata.cpp @@ -49,16 +49,16 @@ const char *makefile_text_l4 = #endif "arm-none-eabi-g++ -x c++ -Os -std=c++20 -fno-exceptions -fno-rtti " "-mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mtune=cortex-m4 " - "-nostartfiles -I$1/cmsis" + "-nostartfiles -I$1/cmsis " "-Wl,-Ttext-segment=0x10000000 -Wl,-zmax-page-size=512 -Wl,-eprocess_data_entry " "$0 -o $0.o" NEWLINE - COPY " $0.o $0.orig.o" NEWLINE - "arm-none-eabi-strip -s -S --strip-unneeded $0.o" NEWLINE - "arm-none-eabi-objcopy --remove-section .ARM.attributes " + COPY " $0.o $0.orig.o" NEWLINE + "arm-none-eabi-strip -s -S --strip-unneeded $0.o" NEWLINE + "arm-none-eabi-objcopy --remove-section .ARM.attributes " "--remove-section .comment " "--remove-section .noinit " "$0.o" NEWLINE - "arm-none-eabi-size $0.o" NEWLINE; + "arm-none-eabi-size $0.o" NEWLINE; // $0 = buffer size const char *file_header_h7 = R"cpp( @@ -168,11 +168,21 @@ asm("vsqrt.f32 s0, s0; bx lr"); return 0; } -auto readalt() { +auto readpot1() { Sample s; -asm("push {r4-r6}; svc 3; mov %0, r0; pop {r4-r6}" : "=&r"(s)); +asm("push {r4-r6}; eor r0, r0; svc 3; mov %0, r0; pop {r4-r6}" : "=&r"(s)); return s; } +auto readpot2() { +Sample s; +asm("push {r4-r6}; mov r0, #1; svc 3; mov %0, r0; pop {r4-r6}" : "=&r"(s)); +return s; +} + +void puts(const char *s) { +// 's' will already be in r0. +asm("push {r4-r6}; svc 4; pop {r4-r6}"); +} // End stmdspgui header code diff --git a/gui/wxmain_mrun.cpp b/gui/wxmain_mrun.cpp index 58b1873..e12d068 100644 --- a/gui/wxmain_mrun.cpp +++ b/gui/wxmain_mrun.cpp @@ -48,18 +48,16 @@ void MainFrame::onRunStart(wxCommandEvent& ce) m_device->continuous_start_measure(); m_timer_performance->StartOnce(1000); } else { - if (m_device->is_siggening() && m_wav_clip) { - // TODO Confirm need for factor of 500 - m_timer_wavclip->Start(m_device->get_buffer_size() * 500 / - srateNums[m_rate_select->GetSelection()]); - } else if (m_conv_result_log) { - m_timer_record->Start(m_device->get_buffer_size() / - srateNums[m_rate_select->GetSelection()] * - 800 / 1000); - } else if (m_run_draw_samples->IsChecked()) { - m_timer_record->Start(m_device->get_buffer_size() / - srateNums[m_rate_select->GetSelection()]); - } + auto reqSpeedExact = + m_device->get_buffer_size() + / static_cast(srateNums[m_rate_select->GetSelection()]) + * 1000.f * 0.5f; + int reqSpeed = reqSpeedExact; + + if (m_device->is_siggening() && m_wav_clip) + m_timer_wavclip->Start(reqSpeed); + if (m_conv_result_log || m_run_draw_samples->IsChecked()) + m_timer_record->Start(reqSpeed); m_device->continuous_start(); } diff --git a/source/adc.cpp b/source/adc.cpp index 3ab5430..2a4fa38 100644 --- a/source/adc.cpp +++ b/source/adc.cpp @@ -2,7 +2,7 @@ * @file adc.cpp * @brief Manages signal reading through the ADC. * - * Copyright (C) 2020 Clyne Sullivan + * Copyright (C) 2021 Clyne Sullivan * * Distributed under the GNU GPL v3 or later. You should have received a copy of * the GNU General Public License along with this program. @@ -69,7 +69,7 @@ static void readAltCallback(ADCDriver *) } ADCConversionGroup ADC::m_group_config2 = { .circular = false, - .num_channels = 1, + .num_channels = 2, .end_cb = readAltCallback, .error_cb = nullptr, .cfgr = ADC_CFGR_EXTEN_RISING | ADC_CFGR_EXTSEL_SRC(13), /* TIM6_TRGO */ @@ -88,10 +88,10 @@ ADCConversionGroup ADC::m_group_config2 = { .awd3cr = 0, #endif .smpr = { - ADC_SMPR1_SMP_AN1(ADC_SMPR_SMP_12P5), 0 + ADC_SMPR1_SMP_AN1(ADC_SMPR_SMP_12P5) | ADC_SMPR1_SMP_AN2(ADC_SMPR_SMP_12P5), 0 }, .sqr = { - ADC_SQR1_SQ1_N(ADC_CHANNEL_IN1), + ADC_SQR1_SQ1_N(ADC_CHANNEL_IN1) | ADC_SQR1_SQ2_N(ADC_CHANNEL_IN2), 0, 0, 0 }, }; @@ -107,6 +107,7 @@ void ADC::begin() #else palSetPadMode(GPIOA, 0, PAL_MODE_INPUT_ANALOG); // Algorithm in palSetPadMode(GPIOC, 0, PAL_MODE_INPUT_ANALOG); // Potentiometer 1 + palSetPadMode(GPIOC, 1, PAL_MODE_INPUT_ANALOG); // Potentiometer 2 #endif adcStart(m_driver, &m_config); @@ -135,15 +136,15 @@ void ADC::stop() adcsample_t ADC::readAlt(unsigned int id) { - if (id != 0) + if (id > 1) return 0; - static adcsample_t result[32] = {}; + static adcsample_t result[16] = {}; readAltDone = false; - adcStartConversion(m_driver2, &m_group_config2, result, 32); + adcStartConversion(m_driver2, &m_group_config2, result, 8); while (!readAltDone) - ; + __WFI(); adcStopConversion(m_driver2); - return result[0]; + return result[id]; } void ADC::setRate(SClock::Rate rate) diff --git a/source/adc.hpp b/source/adc.hpp index 24a7fff..5f7fa08 100644 --- a/source/adc.hpp +++ b/source/adc.hpp @@ -2,7 +2,7 @@ * @file adc.hpp * @brief Manages signal reading through the ADC. * - * Copyright (C) 2020 Clyne Sullivan + * Copyright (C) 2021 Clyne Sullivan * * Distributed under the GNU GPL v3 or later. You should have received a copy of * the GNU General Public License along with this program. diff --git a/source/dac.cpp b/source/dac.cpp index ce9c465..2772928 100644 --- a/source/dac.cpp +++ b/source/dac.cpp @@ -2,7 +2,7 @@ * @file dac.cpp * @brief Manages signal creation using the DAC. * - * Copyright (C) 2020 Clyne Sullivan + * Copyright (C) 2021 Clyne Sullivan * * Distributed under the GNU GPL v3 or later. You should have received a copy of * the GNU General Public License along with this program. @@ -22,9 +22,16 @@ const DACConfig DAC::m_config = { .cr = 0 }; +static int dacIsDone = -1; +static void dacEndCallback(DACDriver *dacd) +{ + if (dacd == &DACD2) + dacIsDone = dacIsBufferComplete(dacd) ? 1 : 0; +} + const DACConversionGroup DAC::m_group_config = { .num_channels = 1, - .end_cb = nullptr, + .end_cb = dacEndCallback, .error_cb = nullptr, #if defined(TARGET_PLATFORM_H7) .trigger = 5 // TIM6_TRGO @@ -45,11 +52,18 @@ void DAC::begin() void DAC::start(int channel, dacsample_t *buffer, size_t count) { if (channel >= 0 && channel < 2) { + if (channel == 1) + dacIsDone = -1; dacStartConversion(m_driver[channel], &m_group_config, buffer, count); SClock::start(); } } +int DAC::sigGenWantsMore() +{ + return dacIsDone; +} + void DAC::stop(int channel) { if (channel >= 0 && channel < 2) { diff --git a/source/dac.hpp b/source/dac.hpp index e305c4b..4360c26 100644 --- a/source/dac.hpp +++ b/source/dac.hpp @@ -2,7 +2,7 @@ * @file dac.hpp * @brief Manages signal creation using the DAC. * - * Copyright (C) 2020 Clyne Sullivan + * Copyright (C) 2021 Clyne Sullivan * * Distributed under the GNU GPL v3 or later. You should have received a copy of * the GNU General Public License along with this program. @@ -23,6 +23,8 @@ public: static void start(int channel, dacsample_t *buffer, size_t count); static void stop(int channel); + static int sigGenWantsMore(); + private: static DACDriver *m_driver[2]; diff --git a/source/elf_load.cpp b/source/elf_load.cpp index 0e41d6a..e161206 100644 --- a/source/elf_load.cpp +++ b/source/elf_load.cpp @@ -2,7 +2,7 @@ * @file elf_load.cpp * @brief Loads ELF binary data into memory for execution. * - * Copyright (C) 2020 Clyne Sullivan + * Copyright (C) 2021 Clyne Sullivan * * Distributed under the GNU GPL v3 or later. You should have received a copy of * the GNU General Public License along with this program. diff --git a/source/elf_load.hpp b/source/elf_load.hpp index 619dada..ae7265b 100644 --- a/source/elf_load.hpp +++ b/source/elf_load.hpp @@ -2,7 +2,7 @@ * @file elf_load.hpp * @brief Loads ELF binary data into memory for execution. * - * Copyright (C) 2020 Clyne Sullivan + * Copyright (C) 2021 Clyne Sullivan * * Distributed under the GNU GPL v3 or later. You should have received a copy of * the GNU General Public License along with this program. diff --git a/source/main.cpp b/source/main.cpp index aaf268a..e9c33ef 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -2,7 +2,7 @@ * @file main.cpp * @brief Program entry point. * - * Copyright (C) 2020 Clyne Sullivan + * Copyright (C) 2021 Clyne Sullivan * * Distributed under the GNU GPL v3 or later. You should have received a copy of * the GNU General Public License along with this program. @@ -26,8 +26,16 @@ static_assert(sizeof(dacsample_t) == sizeof(uint16_t)); #include -constexpr unsigned int MAX_ELF_FILE_SIZE = 16 * 1024; +// Pin definitions +// +#if defined(TARGET_PLATFORM_L4) +constexpr auto LINE_LED_GREEN = PAL_LINE(GPIOC_BASE, 10U); +constexpr auto LINE_LED_YELLOW = PAL_LINE(GPIOC_BASE, 11U); +constexpr auto LINE_LED_RED = PAL_LINE(GPIOC_BASE, 12U); +#endif +// Run status +// enum class RunStatus : char { Idle = '1', @@ -36,6 +44,8 @@ enum class RunStatus : char }; static RunStatus run_status = RunStatus::Idle; +// Conversion threads messaging +// #define MSG_CONVFIRST (1) #define MSG_CONVSECOND (2) #define MSG_CONVFIRST_MEASURE (3) @@ -44,43 +54,11 @@ static RunStatus run_status = RunStatus::Idle; #define MSG_FOR_FIRST(m) (m & 1) #define MSG_FOR_MEASURE(m) (m > 2) -static ErrorManager EM; - static msg_t conversionMBBuffer[2]; static MAILBOX_DECL(conversionMB, conversionMBBuffer, 2); -// Thread for LED status and wakeup hold -__attribute__((section(".stacks"))) -static THD_WORKING_AREA(monitorThreadWA, 256); -static THD_FUNCTION(monitorThread, arg); - -// Thread for managing the conversion task -__attribute__((section(".stacks"))) -static THD_WORKING_AREA(conversionThreadMonitorWA, 1024); -static THD_FUNCTION(conversionThreadMonitor, arg); -static thread_t *conversionThreadHandle = nullptr; - -// Thread for unprivileged algorithm execution -__attribute__((section(".stacks"))) -static THD_WORKING_AREA(conversionThreadWA, 128); // All we do is enter unprivileged mode. -static THD_FUNCTION(conversionThread, arg); -constexpr unsigned int conversionThreadUPWASize = -#if defined(TARGET_PLATFORM_H7) - 62 * 1024; -#else - 15 * 1024; -#endif -__attribute__((section(".convdata"))) -static THD_WORKING_AREA(conversionThreadUPWA, conversionThreadUPWASize); -__attribute__((section(".convdata"))) -static thread_t *conversionThreadMonitorHandle = nullptr; - -// Thread for USB monitoring -__attribute__((section(".stacks"))) -static THD_WORKING_AREA(communicationThreadWA, 4096); -static THD_FUNCTION(communicationThread, arg); - -static time_measurement_t conversion_time_measurement; +// Sample input and output buffers +// #if defined(TARGET_PLATFORM_H7) __attribute__((section(".convdata"))) static SampleBuffer samplesIn (reinterpret_cast(0x38000000)); // 16k @@ -95,35 +73,38 @@ static SampleBuffer samplesOut (reinterpret_cast(0x2000C000)); // 16k static SampleBuffer samplesSigGen (reinterpret_cast(0x20010000)); // 16k #endif +// Algorithm binary storage +// +constexpr unsigned int MAX_ELF_FILE_SIZE = 16 * 1024; static unsigned char elf_file_store[MAX_ELF_FILE_SIZE]; __attribute__((section(".convdata"))) static ELF::Entry elf_entry = nullptr; +// Other variables +// +static ErrorManager EM; +static time_measurement_t conversion_time_measurement; static char userMessageBuffer[128]; static unsigned char userMessageSize = 0; +// Functions +// __attribute__((section(".convcode"))) static void conversion_unprivileged_main(); - -static void mpu_setup(); +static void startThreads(); +static void mpuSetup(); static void abortAlgorithmFromISR(); -static void signal_operate(adcsample_t *buffer, size_t count); -static void signal_operate_measure(adcsample_t *buffer, size_t count); - -#if defined(TARGET_PLATFORM_L4) -constexpr auto LINE_LED_GREEN = PAL_LINE(GPIOC_BASE, 10U); -constexpr auto LINE_LED_YELLOW = PAL_LINE(GPIOC_BASE, 11U); -constexpr auto LINE_LED_RED = PAL_LINE(GPIOC_BASE, 12U); -#endif +static void signalOperate(adcsample_t *buffer, size_t count); +static void signalOperateMeasure(adcsample_t *buffer, size_t count); int main() { - // Initialize the RTOS + // Initialize ChibiOS halInit(); chSysInit(); SCB->CPACR |= 0xF << 20; // Enable FPU - mpu_setup(); + mpuSetup(); #if defined(TARGET_PLATFORM_L4) palSetLineMode(LINE_LED_GREEN, PAL_MODE_OUTPUT_PUSHPULL); @@ -140,7 +121,42 @@ int main() SClock::setRate(SClock::Rate::R32K); ADC::setRate(SClock::Rate::R32K); - chTMObjectInit(&conversion_time_measurement); + startThreads(); + chThdExit(0); + return 0; +} + +static THD_FUNCTION(monitorThread, arg); // Runs status LEDs and allows debug halt. +static THD_FUNCTION(conversionThreadMonitor, arg); // Monitors and manages algo. thread. +static THD_FUNCTION(conversionThread, arg); // Algorithm thread (unprivileged). +static THD_FUNCTION(communicationThread, arg); // Manages USB communications. + +// Need to hold some thread handles for mailbox usage. +static thread_t *conversionThreadHandle = nullptr; +__attribute__((section(".convdata"))) +static thread_t *conversionThreadMonitorHandle = nullptr; + +// The more stack for the algorithm, the merrier. +constexpr unsigned int conversionThreadUPWASize = +#if defined(TARGET_PLATFORM_H7) + 62 * 1024; +#else + 15 * 1024; +#endif + +__attribute__((section(".stacks"))) +static THD_WORKING_AREA(monitorThreadWA, 256); +__attribute__((section(".stacks"))) +static THD_WORKING_AREA(conversionThreadMonitorWA, 1024); +__attribute__((section(".stacks"))) +static THD_WORKING_AREA(conversionThreadWA, 128); // For entering unprivileged mode. +__attribute__((section(".convdata"))) +static THD_WORKING_AREA(conversionThreadUPWA, conversionThreadUPWASize); +__attribute__((section(".stacks"))) +static THD_WORKING_AREA(communicationThreadWA, 4096); + +void startThreads() +{ chThdCreateStatic( monitorThreadWA, sizeof(monitorThreadWA), LOWPRIO, @@ -149,19 +165,17 @@ int main() conversionThreadMonitorWA, sizeof(conversionThreadMonitorWA), NORMALPRIO + 1, conversionThreadMonitor, nullptr); + auto conversionThreadUPWAEnd = + reinterpret_cast(conversionThreadUPWA) + conversionThreadUPWASize; conversionThreadHandle = chThdCreateStatic( conversionThreadWA, sizeof(conversionThreadWA), HIGHPRIO, conversionThread, - reinterpret_cast(reinterpret_cast(conversionThreadUPWA) + - conversionThreadUPWASize)); + reinterpret_cast(conversionThreadUPWAEnd)); chThdCreateStatic( communicationThreadWA, sizeof(communicationThreadWA), NORMALPRIO, communicationThread, nullptr); - - chThdExit(0); - return 0; } THD_FUNCTION(communicationThread, arg) @@ -190,7 +204,7 @@ THD_FUNCTION(communicationThread, arg) // 'S' - Stop conversion. // 's' - Get latest block of conversion results. // 't' - Get latest block of conversion input. - // 'u' - Get user message. + // 'u' - Get user message. // 'W' - Start signal generator (siggen). // 'w' - Stop siggen. @@ -222,8 +236,22 @@ THD_FUNCTION(communicationThread, arg) if (EM.assert(USBSerial::read(&cmd[1], 2) == 2, Error::BadParamSize)) { unsigned int count = cmd[1] | (cmd[2] << 8); if (EM.assert(count <= MAX_SAMPLE_BUFFER_SIZE, Error::BadParam)) { - samplesSigGen.setSize(count); - USBSerial::read(samplesSigGen.bytedata(), samplesSigGen.bytesize()); + if (run_status == RunStatus::Idle) { + samplesSigGen.setSize(count * 2); + USBSerial::read( + reinterpret_cast(samplesSigGen.middata()), + samplesSigGen.bytesize() / 2); + } else if (run_status == RunStatus::Running) { + int more; + do { + chThdSleepMicroseconds(10); + more = DAC::sigGenWantsMore(); + } while (more == -1); + + USBSerial::read(reinterpret_cast( + more == 0 ? samplesSigGen.data() : samplesSigGen.middata()), + samplesSigGen.bytesize() / 2); + } } } break; @@ -275,7 +303,7 @@ THD_FUNCTION(communicationThread, arg) if (EM.assert(run_status == RunStatus::Idle, Error::NotIdle)) { run_status = RunStatus::Running; samplesOut.clear(); - ADC::start(samplesIn.data(), samplesIn.size(), signal_operate_measure); + ADC::start(samplesIn.data(), samplesIn.size(), signalOperateMeasure); DAC::start(0, samplesOut.data(), samplesOut.size()); } break; @@ -293,7 +321,7 @@ THD_FUNCTION(communicationThread, arg) if (EM.assert(run_status == RunStatus::Idle, Error::NotIdle)) { run_status = RunStatus::Running; samplesOut.clear(); - ADC::start(samplesIn.data(), samplesIn.size(), signal_operate); + ADC::start(samplesIn.data(), samplesIn.size(), signalOperate); DAC::start(0, samplesOut.data(), samplesOut.size()); } break; @@ -488,7 +516,7 @@ void conversion_unprivileged_main() } } -void mpu_setup() +void mpuSetup() { // Set up MPU for user algorithm #if defined(TARGET_PLATFORM_H7) @@ -561,7 +589,7 @@ void abortAlgorithmFromISR() } } -void signal_operate(adcsample_t *buffer, size_t) +void signalOperate(adcsample_t *buffer, size_t) { chSysLockFromISR(); @@ -582,7 +610,7 @@ void signal_operate(adcsample_t *buffer, size_t) } } -void signal_operate_measure(adcsample_t *buffer, [[maybe_unused]] size_t count) +void signalOperateMeasure(adcsample_t *buffer, [[maybe_unused]] size_t count) { chSysLockFromISR(); if (buffer == samplesIn.data()) { @@ -594,7 +622,7 @@ void signal_operate_measure(adcsample_t *buffer, [[maybe_unused]] size_t count) } chSysUnlockFromISR(); - ADC::setOperation(signal_operate); + ADC::setOperation(signalOperate); } extern "C" { @@ -654,7 +682,7 @@ void port_syscall(struct port_extctx *ctxp, uint32_t n) } break; case 3: - ctxp->r0 = ADC::readAlt(0); + ctxp->r0 = ADC::readAlt(ctxp->r0); break; case 4: { diff --git a/source/samplebuffer.cpp b/source/samplebuffer.cpp index 24cc424..1acf2f4 100644 --- a/source/samplebuffer.cpp +++ b/source/samplebuffer.cpp @@ -1,3 +1,14 @@ +/** + * @file samplebuffer.cpp + * @brief Manages ADC/DAC buffer data. + * + * Copyright (C) 2021 Clyne Sullivan + * + * Distributed under the GNU GPL v3 or later. You should have received a copy of + * the GNU General Public License along with this program. + * If not, see . + */ + #include "samplebuffer.hpp" SampleBuffer::SampleBuffer(Sample *buffer) : diff --git a/source/samplebuffer.hpp b/source/samplebuffer.hpp index 6d17d2a..d13023a 100644 --- a/source/samplebuffer.hpp +++ b/source/samplebuffer.hpp @@ -1,3 +1,14 @@ +/** + * @file samplebuffer.hpp + * @brief Manages ADC/DAC buffer data. + * + * Copyright (C) 2021 Clyne Sullivan + * + * Distributed under the GNU GPL v3 or later. You should have received a copy of + * the GNU General Public License along with this program. + * If not, see . + */ + #ifndef SAMPLEBUFFER_HPP_ #define SAMPLEBUFFER_HPP_ diff --git a/source/sclock.cpp b/source/sclock.cpp index 198c684..317b995 100644 --- a/source/sclock.cpp +++ b/source/sclock.cpp @@ -1,3 +1,14 @@ +/** + * @file sclock.cpp + * @brief Manages sampling rate clock speeds. + * + * Copyright (C) 2021 Clyne Sullivan + * + * Distributed under the GNU GPL v3 or later. You should have received a copy of + * the GNU General Public License along with this program. + * If not, see . + */ + #include "sclock.hpp" GPTDriver *SClock::m_timer = &GPTD6; diff --git a/source/sclock.hpp b/source/sclock.hpp index 960d9e3..d5b93df 100644 --- a/source/sclock.hpp +++ b/source/sclock.hpp @@ -1,3 +1,14 @@ +/** + * @file sclock.hpp + * @brief Manages sampling rate clock speeds. + * + * Copyright (C) 2021 Clyne Sullivan + * + * Distributed under the GNU GPL v3 or later. You should have received a copy of + * the GNU General Public License along with this program. + * If not, see . + */ + #ifndef SCLOCK_HPP_ #define SCLOCK_HPP_ diff --git a/source/usbserial.cpp b/source/usbserial.cpp index c24be2f..775a911 100644 --- a/source/usbserial.cpp +++ b/source/usbserial.cpp @@ -2,7 +2,7 @@ * @file usbserial.cpp * @brief Wrapper for ChibiOS's SerialUSBDriver. * - * Copyright (C) 2020 Clyne Sullivan + * Copyright (C) 2021 Clyne Sullivan * * Distributed under the GNU GPL v3 or later. You should have received a copy of * the GNU General Public License along with this program. @@ -32,7 +32,7 @@ bool USBSerial::isActive() { if (auto config = m_driver->config; config != nullptr) { if (auto usbp = config->usbp; usbp != nullptr) - return usbp->state == USB_ACTIVE; + return usbp->state == USB_ACTIVE && !ibqIsEmptyI(&m_driver->ibqueue); } return false; diff --git a/source/usbserial.hpp b/source/usbserial.hpp index 828fc56..58113c9 100644 --- a/source/usbserial.hpp +++ b/source/usbserial.hpp @@ -2,7 +2,7 @@ * @file usbserial.hpp * @brief Wrapper for ChibiOS's SerialUSBDriver. * - * Copyright (C) 2020 Clyne Sullivan + * Copyright (C) 2021 Clyne Sullivan * * Distributed under the GNU GPL v3 or later. You should have received a copy of * the GNU General Public License along with this program. From bb8b7b0227bcddaf2e5407084e136804190d4dab Mon Sep 17 00:00:00 2001 From: Clyne Sullivan Date: Mon, 14 Jun 2021 06:23:23 -0400 Subject: [PATCH 03/13] stick with wx3.0; Linux drawing broke again; timer fixes --- gui/Makefile | 2 +- gui/wxapp.hpp | 2 +- gui/wxmain.cpp | 46 ++++++++++++++++++++++------------- gui/wxmain_mrun.cpp | 7 ++++-- gui/wxmain_mrun_genupload.cpp | 20 +++++++-------- source/dac.cpp | 2 +- 6 files changed, 47 insertions(+), 32 deletions(-) diff --git a/gui/Makefile b/gui/Makefile index e06a740..e7e1a74 100644 --- a/gui/Makefile +++ b/gui/Makefile @@ -32,7 +32,7 @@ endif OFILES = $(patsubst %.cc, %.o, $(patsubst %.cpp, %.o, $(CXXFILES))) ifeq ($(UNAME), Linux) -LIBS = $(shell wx-config --libs) -lwx_gtk3u_stc-3.1 +LIBS = $(shell wx-config --libs) -lwx_gtk3u_stc-3.0 else LIBS = -lSetupAPI \ -LC:\wx\lib\gcc810_x64_dll -lwxbase31u -lwxmsw31u_core -lwxmsw31u_stc diff --git a/gui/wxapp.hpp b/gui/wxapp.hpp index 85bddc2..ef6a68c 100644 --- a/gui/wxapp.hpp +++ b/gui/wxapp.hpp @@ -21,7 +21,7 @@ class MainApp : public wxApp { public: virtual bool OnInit() final { - wxFont::AddPrivateFont("./Hack-Regular.ttf"); + //wxFont::AddPrivateFont("./Hack-Regular.ttf"); m_main_frame = new MainFrame; m_main_frame->Show(true); diff --git a/gui/wxmain.cpp b/gui/wxmain.cpp index 75eedb6..c526157 100644 --- a/gui/wxmain.cpp +++ b/gui/wxmain.cpp @@ -152,8 +152,9 @@ MainFrame::MainFrame() : Bind(wxEVT_TIMER, &MainFrame::onTimerRecord, this, Id::TimerRecord); Bind(wxEVT_TIMER, &MainFrame::onTimerWavClip, this, Id::TimerWavClip); Bind(wxEVT_CLOSE_WINDOW, &MainFrame::onCloseEvent, this, wxID_ANY); - m_compile_output-> - Bind(wxEVT_PAINT, &MainFrame::onPaint, this, Id::CompileOutput); +// m_compile_output-> +// Bind(wxEVT_PAINT, &MainFrame::onPaint, this, Id::CompileOutput); + Bind(wxEVT_PAINT, &MainFrame::onPaint, this, wxID_ANY); // Toolbar actions Bind(wxEVT_BUTTON, &MainFrame::onRunCompile, this, wxID_ANY, wxID_ANY, comp); @@ -234,7 +235,7 @@ void MainFrame::onTimerRecord(wxTimerEvent&) if (m_run_draw_samples->IsChecked()) { samples = m_device->continuous_read_input(); std::copy(samples.cbegin(), samples.cend(), m_device_samples_input); - m_compile_output->Refresh(); + /*m_compile_output->*/Refresh(); } } } @@ -253,42 +254,50 @@ void MainFrame::onTimerWavClip(wxTimerEvent&) void MainFrame::onPaint(wxPaintEvent&) { - if (!m_is_running || !m_run_draw_samples->IsChecked()) + if (!m_is_running || !m_run_draw_samples->IsChecked()) { + if (!m_compile_output->IsShown()) + m_compile_output->Show(); return; + } else if (m_compile_output->IsShown()) { + m_compile_output->Hide(); + } - const auto& dim = m_compile_output->GetSize(); + auto py = m_compile_output->GetScreenPosition().y - this->GetScreenPosition().y - 28; wxRect rect { - 0, 0, dim.GetWidth(), dim.GetHeight() + 0, py, + this->GetSize().GetWidth(), + this->GetSize().GetHeight() - py - 60 }; - wxBufferedPaintDC dc (m_compile_output); - dc.SetBrush(*wxBLACK_BRUSH); - dc.SetPen(*wxBLACK_PEN); - dc.DrawRectangle(rect); + auto *dc = new wxBufferedPaintDC(this); + dc->SetBrush(*wxBLACK_BRUSH); + dc->SetPen(*wxBLACK_PEN); + dc->DrawRectangle(rect); auto stoy = [&](stmdsp::adcsample_t s) { - return static_cast(rect.GetHeight()) - + return static_cast(py) + rect.GetHeight() - (static_cast(rect.GetHeight()) * s / 4095.f); }; auto scount = m_device->get_buffer_size(); float dx = static_cast(rect.GetWidth()) / scount; float x = 0; float lasty = stoy(2048); - dc.SetBrush(wxBrush(wxColour(0xFF, 0, 0, 0x80))); - dc.SetPen(wxPen(wxColour(0xFF, 0, 0, 0x80))); + dc->SetBrush(wxBrush(wxColour(0xFF, 0, 0, 0x80))); + dc->SetPen(wxPen(wxColour(0xFF, 0, 0, 0x80))); for (decltype(scount) i = 0; i < scount; i++) { auto y = stoy(m_device_samples[i]); - dc.DrawLine(x, lasty, x + dx, y); + dc->DrawLine(x, lasty, x + dx, y); x += dx, lasty = y; } x = 0; lasty = stoy(2048); - dc.SetBrush(wxBrush(wxColour(0, 0, 0xFF, 0x80))); - dc.SetPen(wxPen(wxColour(0, 0, 0xFF, 0x80))); + dc->SetBrush(wxBrush(wxColour(0, 0, 0xFF, 0x80))); + dc->SetPen(wxPen(wxColour(0, 0, 0xFF, 0x80))); for (decltype(scount) i = 0; i < scount; i++) { auto y = stoy(m_device_samples_input[i]); - dc.DrawLine(x, lasty, x + dx, y); + dc->DrawLine(x, lasty, x + dx, y); x += dx, lasty = y; } + delete dc; } void MainFrame::prepareEditor() @@ -452,6 +461,8 @@ void MainFrame::updateMenuOptions() m_menu_bar->Enable(MRunGenUpload, connected); m_menu_bar->Enable(MRunGenStart, connected); + m_menu_bar->Enable(MRunConnect, !m_is_running); + bool nrunning = connected && !m_is_running; m_menu_bar->Enable(MRunUpload, nrunning); m_menu_bar->Enable(MRunUnload, nrunning); @@ -459,6 +470,7 @@ void MainFrame::updateMenuOptions() m_menu_bar->Enable(MRunMeasure, nrunning); m_menu_bar->Enable(MRunDrawSamples, nrunning); m_menu_bar->Enable(MRunLogResults, nrunning); + m_menu_bar->Enable(MRunGenUpload, nrunning); m_rate_select->Enable(nrunning); } diff --git a/gui/wxmain_mrun.cpp b/gui/wxmain_mrun.cpp index e12d068..9fb307a 100644 --- a/gui/wxmain_mrun.cpp +++ b/gui/wxmain_mrun.cpp @@ -54,10 +54,13 @@ void MainFrame::onRunStart(wxCommandEvent& ce) * 1000.f * 0.5f; int reqSpeed = reqSpeedExact; - if (m_device->is_siggening() && m_wav_clip) + if (m_device->is_siggening() && m_wav_clip) { m_timer_wavclip->Start(reqSpeed); + // Cap refresh speed in case sample drawing runs too. + reqSpeed = std::max(reqSpeed, 500); + } if (m_conv_result_log || m_run_draw_samples->IsChecked()) - m_timer_record->Start(reqSpeed); + m_timer_record->Start(std::max(reqSpeed, 200)); m_device->continuous_start(); } diff --git a/gui/wxmain_mrun_genupload.cpp b/gui/wxmain_mrun_genupload.cpp index b720e3a..d1b82ef 100644 --- a/gui/wxmain_mrun_genupload.cpp +++ b/gui/wxmain_mrun_genupload.cpp @@ -1,5 +1,5 @@ #include "stmdsp.hpp" -#include "exprtk.hpp" +//#include "exprtk.hpp" #include #include @@ -7,20 +7,20 @@ std::vector siggen_formula_parse(const std::string& formula { double x = 0; - exprtk::symbol_table symbol_table; - symbol_table.add_variable("x", x); - symbol_table.add_constants(); + //exprtk::symbol_table symbol_table; + //symbol_table.add_variable("x", x); + //symbol_table.add_constants(); - exprtk::expression expression; - expression.register_symbol_table(symbol_table); + //exprtk::expression expression; + //expression.register_symbol_table(symbol_table); - exprtk::parser parser; - parser.compile(formulaString, expression); + //exprtk::parser parser; + //parser.compile(formulaString, expression); std::vector samples; for (x = 0; samples.size() < stmdsp::SAMPLES_MAX; x += 1) { - auto y = static_cast(expression.value()); - samples.push_back(y); + //auto y = static_cast(expression.value()); + samples.push_back(2048); } return samples; diff --git a/source/dac.cpp b/source/dac.cpp index 2772928..1ff8867 100644 --- a/source/dac.cpp +++ b/source/dac.cpp @@ -17,7 +17,7 @@ DACDriver *DAC::m_driver[2] = { }; const DACConfig DAC::m_config = { - .init = 0, + .init = 2048, .datamode = DAC_DHRM_12BIT_RIGHT, .cr = 0 }; From d24ed15843c328983f9ed20283f89624e8574b9f Mon Sep 17 00:00:00 2001 From: Clyne Sullivan Date: Mon, 14 Jun 2021 06:24:24 -0400 Subject: [PATCH 04/13] update gitignore --- .gitignore | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index d7fc7b4..30c963e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,9 @@ -**/.* -**/*.o -**/*.so +.* +*.o +*.so +*.exe +*.dll perf* build -eagle/*#* gui/stmdspgui doc/guide.odt -*.exe -*.dll From 123cc4c756cc8a22f66351ab65595c5a20e53e27 Mon Sep 17 00:00:00 2001 From: Clyne Sullivan Date: Sat, 31 Jul 2021 10:47:00 -0400 Subject: [PATCH 05/13] reorganized source, wip --- Makefile | 7 +- openocd.cfg | 2 +- source/board/board_h7.c | 21 + source/board/board_l4.c | 23 + source/board/l4/board.h | 4 + source/communication.cpp | 291 +++++++++++ source/communication.hpp | 29 ++ source/conversion.cpp | 206 ++++++++ source/conversion.hpp | 67 +++ source/{elf_format.hpp => elf.h} | 8 +- source/elf_load.hpp | 26 - source/{elf_load.cpp => elfload.cpp} | 20 +- source/elfload.hpp | 48 ++ source/error.cpp | 38 ++ source/error.hpp | 44 +- source/handlers.cpp | 138 ++++++ source/handlers.hpp | 31 ++ source/main.cpp | 712 +-------------------------- source/monitor.cpp | 80 +++ source/monitor.hpp | 29 ++ source/{ => periph}/adc.cpp | 6 +- source/{ => periph}/adc.hpp | 0 source/{ => periph}/cordic.cpp | 0 source/{ => periph}/cordic.hpp | 0 source/{ => periph}/dac.cpp | 0 source/{ => periph}/dac.hpp | 0 source/{ => periph}/usbcfg.c | 0 source/{ => periph}/usbcfg.h | 0 source/{ => periph}/usbserial.cpp | 0 source/{ => periph}/usbserial.hpp | 0 source/runstatus.hpp | 11 + source/samples.cpp | 35 ++ source/samples.hpp | 26 + 33 files changed, 1137 insertions(+), 765 deletions(-) create mode 100644 source/communication.cpp create mode 100644 source/communication.hpp create mode 100644 source/conversion.cpp create mode 100644 source/conversion.hpp rename source/{elf_format.hpp => elf.h} (94%) delete mode 100644 source/elf_load.hpp rename source/{elf_load.cpp => elfload.cpp} (79%) create mode 100644 source/elfload.hpp create mode 100644 source/error.cpp create mode 100644 source/handlers.cpp create mode 100644 source/handlers.hpp create mode 100644 source/monitor.cpp create mode 100644 source/monitor.hpp rename source/{ => periph}/adc.cpp (98%) rename source/{ => periph}/adc.hpp (100%) rename source/{ => periph}/cordic.cpp (100%) rename source/{ => periph}/cordic.hpp (100%) rename source/{ => periph}/dac.cpp (100%) rename source/{ => periph}/dac.hpp (100%) rename source/{ => periph}/usbcfg.c (100%) rename source/{ => periph}/usbcfg.h (100%) rename source/{ => periph}/usbserial.cpp (100%) rename source/{ => periph}/usbserial.hpp (100%) create mode 100644 source/runstatus.hpp create mode 100644 source/samples.cpp create mode 100644 source/samples.hpp diff --git a/Makefile b/Makefile index bec5309..e308e1e 100644 --- a/Makefile +++ b/Makefile @@ -128,8 +128,8 @@ include $(CHIBIOS)/os/rt/rt.mk include $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/port_v7m.mk # Auto-build files in ./source recursively. #include $(CHIBIOS)/tools/mk/autobuild.mk -ALLCSRC += $(wildcard source/*.c) -ALLCPPSRC += $(wildcard source/*.cpp) +ALLCSRC += $(wildcard source/*.c) $(wildcard source/periph/*.c) +ALLCPPSRC += $(wildcard source/*.cpp) $(wildcard source/periph/*.cpp) ALLASMSRC += $(wildcard source/*.s) # Other files (optional). #include $(CHIBIOS)/test/lib/test.mk @@ -158,7 +158,8 @@ ASMSRC = $(ALLASMSRC) ASMXSRC = $(ALLXASMSRC) # Inclusion directories. -INCDIR = $(CONFDIR) $(ALLINC) $(TESTINC) +INCDIR = $(CONFDIR) $(ALLINC) $(TESTINC) \ + source source/periph # Define C warning options here. CWARN = -Wall -Wextra -Wundef -Wstrict-prototypes -pedantic diff --git a/openocd.cfg b/openocd.cfg index 0599165..47e6c7d 100644 --- a/openocd.cfg +++ b/openocd.cfg @@ -1,3 +1,3 @@ source [find interface/stlink.cfg] -source [find target/stm32h7x.cfg] +source [find target/stm32l4x.cfg] diff --git a/source/board/board_h7.c b/source/board/board_h7.c index 2868726..74285cf 100644 --- a/source/board/board_h7.c +++ b/source/board/board_h7.c @@ -262,5 +262,26 @@ bool mmc_lld_is_write_protected(MMCDriver *mmcp) { * @note You can add your board-specific code here. */ void boardInit(void) { + // Enable the FPU (floating-point unit) + SCB->CPACR |= 0xF << 20; + // Setup the MPU (memory protection unit): + // Region 2: Data for algorithm thread + // Region 3: Code for algorithm thread + // Region 4: User algorithm code + mpuConfigureRegion(MPU_REGION_2, + 0x20000000, + MPU_RASR_ATTR_AP_RW_RW | MPU_RASR_ATTR_NON_CACHEABLE | + MPU_RASR_SIZE_64K | + MPU_RASR_ENABLE); + mpuConfigureRegion(MPU_REGION_3, + 0x0807F800, + MPU_RASR_ATTR_AP_RO_RO | MPU_RASR_ATTR_NON_CACHEABLE | + MPU_RASR_SIZE_2K | + MPU_RASR_ENABLE); + mpuConfigureRegion(MPU_REGION_4, + 0x00000000, + MPU_RASR_ATTR_AP_RW_RW | MPU_RASR_ATTR_NON_CACHEABLE | + MPU_RASR_SIZE_64K | + MPU_RASR_ENABLE); } diff --git a/source/board/board_l4.c b/source/board/board_l4.c index cd16e43..31d1d51 100644 --- a/source/board/board_l4.c +++ b/source/board/board_l4.c @@ -277,5 +277,28 @@ bool mmc_lld_is_write_protected(MMCDriver *mmcp) { * @note You can add your board-specific code here. */ void boardInit(void) { + palSetLineMode(LINE_LED_GREEN, PAL_MODE_OUTPUT_PUSHPULL); + palSetLineMode(LINE_LED_YELLOW, PAL_MODE_OUTPUT_PUSHPULL); + palSetLineMode(LINE_LED_RED, PAL_MODE_OUTPUT_PUSHPULL); + SCB->CPACR |= 0xF << 20; // Enable FPU + + // Region 2: Data for algorithm thread and ADC/DAC buffers + // Region 3: Code for algorithm thread + // Region 4: User algorithm code + mpuConfigureRegion(MPU_REGION_2, + 0x20008000, + MPU_RASR_ATTR_AP_RW_RW | MPU_RASR_ATTR_NON_CACHEABLE | + MPU_RASR_SIZE_128K | + MPU_RASR_ENABLE); + mpuConfigureRegion(MPU_REGION_3, + 0x0807F800, + MPU_RASR_ATTR_AP_RO_RO | MPU_RASR_ATTR_NON_CACHEABLE | + MPU_RASR_SIZE_2K | + MPU_RASR_ENABLE); + mpuConfigureRegion(MPU_REGION_4, + 0x10000000, + MPU_RASR_ATTR_AP_RW_RW | MPU_RASR_ATTR_NON_CACHEABLE | + MPU_RASR_SIZE_32K | + MPU_RASR_ENABLE); } diff --git a/source/board/l4/board.h b/source/board/l4/board.h index 8291664..e4dcf03 100644 --- a/source/board/l4/board.h +++ b/source/board/l4/board.h @@ -1502,4 +1502,8 @@ extern "C" { #endif #endif /* _FROM_ASM_ */ +#define LINE_LED_GREEN PAL_LINE(GPIOC_BASE, 10U) +#define LINE_LED_YELLOW PAL_LINE(GPIOC_BASE, 11U) +#define LINE_LED_RED PAL_LINE(GPIOC_BASE, 12U) + #endif /* BOARD_H */ diff --git a/source/communication.cpp b/source/communication.cpp new file mode 100644 index 0000000..5835aa5 --- /dev/null +++ b/source/communication.cpp @@ -0,0 +1,291 @@ +#include "communication.hpp" + +#include "ch.h" +#include "hal.h" + +#include "periph/adc.hpp" +#include "periph/dac.hpp" +#include "periph/usbserial.hpp" +#include "elfload.hpp" +#include "error.hpp" +#include "conversion.hpp" +#include "runstatus.hpp" +#include "samples.hpp" + +#include +#include + +__attribute__((section(".stacks"))) +std::array CommunicationManager::m_thread_stack = {}; + +void CommunicationManager::begin() +{ + chThdCreateStatic(m_thread_stack.data(), + m_thread_stack.size(), + NORMALPRIO, + threadComm, + nullptr); +} + +static void writeADCBuffer(unsigned char *); +static void setBufferSize(unsigned char *); +static void updateGenerator(unsigned char *); +static void loadAlgorithm(unsigned char *); +static void readStatus(unsigned char *); +static void startConversionMeasure(unsigned char *); +static void startConversion(unsigned char *); +static void stopConversion(unsigned char *); +static void startGenerator(unsigned char *); +static void readADCBuffer(unsigned char *); +static void readDACBuffer(unsigned char *); +static void unloadAlgorithm(unsigned char *); +static void readIdentifier(unsigned char *); +static void readExecTime(unsigned char *); +static void sampleRate(unsigned char *); +static void readConversionResults(unsigned char *); +static void readConversionInput(unsigned char *); +static void readMessage(unsigned char *); +static void stopGenerator(unsigned char *); + +static const std::array, 19> commandTable {{ + {'A', writeADCBuffer}, + {'B', setBufferSize}, + {'D', updateGenerator}, + {'E', loadAlgorithm}, + {'I', readStatus}, + {'M', startConversionMeasure}, + {'R', startConversion}, + {'S', stopConversion}, + {'W', startGenerator}, + {'a', readADCBuffer}, + {'d', readDACBuffer}, + {'e', unloadAlgorithm}, + {'i', readIdentifier}, + {'m', readExecTime}, + {'r', sampleRate}, + {'s', readConversionResults}, + {'t', readConversionInput}, + {'u', readMessage}, + {'w', stopGenerator} +}}; + +void CommunicationManager::threadComm(void *) +{ + while (1) { + if (USBSerial::isActive()) { + // Attempt to receive a command packet + if (unsigned char cmd[3]; USBSerial::read(&cmd[0], 1) > 0) { + // Packet received, first byte represents the desired command/action + auto func = std::find_if(commandTable.cbegin(), commandTable.cend(), + [&cmd](const auto& f) { return f.first == cmd[0]; }); + if (func != commandTable.cend()) + func->second(cmd); + } + } + + chThdSleepMicroseconds(100); + } +} + +void writeADCBuffer(unsigned char *) +{ + USBSerial::read(Samples::In.bytedata(), Samples::In.bytesize()); +} + +void setBufferSize(unsigned char *cmd) +{ + if (EM.assert(run_status == RunStatus::Idle, Error::NotIdle) && + EM.assert(USBSerial::read(&cmd[1], 2) == 2, Error::BadParamSize)) + { + // count is multiplied by two since this command receives size of buffer + // for each algorithm application. + unsigned int count = (cmd[1] | (cmd[2] << 8)) * 2; + if (EM.assert(count <= MAX_SAMPLE_BUFFER_SIZE, Error::BadParam)) { + Samples::In.setSize(count); + Samples::Out.setSize(count); + } + } +} + +void updateGenerator(unsigned char *cmd) +{ + if (EM.assert(USBSerial::read(&cmd[1], 2) == 2, Error::BadParamSize)) { + unsigned int count = cmd[1] | (cmd[2] << 8); + if (EM.assert(count <= MAX_SAMPLE_BUFFER_SIZE, Error::BadParam)) { + if (run_status == RunStatus::Idle) { + Samples::Generator.setSize(count); + USBSerial::read( + reinterpret_cast(Samples::Generator.data()), + Samples::Generator.bytesize()); + } else if (run_status == RunStatus::Running) { + int more; + do { + chThdSleepMicroseconds(10); + more = DAC::sigGenWantsMore(); + } while (more == -1); + + USBSerial::read(reinterpret_cast( + more == 0 ? Samples::Generator.data() : Samples::Generator.middata()), + Samples::Generator.bytesize() / 2); + } + } + } +} + +void loadAlgorithm(unsigned char *cmd) +{ + if (EM.assert(run_status == RunStatus::Idle, Error::NotIdle) && + EM.assert(USBSerial::read(&cmd[1], 2) == 2, Error::BadParamSize)) + { + // Only load the binary if it can fit in the memory reserved for it. + unsigned int size = cmd[1] | (cmd[2] << 8); + if (EM.assert(size < MAX_ELF_FILE_SIZE, Error::BadUserCodeSize)) { + USBSerial::read(ELFManager::fileBuffer(), size); + auto entry = ELFManager::loadFromInternalBuffer(); + EM.assert(entry != nullptr, Error::BadUserCodeLoad); + } + } +} + +void readStatus(unsigned char *) +{ + unsigned char buf[2] = { + static_cast(run_status), + static_cast(EM.pop()) + }; + + USBSerial::write(buf, sizeof(buf)); +} + +void startConversionMeasure(unsigned char *) +{ + if (EM.assert(run_status == RunStatus::Idle, Error::NotIdle)) { + run_status = RunStatus::Running; + ConversionManager::startMeasured(); + } +} + +void startConversion(unsigned char *) +{ + if (EM.assert(run_status == RunStatus::Idle, Error::NotIdle)) { + run_status = RunStatus::Running; + ConversionManager::start(); + } +} + +void stopConversion(unsigned char *) +{ + if (run_status == RunStatus::Running) { + ConversionManager::stop(); + run_status = RunStatus::Idle; + } +} + +void startGenerator(unsigned char *) +{ + DAC::start(1, Samples::Generator.data(), Samples::Generator.size()); +} + +void readADCBuffer(unsigned char *) +{ + USBSerial::write(Samples::In.bytedata(), Samples::In.bytesize()); +} + +void readDACBuffer(unsigned char *) +{ + + USBSerial::write(Samples::Out.bytedata(), Samples::Out.bytesize()); +} + +void unloadAlgorithm(unsigned char *) +{ + ELFManager::unload(); +} + +void readIdentifier(unsigned char *) +{ +#if defined(TARGET_PLATFORM_H7) + USBSerial::write(reinterpret_cast("stmdsph"), 7); +#else + USBSerial::write(reinterpret_cast("stmdspl"), 7); +#endif +} + +void readExecTime(unsigned char *) +{ + USBSerial::write(reinterpret_cast(&conversion_time_measurement.last), + sizeof(rtcnt_t)); +} + +void sampleRate(unsigned char *cmd) +{ + if (EM.assert(USBSerial::read(&cmd[1], 1) == 1, Error::BadParamSize)) { + if (cmd[1] == 0xFF) { + unsigned char r = SClock::getRate(); + USBSerial::write(&r, 1); + } else { + auto r = static_cast(cmd[1]); + SClock::setRate(r); + ADC::setRate(r); + } + } +} + +void readConversionResults(unsigned char *) +{ + if (auto samps = Samples::Out.modified(); samps != nullptr) { + unsigned char buf[2] = { + static_cast(Samples::Out.size() / 2 & 0xFF), + static_cast(((Samples::Out.size() / 2) >> 8) & 0xFF) + }; + USBSerial::write(buf, 2); + unsigned int total = Samples::Out.bytesize() / 2; + unsigned int offset = 0; + unsigned char unused; + while (total > 512) { + USBSerial::write(reinterpret_cast(samps) + offset, 512); + while (USBSerial::read(&unused, 1) == 0); + offset += 512; + total -= 512; + } + USBSerial::write(reinterpret_cast(samps) + offset, total); + while (USBSerial::read(&unused, 1) == 0); + } else { + USBSerial::write(reinterpret_cast("\0\0"), 2); + } +} + +void readConversionInput(unsigned char *) +{ + if (auto samps = Samples::In.modified(); samps != nullptr) { + unsigned char buf[2] = { + static_cast(Samples::In.size() / 2 & 0xFF), + static_cast(((Samples::In.size() / 2) >> 8) & 0xFF) + }; + USBSerial::write(buf, 2); + unsigned int total = Samples::In.bytesize() / 2; + unsigned int offset = 0; + unsigned char unused; + while (total > 512) { + USBSerial::write(reinterpret_cast(samps) + offset, 512); + while (USBSerial::read(&unused, 1) == 0); + offset += 512; + total -= 512; + } + USBSerial::write(reinterpret_cast(samps) + offset, total); + while (USBSerial::read(&unused, 1) == 0); + } else { + USBSerial::write(reinterpret_cast("\0\0"), 2); + } +} + +void readMessage(unsigned char *) +{ + //USBSerial::write(reinterpret_cast(userMessageBuffer), userMessageSize); +} + +void stopGenerator(unsigned char *) +{ + DAC::stop(1); +} + diff --git a/source/communication.hpp b/source/communication.hpp new file mode 100644 index 0000000..03220b8 --- /dev/null +++ b/source/communication.hpp @@ -0,0 +1,29 @@ +/** + * @file communication.hpp + * @brief Manages communication with the host computer. + * + * Copyright (C) 2021 Clyne Sullivan + * + * Distributed under the GNU GPL v3 or later. You should have received a copy of + * the GNU General Public License along with this program. + * If not, see . + */ + +#ifndef STMDSP_COMMUNICATION_HPP +#define STMDSP_COMMUNICATION_HPP + +#include + +class CommunicationManager +{ +public: + static void begin(); + +private: + static void threadComm(void *); + + static std::array m_thread_stack; +}; + +#endif // STMDSP_COMMUNICATION_HPP + diff --git a/source/conversion.cpp b/source/conversion.cpp new file mode 100644 index 0000000..27954be --- /dev/null +++ b/source/conversion.cpp @@ -0,0 +1,206 @@ +#include "conversion.hpp" + +#include "periph/adc.hpp" +#include "periph/dac.hpp" +#include "elfload.hpp" +#include "error.hpp" +#include "runstatus.hpp" +#include "samples.hpp" + +constexpr msg_t MSG_CONVFIRST = 1; +constexpr msg_t MSG_CONVSECOND = 2; +constexpr msg_t MSG_CONVFIRST_MEASURE = 3; +constexpr msg_t MSG_CONVSECOND_MEASURE = 4; + +constexpr auto MSG_FOR_FIRST = [](msg_t m) { return m & 1; }; +constexpr auto MSG_FOR_MEASURE = [](msg_t m) { return m > 2; }; + +time_measurement_t conversion_time_measurement; + +__attribute__((section(".convdata"))) +thread_t *ConversionManager::m_thread_monitor = nullptr; +thread_t *ConversionManager::m_thread_runner = nullptr; + +__attribute__((section(".stacks"))) +std::array ConversionManager::m_thread_monitor_stack = {}; +__attribute__((section(".stacks"))) +std::array ConversionManager::m_thread_runner_entry_stack = {}; +__attribute__((section(".convdata"))) +std::array ConversionManager::m_thread_runner_stack = {}; + +std::array ConversionManager::m_mailbox_buffer; +mailbox_t ConversionManager::m_mailbox = _MAILBOX_DATA(m_mailbox, m_mailbox_buffer.data(), m_mailbox_buffer.size()); + +void ConversionManager::begin() +{ + m_thread_monitor = chThdCreateStatic(m_thread_monitor_stack.data(), + m_thread_monitor_stack.size(), + NORMALPRIO + 1, + threadMonitor, + nullptr); + auto runner_stack_end = &m_thread_runner_stack[CONVERSION_THREAD_STACK_SIZE]; + m_thread_runner = chThdCreateStatic(m_thread_runner_entry_stack.data(), + m_thread_runner_entry_stack.size(), + HIGHPRIO, + threadRunnerEntry, + runner_stack_end); +} + +void ConversionManager::start() +{ + Samples::Out.clear(); + ADC::start(Samples::In.data(), Samples::In.size(), adcReadHandler); + DAC::start(0, Samples::Out.data(), Samples::Out.size()); +} + +void ConversionManager::startMeasured() +{ + Samples::Out.clear(); + ADC::start(Samples::In.data(), Samples::In.size(), adcReadHandlerMeasure); + DAC::start(0, Samples::Out.data(), Samples::Out.size()); +} + +void ConversionManager::stop() +{ + DAC::stop(0); + ADC::stop(); +} + +thread_t *ConversionManager::getMonitorHandle() +{ + return m_thread_monitor; +} + +void ConversionManager::abort() +{ + ELFManager::unload(); + EM.add(Error::ConversionAborted); + run_status = RunStatus::Recovering; + + // Confirm that the exception return thread is the algorithm... + uint32_t *psp; + asm("mrs %0, psp" : "=r" (psp)); + + bool isRunnerStack = + (uint32_t)psp >= reinterpret_cast(m_thread_runner_stack.data()) && + (uint32_t)psp <= reinterpret_cast(m_thread_runner_stack.data() + + m_thread_runner_stack.size()); + + if (isRunnerStack) + { + // If it is, we can force the algorithm to exit by "resetting" its thread. + // We do this by rebuilding the thread's stacked exception return. + auto newpsp = reinterpret_cast(m_thread_runner_stack.data() + + m_thread_runner_stack.size() - + 8 * sizeof(uint32_t)); + // Set the LR register to the thread's entry point. + newpsp[5] = reinterpret_cast(threadRunner); + // Overwrite the instruction we'll return to with "bx lr" (jump to address in LR). + newpsp[6] = psp[6]; + *reinterpret_cast(newpsp[6]) = 0x4770; // "bx lr" + // Keep PSR contents (bit set forces Thumb mode, just in case). + newpsp[7] = psp[7] | (1 << 24); + // Set the new stack pointer. + asm("msr psp, %0" :: "r" (newpsp)); + } +} + +void ConversionManager::threadMonitor(void *) +{ + while (1) { + msg_t message; + msg_t fetch = chMBFetchTimeout(&m_mailbox, &message, TIME_INFINITE); + if (fetch == MSG_OK) + chMsgSend(m_thread_runner, message); + } +} + +void ConversionManager::threadRunnerEntry(void *stack) +{ + ELFManager::unload(); + port_unprivileged_jump(reinterpret_cast(threadRunner), + reinterpret_cast(stack)); +} + +__attribute__((section(".convcode"))) +void ConversionManager::threadRunner(void *) +{ + while (1) { + // Sleep until we receive a mailbox message. + msg_t message; + asm("svc 0; mov %0, r0" : "=r" (message)); + + if (message != 0) { + auto samples = MSG_FOR_FIRST(message) ? Samples::In.data() + : Samples::In.middata(); + auto size = Samples::In.size() / 2; + + auto entry = ELFManager::loadedElf(); + if (entry) { + // Below, we remember the stack pointer just in case the + // loaded algorithm messes things up. + uint32_t sp; + + if (!MSG_FOR_MEASURE(message)) { + asm("mov %0, sp" : "=r" (sp)); + samples = entry(samples, size); + asm("mov sp, %0" :: "r" (sp)); + } else { + // Start execution timer: + asm("mov %0, sp; eor r0, r0; svc 2" : "=r" (sp)); + samples = entry(samples, size); + // Stop execution timer: + asm("mov r0, #1; svc 2; mov sp, %0" :: "r" (sp)); + } + } + + // Update the sample out buffer with the transformed samples. + if (samples != nullptr) { + if (MSG_FOR_FIRST(message)) + Samples::Out.modify(samples, size); + else + Samples::Out.midmodify(samples, size); + } + } + } +} + +void ConversionManager::adcReadHandler(adcsample_t *buffer, size_t) +{ + chSysLockFromISR(); + + // If previous request hasn't been handled, then we're going too slow. + // We'll need to abort. + if (chMBGetUsedCountI(&m_mailbox) > 1) { + chMBResetI(&m_mailbox); + chMBResumeX(&m_mailbox); + chSysUnlockFromISR(); + abort(); + } else { + // Mark the modified samples as 'fresh' or ready for manipulation. + if (buffer == Samples::In.data()) { + Samples::In.setModified(); + chMBPostI(&m_mailbox, MSG_CONVFIRST); + } else { + Samples::In.setMidmodified(); + chMBPostI(&m_mailbox, MSG_CONVSECOND); + } + chSysUnlockFromISR(); + } +} + +void ConversionManager::adcReadHandlerMeasure(adcsample_t *buffer, size_t) +{ + chSysLockFromISR(); + if (buffer == Samples::In.data()) { + Samples::In.setModified(); + chMBPostI(&m_mailbox, MSG_CONVFIRST_MEASURE); + } else { + Samples::In.setMidmodified(); + chMBPostI(&m_mailbox, MSG_CONVSECOND_MEASURE); + } + chSysUnlockFromISR(); + + ADC::setOperation(adcReadHandler); +} + diff --git a/source/conversion.hpp b/source/conversion.hpp new file mode 100644 index 0000000..ad949dc --- /dev/null +++ b/source/conversion.hpp @@ -0,0 +1,67 @@ +/** + * @file conversion.hpp + * @brief Manages algorithm application (converts input samples to output). + * + * Copyright (C) 2021 Clyne Sullivan + * + * Distributed under the GNU GPL v3 or later. You should have received a copy of + * the GNU General Public License along with this program. + * If not, see . + */ + +#ifndef STMDSP_CONVERSION_HPP +#define STMDSP_CONVERSION_HPP + +#include "ch.h" +#include "hal.h" + +#include + +constexpr unsigned int CONVERSION_THREAD_STACK_SIZE = +#if defined(TARGET_PLATFORM_H7) + 62 * 1024; +#else + 15 * 1024; +#endif + +class ConversionManager +{ +public: + static void begin(); + + // Begins sample conversion. + static void start(); + // Begins conversion with execution time measured. + static void startMeasured(); + // Stops conversion. + static void stop(); + + static thread_t *getMonitorHandle(); + + // Internal only: Aborts a running conversion. + static void abort(); + +private: + static void threadMonitor(void *); + static void threadRunnerEntry(void *stack); + + static void threadRunner(void *); + static void adcReadHandler(adcsample_t *buffer, size_t); + static void adcReadHandlerMeasure(adcsample_t *buffer, size_t); + + static thread_t *m_thread_monitor; + static thread_t *m_thread_runner; + + static std::array m_thread_monitor_stack; + static std::array m_thread_runner_entry_stack; + static std::array m_thread_runner_stack; + + static std::array m_mailbox_buffer; + static mailbox_t m_mailbox; +}; + +// Stores the measured execution time. +extern time_measurement_t conversion_time_measurement; + +#endif // STMDSP_CONVERSION_HPP + diff --git a/source/elf_format.hpp b/source/elf.h similarity index 94% rename from source/elf_format.hpp rename to source/elf.h index d4feb99..998356d 100644 --- a/source/elf_format.hpp +++ b/source/elf.h @@ -1,12 +1,12 @@ /** - * @file elf_format.cpp + * @file elf.h * @brief Defines ELF binary format info. * * Free to use, written by Clyne Sullivan. */ -#ifndef STMDSP_ELF_FORMAT_HPP_ -#define STMDSP_ELF_FORMAT_HPP_ +#ifndef STMDSP_ELF_HPP +#define STMDSP_ELF_HPP #include @@ -96,5 +96,5 @@ typedef struct { Elf32_Word p_align; } __attribute__((packed)) Elf32_Phdr; -#endif // STMDSP_ELF_FORMAT_HPP_ +#endif // STMDSP_ELF_HPP diff --git a/source/elf_load.hpp b/source/elf_load.hpp deleted file mode 100644 index ae7265b..0000000 --- a/source/elf_load.hpp +++ /dev/null @@ -1,26 +0,0 @@ -/** - * @file elf_load.hpp - * @brief Loads ELF binary data into memory for execution. - * - * Copyright (C) 2021 Clyne Sullivan - * - * Distributed under the GNU GPL v3 or later. You should have received a copy of - * the GNU General Public License along with this program. - * If not, see . - */ - -#ifndef ELF_LOAD_HPP_ -#define ELF_LOAD_HPP_ - -#include -#include - -namespace ELF -{ - using Entry = uint16_t *(*)(uint16_t *, size_t); - - Entry load(void *elf_data); -} - -#endif // ELF_LOAD_HPP_ - diff --git a/source/elf_load.cpp b/source/elfload.cpp similarity index 79% rename from source/elf_load.cpp rename to source/elfload.cpp index e161206..a430ad2 100644 --- a/source/elf_load.cpp +++ b/source/elfload.cpp @@ -1,5 +1,5 @@ /** - * @file elf_load.cpp + * @file elfload.cpp * @brief Loads ELF binary data into memory for execution. * * Copyright (C) 2021 Clyne Sullivan @@ -9,12 +9,16 @@ * If not, see . */ -#include "elf_load.hpp" -#include "elf_format.hpp" +#include "elfload.hpp" +#include "elf.h" #include #include +__attribute__((section(".convdata"))) +ELFManager::EntryFunc ELFManager::m_entry = nullptr; +std::array ELFManager::m_file_buffer = {}; + static const unsigned char elf_header[] = { '\177', 'E', 'L', 'F' }; template @@ -23,10 +27,10 @@ constexpr static auto ptr_from_offset(void *base, uint32_t offset) return reinterpret_cast(reinterpret_cast(base) + offset); } -namespace ELF { - -Entry load(void *elf_data) +ELFManager::EntryFunc ELFManager::loadFromInternalBuffer() { + auto elf_data = m_file_buffer.data(); + // Check the ELF's header signature auto ehdr = reinterpret_cast(elf_data); if (!std::equal(ehdr->e_ident, ehdr->e_ident + 4, elf_header)) @@ -54,8 +58,6 @@ Entry load(void *elf_data) } - return loaded ? reinterpret_cast(ehdr->e_entry) : nullptr; + return loaded ? reinterpret_cast(ehdr->e_entry) : nullptr; } -} // namespace ELF - diff --git a/source/elfload.hpp b/source/elfload.hpp new file mode 100644 index 0000000..ada35e5 --- /dev/null +++ b/source/elfload.hpp @@ -0,0 +1,48 @@ +/** + * @file elfload.hpp + * @brief Loads ELF binary data into memory for execution. + * + * Copyright (C) 2021 Clyne Sullivan + * + * Distributed under the GNU GPL v3 or later. You should have received a copy of + * the GNU General Public License along with this program. + * If not, see . + */ + +#ifndef ELF_LOAD_HPP_ +#define ELF_LOAD_HPP_ + +#include "samplebuffer.hpp" + +#include +#include + +constexpr unsigned int MAX_ELF_FILE_SIZE = 16 * 1024; + +class ELFManager +{ +public: + using EntryFunc = Sample *(*)(Sample *, size_t); + + static EntryFunc loadFromInternalBuffer(); + + static EntryFunc loadedElf() { + return m_entry; + } + + static unsigned char *fileBuffer() { + return m_file_buffer.data(); + } + + static void unload() { + m_entry = nullptr; + } + +private: + static EntryFunc m_entry; + + static std::array m_file_buffer; +}; + +#endif // ELF_LOAD_HPP_ + diff --git a/source/error.cpp b/source/error.cpp new file mode 100644 index 0000000..9f2e98f --- /dev/null +++ b/source/error.cpp @@ -0,0 +1,38 @@ +/** + * @file error.cpp + * @brief Tracks and reports non-critical errors. + * + * Copyright (C) 2021 Clyne Sullivan + * + * Distributed under the GNU GPL v3 or later. You should have received a copy of + * the GNU General Public License along with this program. + * If not, see . + */ + +#include "error.hpp" + +ErrorManager EM; + +void ErrorManager::add(Error error) +{ + if (m_index < m_queue.size()) + m_queue[m_index++] = error; +} + +bool ErrorManager::assert(bool condition, Error error) +{ + if (!condition) + add(error); + return condition; +} + +bool ErrorManager::hasError() +{ + return m_index > 0; +} + +Error ErrorManager::pop() +{ + return m_index == 0 ? Error::None : m_queue[--m_index]; +} + diff --git a/source/error.hpp b/source/error.hpp index 6911792..9bbbe2c 100644 --- a/source/error.hpp +++ b/source/error.hpp @@ -1,6 +1,18 @@ -#include +/** + * @file error.hpp + * @brief Tracks and reports non-critical errors. + * + * Copyright (C) 2021 Clyne Sullivan + * + * Distributed under the GNU GPL v3 or later. You should have received a copy of + * the GNU General Public License along with this program. + * If not, see . + */ + +#ifndef STMDSP_ERROR_HPP +#define STMDSP_ERROR_HPP -constexpr unsigned int MAX_ERROR_QUEUE_SIZE = 8; +#include enum class Error : char { @@ -15,28 +27,20 @@ enum class Error : char class ErrorManager { -public: - void add(Error error) { - if (m_index < m_queue.size()) - m_queue[m_index++] = error; - } - - bool assert(bool condition, Error error) { - if (!condition) - add(error); - return condition; - } + constexpr static unsigned int MAX_ERROR_QUEUE_SIZE = 8; - bool hasError() { - return m_index > 0; - } - - Error pop() { - return m_index == 0 ? Error::None : m_queue[--m_index]; - } +public: + void add(Error error); + bool assert(bool condition, Error error); + bool hasError(); + Error pop(); private: std::array m_queue; unsigned int m_index = 0; }; +extern ErrorManager EM; + +#endif // STMDSP_ERROR_HPP + diff --git a/source/handlers.cpp b/source/handlers.cpp new file mode 100644 index 0000000..4b0e3eb --- /dev/null +++ b/source/handlers.cpp @@ -0,0 +1,138 @@ +#include "handlers.hpp" + +#include "adc.hpp" +#include "conversion.hpp" +#include "cordic.hpp" +#include "runstatus.hpp" + +extern "C" { + +__attribute__((naked)) +void port_syscall(struct port_extctx *ctxp, uint32_t n) +{ + switch (n) { + + // Sleeps the current thread until a message is received. + // Used the algorithm runner to wait for new data. + case 0: + { + chSysLock(); + chMsgWaitS(); + auto monitor = ConversionManager::getMonitorHandle(); + auto msg = chMsgGet(monitor); + chMsgReleaseS(monitor, MSG_OK); + chSysUnlock(); + ctxp->r0 = msg; + } + break; + + // Provides access to advanced math functions. + // A service call like this is required for some hardware targets that + // provide hardware-accelerated math computations (e.g. CORDIC). + case 1: + { + using mathcall = void (*)(); + static mathcall funcs[3] = { + reinterpret_cast(cordic::sin), + reinterpret_cast(cordic::cos), + reinterpret_cast(cordic::tan), + }; +#if defined(PLATFORM_H7) + asm("vmov.f64 d0, %0, %1" :: "r" (ctxp->r1), "r" (ctxp->r2)); + if (ctxp->r0 < 3) { + funcs[ctxp->r0](); + asm("vmov.f64 %0, %1, d0" : "=r" (ctxp->r1), "=r" (ctxp->r2)); + } else { + asm("eor r0, r0; vmov.f64 d0, r0, r0"); + } +#else + asm("vmov.f32 s0, %0" :: "r" (ctxp->r1)); + if (ctxp->r0 < 3) { + funcs[ctxp->r0](); + asm("vmov.f32 %0, s0" : "=r" (ctxp->r1)); + } else { + asm("eor r0, r0; vmov.f32 s0, r0"); + } +#endif + } + break; + + // Starts or stops precise cycle time measurement. + // Used to measure algorithm execution time. + case 2: + if (ctxp->r0 == 0) { + chTMStartMeasurementX(&conversion_time_measurement); + } else { + chTMStopMeasurementX(&conversion_time_measurement); + // Subtract measurement overhead from the result. + // Running an empty algorithm ("bx lr") takes 196 cycles as of 2/4/21. + // Only measures algorithm code time (loading args/storing result takes 9 cycles). + constexpr rtcnt_t measurement_overhead = 196 - 1; + if (conversion_time_measurement.last > measurement_overhead) + conversion_time_measurement.last -= measurement_overhead; + } + break; + + // Reads one of the analog inputs made available for algorithm run-time input. + case 3: + ctxp->r0 = ADC::readAlt(ctxp->r0); + break; + + //case 4: + // { + // const char *str = reinterpret_cast(ctxp->r0); + // auto src = str; + // auto dst = userMessageBuffer; + // while (*src) + // *dst++ = *src++; + // *dst = '\0'; + // userMessageSize = src - str; + // } + // break; + default: + while (1); + break; + } + + asm("svc 0"); + while (1); +} + +__attribute__((naked)) +void MemManage_Handler() +{ + // 1. Get the stack pointer. + uint32_t lr; + asm("mov %0, lr" : "=r" (lr)); + + // 2. Recover from the fault. + ConversionManager::abort(); + + // 3. Return. + asm("mov lr, %0; bx lr" :: "r" (lr)); +} + +__attribute__((naked)) +void HardFault_Handler() +{ + // Get the stack pointer. + //uint32_t *stack; + uint32_t lr; + asm("mov %0, lr" : "=r" (lr)); + /*asm("\ + tst lr, #4; \ + ite eq; \ + mrseq %0, msp; \ + mrsne %0, psp; \ + mov %1, lr; \ + " : "=r" (stack), "=r" (lr));*/ + + // If coming from the algorithm, attempt to recover; otherwise, give up. + if (run_status != RunStatus::Running && (lr & 4) != 0) + MemManage_Handler(); + + while (1); +} + +} // extern "C" + diff --git a/source/handlers.hpp b/source/handlers.hpp new file mode 100644 index 0000000..fd7e10c --- /dev/null +++ b/source/handlers.hpp @@ -0,0 +1,31 @@ +/** + * @file handlers.hpp + * @brief Interrupt service routine handlers. + * + * Copyright (C) 2021 Clyne Sullivan + * + * Distributed under the GNU GPL v3 or later. You should have received a copy of + * the GNU General Public License along with this program. + * If not, see . + */ + +#ifndef STMDSP_HANDLERS_HPP +#define STMDSP_HANDLERS_HPP + +#include "ch.h" + +extern "C" { + +__attribute__((naked)) +void port_syscall(struct port_extctx *ctxp, uint32_t n); + +__attribute__((naked)) +void MemManage_Handler(); + +__attribute__((naked)) +void HardFault_Handler(); + +} + +#endif // STMDSP_HANDLERS_HPP + diff --git a/source/main.cpp b/source/main.cpp index e9c33ef..9a22a73 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -12,90 +12,24 @@ #include "ch.h" #include "hal.h" -static_assert(sizeof(adcsample_t) == sizeof(uint16_t)); -static_assert(sizeof(dacsample_t) == sizeof(uint16_t)); - #include "adc.hpp" #include "cordic.hpp" #include "dac.hpp" -#include "elf_load.hpp" #include "error.hpp" -#include "samplebuffer.hpp" #include "sclock.hpp" #include "usbserial.hpp" -#include - -// Pin definitions -// -#if defined(TARGET_PLATFORM_L4) -constexpr auto LINE_LED_GREEN = PAL_LINE(GPIOC_BASE, 10U); -constexpr auto LINE_LED_YELLOW = PAL_LINE(GPIOC_BASE, 11U); -constexpr auto LINE_LED_RED = PAL_LINE(GPIOC_BASE, 12U); -#endif - -// Run status -// -enum class RunStatus : char -{ - Idle = '1', - Running, - Recovering -}; -static RunStatus run_status = RunStatus::Idle; - -// Conversion threads messaging -// -#define MSG_CONVFIRST (1) -#define MSG_CONVSECOND (2) -#define MSG_CONVFIRST_MEASURE (3) -#define MSG_CONVSECOND_MEASURE (4) - -#define MSG_FOR_FIRST(m) (m & 1) -#define MSG_FOR_MEASURE(m) (m > 2) - -static msg_t conversionMBBuffer[2]; -static MAILBOX_DECL(conversionMB, conversionMBBuffer, 2); - -// Sample input and output buffers -// -#if defined(TARGET_PLATFORM_H7) -__attribute__((section(".convdata"))) -static SampleBuffer samplesIn (reinterpret_cast(0x38000000)); // 16k -__attribute__((section(".convdata"))) -static SampleBuffer samplesOut (reinterpret_cast(0x30004000)); // 16k -static SampleBuffer samplesSigGen (reinterpret_cast(0x30000000)); // 16k -#else -__attribute__((section(".convdata"))) -static SampleBuffer samplesIn (reinterpret_cast(0x20008000)); // 16k -__attribute__((section(".convdata"))) -static SampleBuffer samplesOut (reinterpret_cast(0x2000C000)); // 16k -static SampleBuffer samplesSigGen (reinterpret_cast(0x20010000)); // 16k -#endif - -// Algorithm binary storage -// -constexpr unsigned int MAX_ELF_FILE_SIZE = 16 * 1024; -static unsigned char elf_file_store[MAX_ELF_FILE_SIZE]; -__attribute__((section(".convdata"))) -static ELF::Entry elf_entry = nullptr; +#include "runstatus.hpp" +RunStatus run_status = RunStatus::Idle; // Other variables // -static ErrorManager EM; -static time_measurement_t conversion_time_measurement; -static char userMessageBuffer[128]; -static unsigned char userMessageSize = 0; +//static char userMessageBuffer[128]; +//static unsigned char userMessageSize = 0; -// Functions -// -__attribute__((section(".convcode"))) -static void conversion_unprivileged_main(); -static void startThreads(); -static void mpuSetup(); -static void abortAlgorithmFromISR(); -static void signalOperate(adcsample_t *buffer, size_t count); -static void signalOperateMeasure(adcsample_t *buffer, size_t count); +#include "conversion.hpp" +#include "communication.hpp" +#include "monitor.hpp" int main() { @@ -103,15 +37,7 @@ int main() halInit(); chSysInit(); - SCB->CPACR |= 0xF << 20; // Enable FPU - mpuSetup(); - -#if defined(TARGET_PLATFORM_L4) - palSetLineMode(LINE_LED_GREEN, PAL_MODE_OUTPUT_PUSHPULL); - palSetLineMode(LINE_LED_YELLOW, PAL_MODE_OUTPUT_PUSHPULL); - palSetLineMode(LINE_LED_RED, PAL_MODE_OUTPUT_PUSHPULL); -#endif - + // Init peripherials ADC::begin(); DAC::begin(); SClock::begin(); @@ -121,624 +47,12 @@ int main() SClock::setRate(SClock::Rate::R32K); ADC::setRate(SClock::Rate::R32K); - startThreads(); + // Start our threads. + ConversionManager::begin(); + CommunicationManager::begin(); + Monitor::begin(); + chThdExit(0); return 0; } -static THD_FUNCTION(monitorThread, arg); // Runs status LEDs and allows debug halt. -static THD_FUNCTION(conversionThreadMonitor, arg); // Monitors and manages algo. thread. -static THD_FUNCTION(conversionThread, arg); // Algorithm thread (unprivileged). -static THD_FUNCTION(communicationThread, arg); // Manages USB communications. - -// Need to hold some thread handles for mailbox usage. -static thread_t *conversionThreadHandle = nullptr; -__attribute__((section(".convdata"))) -static thread_t *conversionThreadMonitorHandle = nullptr; - -// The more stack for the algorithm, the merrier. -constexpr unsigned int conversionThreadUPWASize = -#if defined(TARGET_PLATFORM_H7) - 62 * 1024; -#else - 15 * 1024; -#endif - -__attribute__((section(".stacks"))) -static THD_WORKING_AREA(monitorThreadWA, 256); -__attribute__((section(".stacks"))) -static THD_WORKING_AREA(conversionThreadMonitorWA, 1024); -__attribute__((section(".stacks"))) -static THD_WORKING_AREA(conversionThreadWA, 128); // For entering unprivileged mode. -__attribute__((section(".convdata"))) -static THD_WORKING_AREA(conversionThreadUPWA, conversionThreadUPWASize); -__attribute__((section(".stacks"))) -static THD_WORKING_AREA(communicationThreadWA, 4096); - -void startThreads() -{ - chThdCreateStatic( - monitorThreadWA, sizeof(monitorThreadWA), - LOWPRIO, - monitorThread, nullptr); - conversionThreadMonitorHandle = chThdCreateStatic( - conversionThreadMonitorWA, sizeof(conversionThreadMonitorWA), - NORMALPRIO + 1, - conversionThreadMonitor, nullptr); - auto conversionThreadUPWAEnd = - reinterpret_cast(conversionThreadUPWA) + conversionThreadUPWASize; - conversionThreadHandle = chThdCreateStatic( - conversionThreadWA, sizeof(conversionThreadWA), - HIGHPRIO, - conversionThread, - reinterpret_cast(conversionThreadUPWAEnd)); - chThdCreateStatic( - communicationThreadWA, sizeof(communicationThreadWA), - NORMALPRIO, - communicationThread, nullptr); -} - -THD_FUNCTION(communicationThread, arg) -{ - (void)arg; - while (1) { - if (USBSerial::isActive()) { - // Attempt to receive a command packet - if (unsigned char cmd[3]; USBSerial::read(&cmd[0], 1) > 0) { - // Packet received, first byte represents the desired command/action - switch (cmd[0]) { - - // 'a' - Read contents of ADC buffer. - // 'A' - Write contents of ADC buffer. - // 'B' - Set ADC/DAC buffer size. - // 'd' - Read contents of DAC buffer. - // 'D' - Set siggen size and write to its buffer. - // 'E' - Load algorithm binary. - // 'e' - Unload algorithm. - // 'i' - Read "stmdsp" identifier string. - // 'I' - Read status information. - // 'M' - Begin conversion, measure algorithm execution time. - // 'm' - Read last algorithm execution time. - // 'R' - Begin conversion. - // 'r' - Read or write sample rate. - // 'S' - Stop conversion. - // 's' - Get latest block of conversion results. - // 't' - Get latest block of conversion input. - // 'u' - Get user message. - // 'W' - Start signal generator (siggen). - // 'w' - Stop siggen. - - case 'a': - USBSerial::write(samplesIn.bytedata(), samplesIn.bytesize()); - break; - case 'A': - USBSerial::read(samplesIn.bytedata(), samplesIn.bytesize()); - break; - - case 'B': - if (EM.assert(run_status == RunStatus::Idle, Error::NotIdle) && - EM.assert(USBSerial::read(&cmd[1], 2) == 2, Error::BadParamSize)) - { - // count is multiplied by two since this command receives size of buffer - // for each algorithm application. - unsigned int count = (cmd[1] | (cmd[2] << 8)) * 2; - if (EM.assert(count <= MAX_SAMPLE_BUFFER_SIZE, Error::BadParam)) { - samplesIn.setSize(count); - samplesOut.setSize(count); - } - } - break; - - case 'd': - USBSerial::write(samplesOut.bytedata(), samplesOut.bytesize()); - break; - case 'D': - if (EM.assert(USBSerial::read(&cmd[1], 2) == 2, Error::BadParamSize)) { - unsigned int count = cmd[1] | (cmd[2] << 8); - if (EM.assert(count <= MAX_SAMPLE_BUFFER_SIZE, Error::BadParam)) { - if (run_status == RunStatus::Idle) { - samplesSigGen.setSize(count * 2); - USBSerial::read( - reinterpret_cast(samplesSigGen.middata()), - samplesSigGen.bytesize() / 2); - } else if (run_status == RunStatus::Running) { - int more; - do { - chThdSleepMicroseconds(10); - more = DAC::sigGenWantsMore(); - } while (more == -1); - - USBSerial::read(reinterpret_cast( - more == 0 ? samplesSigGen.data() : samplesSigGen.middata()), - samplesSigGen.bytesize() / 2); - } - } - } - break; - - // 'E' - Reads in and loads the compiled conversion code binary from USB. - case 'E': - if (EM.assert(run_status == RunStatus::Idle, Error::NotIdle) && - EM.assert(USBSerial::read(&cmd[1], 2) == 2, Error::BadParamSize)) - { - // Only load the binary if it can fit in the memory reserved for it. - unsigned int size = cmd[1] | (cmd[2] << 8); - if (EM.assert(size < sizeof(elf_file_store), Error::BadUserCodeSize)) { - USBSerial::read(elf_file_store, size); - elf_entry = ELF::load(elf_file_store); - - EM.assert(elf_entry != nullptr, Error::BadUserCodeLoad); - } - } - break; - - // 'e' - Unloads the currently loaded conversion code - case 'e': - elf_entry = nullptr; - break; - - // 'i' - Sends an identifying string to confirm that this is the stmdsp device. - case 'i': -#if defined(TARGET_PLATFORM_H7) - USBSerial::write(reinterpret_cast("stmdsph"), 7); -#else - USBSerial::write(reinterpret_cast("stmdspl"), 7); -#endif - break; - - // 'I' - Sends the current run status. - case 'I': - { - unsigned char buf[2] = { - static_cast(run_status), - static_cast(EM.pop()) - }; - USBSerial::write(buf, sizeof(buf)); - } - break; - - // 'M' - Begins continuous sampling, but measures the execution time of the first - // sample processing. This duration can be later read through 'm'. - case 'M': - if (EM.assert(run_status == RunStatus::Idle, Error::NotIdle)) { - run_status = RunStatus::Running; - samplesOut.clear(); - ADC::start(samplesIn.data(), samplesIn.size(), signalOperateMeasure); - DAC::start(0, samplesOut.data(), samplesOut.size()); - } - break; - - // 'm' - Returns the last measured sample processing time, presumably in processor - // ticks. - case 'm': - USBSerial::write(reinterpret_cast(&conversion_time_measurement.last), - sizeof(rtcnt_t)); - break; - - // 'R' - Begin continuous sampling/conversion of the ADC. Samples will go through - // the conversion code, and will be sent out over the DAC. - case 'R': - if (EM.assert(run_status == RunStatus::Idle, Error::NotIdle)) { - run_status = RunStatus::Running; - samplesOut.clear(); - ADC::start(samplesIn.data(), samplesIn.size(), signalOperate); - DAC::start(0, samplesOut.data(), samplesOut.size()); - } - break; - - case 'r': - if (EM.assert(USBSerial::read(&cmd[1], 1) == 1, Error::BadParamSize)) { - if (cmd[1] == 0xFF) { - unsigned char r = SClock::getRate(); - USBSerial::write(&r, 1); - } else { - auto r = static_cast(cmd[1]); - SClock::setRate(r); - ADC::setRate(r); - } - } - break; - - // 'S' - Stops the continuous sampling/conversion. - case 'S': - if (run_status == RunStatus::Running) { - DAC::stop(0); - ADC::stop(); - run_status = RunStatus::Idle; - } - break; - - case 's': - if (auto samps = samplesOut.modified(); samps != nullptr) { - unsigned char buf[2] = { - static_cast(samplesOut.size() / 2 & 0xFF), - static_cast(((samplesOut.size() / 2) >> 8) & 0xFF) - }; - USBSerial::write(buf, 2); - unsigned int total = samplesOut.bytesize() / 2; - unsigned int offset = 0; - unsigned char unused; - while (total > 512) { - USBSerial::write(reinterpret_cast(samps) + offset, 512); - while (USBSerial::read(&unused, 1) == 0); - offset += 512; - total -= 512; - } - USBSerial::write(reinterpret_cast(samps) + offset, total); - while (USBSerial::read(&unused, 1) == 0); - } else { - USBSerial::write(reinterpret_cast("\0\0"), 2); - } - break; - case 't': - if (auto samps = samplesIn.modified(); samps != nullptr) { - unsigned char buf[2] = { - static_cast(samplesIn.size() / 2 & 0xFF), - static_cast(((samplesIn.size() / 2) >> 8) & 0xFF) - }; - USBSerial::write(buf, 2); - unsigned int total = samplesIn.bytesize() / 2; - unsigned int offset = 0; - unsigned char unused; - while (total > 512) { - USBSerial::write(reinterpret_cast(samps) + offset, 512); - while (USBSerial::read(&unused, 1) == 0); - offset += 512; - total -= 512; - } - USBSerial::write(reinterpret_cast(samps) + offset, total); - while (USBSerial::read(&unused, 1) == 0); - } else { - USBSerial::write(reinterpret_cast("\0\0"), 2); - } - break; - - case 'u': - USBSerial::write(reinterpret_cast(userMessageBuffer), userMessageSize); - break; - - case 'W': - DAC::start(1, samplesSigGen.data(), samplesSigGen.size()); - break; - case 'w': - DAC::stop(1); - break; - - default: - break; - } - } - } - - chThdSleepMicroseconds(100); - } -} - -THD_FUNCTION(conversionThreadMonitor, arg) -{ - (void)arg; - while (1) { - msg_t message; - if (chMBFetchTimeout(&conversionMB, &message, TIME_INFINITE) == MSG_OK) - chMsgSend(conversionThreadHandle, message); - } -} - -THD_FUNCTION(conversionThread, stack) -{ - elf_entry = nullptr; - port_unprivileged_jump(reinterpret_cast(conversion_unprivileged_main), - reinterpret_cast(stack)); -} - -THD_FUNCTION(monitorThread, arg) -{ - (void)arg; - - palSetLineMode(LINE_BUTTON, PAL_MODE_INPUT_PULLUP); - auto readButton = [] { -#if defined(TARGET_PLATFORM_L4) - return !palReadLine(LINE_BUTTON); -#else - return palReadLine(LINE_BUTTON); -#endif - }; - - palClearLine(LINE_LED_RED); - palClearLine(LINE_LED_YELLOW); - - while (1) { - bool isidle = run_status == RunStatus::Idle; - auto led = isidle ? LINE_LED_GREEN : LINE_LED_YELLOW; - auto delay = isidle ? 500 : 250; - - palSetLine(led); - chThdSleepMilliseconds(delay); - palClearLine(led); - chThdSleepMilliseconds(delay); - - if (run_status == RunStatus::Idle && readButton()) { - palSetLine(LINE_LED_RED); - palSetLine(LINE_LED_YELLOW); - chSysLock(); - while (readButton()) - asm("nop"); - while (!readButton()) - asm("nop"); - chSysUnlock(); - palClearLine(LINE_LED_RED); - palClearLine(LINE_LED_YELLOW); - chThdSleepMilliseconds(500); - } - - static bool erroron = false; - if (auto err = EM.hasError(); err ^ erroron) { - erroron = err; - if (err) - palSetLine(LINE_LED_RED); - else - palClearLine(LINE_LED_RED); - } - } -} - -void conversion_unprivileged_main() -{ - while (1) { - msg_t message; - asm("svc 0; mov %0, r0" : "=r" (message)); // sleep until next message - if (message != 0) { - auto samples = MSG_FOR_FIRST(message) ? samplesIn.data() : samplesIn.middata(); - auto size = samplesIn.size() / 2; - - if (elf_entry) { - if (!MSG_FOR_MEASURE(message)) { - // Remember the stack pointer in case the algorithm messes things up. - uint32_t sp; - asm("mov %0, sp" : "=r" (sp)); - samples = elf_entry(samples, size); - asm("mov sp, %0" :: "r" (sp)); - } else { - uint32_t sp; - asm("mov %0, sp; eor r0, r0; svc 2" : "=r" (sp)); // start measurement - samples = elf_entry(samples, size); - asm("mov r0, #1; svc 2; mov sp, %0" :: "r" (sp)); // stop measurement - } - } - - if (samples != nullptr) { - if (MSG_FOR_FIRST(message)) - samplesOut.modify(samples, size); - else - samplesOut.midmodify(samples, size); - } - } - } -} - -void mpuSetup() -{ - // Set up MPU for user algorithm -#if defined(TARGET_PLATFORM_H7) - // Region 2: Data for algorithm thread - // Region 3: Code for algorithm thread - // Region 4: User algorithm code - mpuConfigureRegion(MPU_REGION_2, - 0x20000000, - MPU_RASR_ATTR_AP_RW_RW | MPU_RASR_ATTR_NON_CACHEABLE | - MPU_RASR_SIZE_64K | - MPU_RASR_ENABLE); - mpuConfigureRegion(MPU_REGION_3, - 0x0807F800, - MPU_RASR_ATTR_AP_RO_RO | MPU_RASR_ATTR_NON_CACHEABLE | - MPU_RASR_SIZE_2K | - MPU_RASR_ENABLE); - mpuConfigureRegion(MPU_REGION_4, - 0x00000000, - MPU_RASR_ATTR_AP_RW_RW | MPU_RASR_ATTR_NON_CACHEABLE | - MPU_RASR_SIZE_64K | - MPU_RASR_ENABLE); -#else - // Region 2: Data for algorithm thread and ADC/DAC buffers - // Region 3: Code for algorithm thread - // Region 4: User algorithm code - mpuConfigureRegion(MPU_REGION_2, - 0x20008000, - MPU_RASR_ATTR_AP_RW_RW | MPU_RASR_ATTR_NON_CACHEABLE | - MPU_RASR_SIZE_128K| - MPU_RASR_ENABLE); - mpuConfigureRegion(MPU_REGION_3, - 0x0807F800, - MPU_RASR_ATTR_AP_RO_RO | MPU_RASR_ATTR_NON_CACHEABLE | - MPU_RASR_SIZE_2K | - MPU_RASR_ENABLE); - mpuConfigureRegion(MPU_REGION_4, - 0x10000000, - MPU_RASR_ATTR_AP_RW_RW | MPU_RASR_ATTR_NON_CACHEABLE | - MPU_RASR_SIZE_32K | - MPU_RASR_ENABLE); -#endif -} - -void abortAlgorithmFromISR() -{ - elf_entry = nullptr; - EM.add(Error::ConversionAborted); - run_status = RunStatus::Recovering; - - // Confirm that the exception return thread is the algorithm... - uint32_t *psp; - asm("mrs %0, psp" : "=r" (psp)); - if ((uint32_t)psp >= (uint32_t)conversionThreadUPWA && - (uint32_t)psp <= (uint32_t)conversionThreadUPWA + conversionThreadUPWASize) - { - // If it is, we can force the algorithm to exit by "resetting" its thread. - // We do this by rebuilding the thread's stacked exception return. - uint32_t *newpsp = reinterpret_cast( - (char *)conversionThreadUPWA + - conversionThreadUPWASize - 8 * sizeof(uint32_t)); - // Set the LR register to the thread's entry point. - newpsp[5] = reinterpret_cast(conversion_unprivileged_main); - // Overwrite the instruction we'll return to with "bx lr" (jump to address in LR). - newpsp[6] = psp[6]; - *reinterpret_cast(newpsp[6]) = 0x4770; // "bx lr" - // Keep PSR contents (bit set forces Thumb mode, just in case). - newpsp[7] = psp[7] | (1 << 24); - // Set the new stack pointer. - asm("msr psp, %0" :: "r" (newpsp)); - } -} - -void signalOperate(adcsample_t *buffer, size_t) -{ - chSysLockFromISR(); - - if (chMBGetUsedCountI(&conversionMB) > 1) { - chMBResetI(&conversionMB); - chMBResumeX(&conversionMB); - chSysUnlockFromISR(); - abortAlgorithmFromISR(); - } else { - if (buffer == samplesIn.data()) { - samplesIn.setModified(); - chMBPostI(&conversionMB, MSG_CONVFIRST); - } else { - samplesIn.setMidmodified(); - chMBPostI(&conversionMB, MSG_CONVSECOND); - } - chSysUnlockFromISR(); - } -} - -void signalOperateMeasure(adcsample_t *buffer, [[maybe_unused]] size_t count) -{ - chSysLockFromISR(); - if (buffer == samplesIn.data()) { - samplesIn.setModified(); - chMBPostI(&conversionMB, MSG_CONVFIRST_MEASURE); - } else { - samplesIn.setMidmodified(); - chMBPostI(&conversionMB, MSG_CONVSECOND_MEASURE); - } - chSysUnlockFromISR(); - - ADC::setOperation(signalOperate); -} - -extern "C" { - -__attribute__((naked)) -void port_syscall(struct port_extctx *ctxp, uint32_t n) -{ - switch (n) { - case 0: - { - chSysLock(); - chMsgWaitS(); - auto msg = chMsgGet(conversionThreadMonitorHandle); - chMsgReleaseS(conversionThreadMonitorHandle, MSG_OK); - chSysUnlock(); - ctxp->r0 = msg; - } - break; - case 1: - { - using mathcall = void (*)(); - static mathcall funcs[3] = { - reinterpret_cast(cordic::sin), - reinterpret_cast(cordic::cos), - reinterpret_cast(cordic::tan), - }; -#if defined(PLATFORM_H7) - asm("vmov.f64 d0, %0, %1" :: "r" (ctxp->r1), "r" (ctxp->r2)); - if (ctxp->r0 < 3) { - funcs[ctxp->r0](); - asm("vmov.f64 %0, %1, d0" : "=r" (ctxp->r1), "=r" (ctxp->r2)); - } else { - asm("eor r0, r0; vmov.f64 d0, r0, r0"); - } -#else - asm("vmov.f32 s0, %0" :: "r" (ctxp->r1)); - if (ctxp->r0 < 3) { - funcs[ctxp->r0](); - asm("vmov.f32 %0, s0" : "=r" (ctxp->r1)); - } else { - asm("eor r0, r0; vmov.f32 s0, r0"); - } -#endif - } - break; - case 2: - if (ctxp->r0 == 0) { - chTMStartMeasurementX(&conversion_time_measurement); - } else { - chTMStopMeasurementX(&conversion_time_measurement); - // Subtract measurement overhead from the result. - // Running an empty algorithm ("bx lr") takes 196 cycles as of 2/4/21. - // Only measures algorithm code time (loading args/storing result takes 9 cycles). - constexpr rtcnt_t measurement_overhead = 196 - 1; - if (conversion_time_measurement.last > measurement_overhead) - conversion_time_measurement.last -= measurement_overhead; - } - break; - case 3: - ctxp->r0 = ADC::readAlt(ctxp->r0); - break; - case 4: - { - const char *str = reinterpret_cast(ctxp->r0); - auto src = str; - auto dst = userMessageBuffer; - while (*src) - *dst++ = *src++; - *dst = '\0'; - userMessageSize = src - str; - } - break; - default: - while (1); - break; - } - - asm("svc 0"); - while (1); -} - -__attribute__((naked)) -void MemManage_Handler() -{ - // 1. Get the stack pointer. - uint32_t lr; - asm("mov %0, lr" : "=r" (lr)); - - // 2. Recover from the fault. - abortAlgorithmFromISR(); - - // 3. Return. - asm("mov lr, %0; bx lr" :: "r" (lr)); -} - -__attribute__((naked)) -void HardFault_Handler() -{ - // Get the stack pointer. - //uint32_t *stack; - uint32_t lr; - asm("mov %0, lr" : "=r" (lr)); - /*asm("\ - tst lr, #4; \ - ite eq; \ - mrseq %0, msp; \ - mrsne %0, psp; \ - mov %1, lr; \ - " : "=r" (stack), "=r" (lr));*/ - - // If coming from the algorithm, attempt to recover; otherwise, give up. - if (run_status != RunStatus::Running && (lr & 4) != 0) - MemManage_Handler(); - - while (1); -} - -} // extern "C" - diff --git a/source/monitor.cpp b/source/monitor.cpp new file mode 100644 index 0000000..335a1eb --- /dev/null +++ b/source/monitor.cpp @@ -0,0 +1,80 @@ +/** + * @file monitor.cpp + * @brief Manages the device monitoring thread (status LEDs, etc.). + * + * Copyright (C) 2021 Clyne Sullivan + * + * Distributed under the GNU GPL v3 or later. You should have received a copy of + * the GNU General Public License along with this program. + * If not, see . + */ + +#include "monitor.hpp" + +#include "error.hpp" +#include "runstatus.hpp" + +#include "ch.h" +#include "hal.h" + +void Monitor::begin() +{ + chThdCreateStatic(m_thread_stack.data(), + m_thread_stack.size(), + LOWPRIO, + threadMonitor, + nullptr); +} + +void Monitor::threadMonitor(void *) +{ + palSetLineMode(LINE_BUTTON, PAL_MODE_INPUT_PULLUP); + auto readButton = [] { +#ifdef TARGET_PLATFORM_L4 + return !palReadLine(LINE_BUTTON); +#else + return palReadLine(LINE_BUTTON); +#endif + }; + + palClearLine(LINE_LED_RED); + palClearLine(LINE_LED_YELLOW); + + while (1) { + bool isidle = run_status == RunStatus::Idle; + auto led = isidle ? LINE_LED_GREEN : LINE_LED_YELLOW; + auto delay = isidle ? 500 : 250; + + palSetLine(led); + chThdSleepMilliseconds(delay); + palClearLine(led); + chThdSleepMilliseconds(delay); + + if (run_status == RunStatus::Idle && readButton()) { + palSetLine(LINE_LED_RED); + palSetLine(LINE_LED_YELLOW); + chSysLock(); + while (readButton()) + asm("nop"); + while (!readButton()) + asm("nop"); + chSysUnlock(); + palClearLine(LINE_LED_RED); + palClearLine(LINE_LED_YELLOW); + chThdSleepMilliseconds(500); + } + + static bool erroron = false; + if (auto err = EM.hasError(); err ^ erroron) { + erroron = err; + if (err) + palSetLine(LINE_LED_RED); + else + palClearLine(LINE_LED_RED); + } + } +} + +__attribute__((section(".stacks"))) +std::array Monitor::m_thread_stack = {}; + diff --git a/source/monitor.hpp b/source/monitor.hpp new file mode 100644 index 0000000..44545c3 --- /dev/null +++ b/source/monitor.hpp @@ -0,0 +1,29 @@ +/** + * @file monitor.hpp + * @brief Manages the device monitoring thread (status LEDs, etc.). + * + * Copyright (C) 2021 Clyne Sullivan + * + * Distributed under the GNU GPL v3 or later. You should have received a copy of + * the GNU General Public License along with this program. + * If not, see . + */ + +#ifndef STMDSP_MONITOR_HPP +#define STMDSP_MONITOR_HPP + +#include + +class Monitor +{ +public: + static void begin(); + +private: + static void threadMonitor(void *); + + static std::array m_thread_stack; +}; + +#endif // STMDSP_MONITOR_HPP + diff --git a/source/adc.cpp b/source/periph/adc.cpp similarity index 98% rename from source/adc.cpp rename to source/periph/adc.cpp index 2a4fa38..00438f2 100644 --- a/source/adc.cpp +++ b/source/periph/adc.cpp @@ -88,7 +88,7 @@ ADCConversionGroup ADC::m_group_config2 = { .awd3cr = 0, #endif .smpr = { - ADC_SMPR1_SMP_AN1(ADC_SMPR_SMP_12P5) | ADC_SMPR1_SMP_AN2(ADC_SMPR_SMP_12P5), 0 + ADC_SMPR1_SMP_AN1(ADC_SMPR_SMP_2P5) | ADC_SMPR1_SMP_AN2(ADC_SMPR_SMP_2P5), 0 }, .sqr = { ADC_SQR1_SQ1_N(ADC_CHANNEL_IN1) | ADC_SQR1_SQ2_N(ADC_CHANNEL_IN2), @@ -141,8 +141,8 @@ adcsample_t ADC::readAlt(unsigned int id) static adcsample_t result[16] = {}; readAltDone = false; adcStartConversion(m_driver2, &m_group_config2, result, 8); - while (!readAltDone) - __WFI(); + while (!readAltDone); + //__WFI(); adcStopConversion(m_driver2); return result[id]; } diff --git a/source/adc.hpp b/source/periph/adc.hpp similarity index 100% rename from source/adc.hpp rename to source/periph/adc.hpp diff --git a/source/cordic.cpp b/source/periph/cordic.cpp similarity index 100% rename from source/cordic.cpp rename to source/periph/cordic.cpp diff --git a/source/cordic.hpp b/source/periph/cordic.hpp similarity index 100% rename from source/cordic.hpp rename to source/periph/cordic.hpp diff --git a/source/dac.cpp b/source/periph/dac.cpp similarity index 100% rename from source/dac.cpp rename to source/periph/dac.cpp diff --git a/source/dac.hpp b/source/periph/dac.hpp similarity index 100% rename from source/dac.hpp rename to source/periph/dac.hpp diff --git a/source/usbcfg.c b/source/periph/usbcfg.c similarity index 100% rename from source/usbcfg.c rename to source/periph/usbcfg.c diff --git a/source/usbcfg.h b/source/periph/usbcfg.h similarity index 100% rename from source/usbcfg.h rename to source/periph/usbcfg.h diff --git a/source/usbserial.cpp b/source/periph/usbserial.cpp similarity index 100% rename from source/usbserial.cpp rename to source/periph/usbserial.cpp diff --git a/source/usbserial.hpp b/source/periph/usbserial.hpp similarity index 100% rename from source/usbserial.hpp rename to source/periph/usbserial.hpp diff --git a/source/runstatus.hpp b/source/runstatus.hpp new file mode 100644 index 0000000..ab269b4 --- /dev/null +++ b/source/runstatus.hpp @@ -0,0 +1,11 @@ +// Run status +// +enum class RunStatus : char +{ + Idle = '1', + Running, + Recovering +}; + +extern RunStatus run_status; + diff --git a/source/samples.cpp b/source/samples.cpp new file mode 100644 index 0000000..cfbf835 --- /dev/null +++ b/source/samples.cpp @@ -0,0 +1,35 @@ +/** + * @file samples.cpp + * @brief Provides sample buffers for inputs and outputs. + * + * Copyright (C) 2021 Clyne Sullivan + * + * Distributed under the GNU GPL v3 or later. You should have received a copy of + * the GNU General Public License along with this program. + * If not, see . + */ + +#include "samples.hpp" + +#include "ch.h" +#include "hal.h" + +#include + +static_assert(sizeof(adcsample_t) == sizeof(uint16_t)); +static_assert(sizeof(dacsample_t) == sizeof(uint16_t)); + +#if defined(TARGET_PLATFORM_H7) +__attribute__((section(".convdata"))) +SampleBuffer Samples::In (reinterpret_cast(0x38000000)); // 16k +__attribute__((section(".convdata"))) +SampleBuffer Samples::Out (reinterpret_cast(0x30004000)); // 16k +SampleBuffer Samples::SigGen (reinterpret_cast(0x30000000)); // 16k +#else +__attribute__((section(".convdata"))) +SampleBuffer Samples::In (reinterpret_cast(0x20008000)); // 16k +__attribute__((section(".convdata"))) +SampleBuffer Samples::Out (reinterpret_cast(0x2000C000)); // 16k +SampleBuffer Samples::Generator (reinterpret_cast(0x20010000)); // 16k +#endif + diff --git a/source/samples.hpp b/source/samples.hpp new file mode 100644 index 0000000..6551e25 --- /dev/null +++ b/source/samples.hpp @@ -0,0 +1,26 @@ +/** + * @file samples.hpp + * @brief Provides sample buffers for inputs and outputs. + * + * Copyright (C) 2021 Clyne Sullivan + * + * Distributed under the GNU GPL v3 or later. You should have received a copy of + * the GNU General Public License along with this program. + * If not, see . + */ + +#ifndef STMDSP_SAMPLES_HPP +#define STMDSP_SAMPLES_HPP + +#include "samplebuffer.hpp" + +class Samples +{ +public: + static SampleBuffer In; + static SampleBuffer Out; + static SampleBuffer Generator; +}; + +#endif // STMDSP_SAMPLES_HPP + From 555749ef5dde558f745f0dc6d00a168d3b3e9d58 Mon Sep 17 00:00:00 2001 From: Clyne Sullivan Date: Sun, 1 Aug 2021 18:53:09 -0400 Subject: [PATCH 06/13] 8x oversample; other fixes --- Makefile | 2 +- source/cfg/mcuconf_l4.h | 4 ++-- source/communication.cpp | 1 + source/conversion.cpp | 17 ++++++++++------- source/conversion.hpp | 2 +- source/elfload.cpp | 16 ++++++++++++++++ source/elfload.hpp | 15 +++------------ source/monitor.cpp | 7 +++---- source/monitor.hpp | 4 +++- source/periph/adc.cpp | 38 +++++++++++++++++++++++++++----------- source/sclock.cpp | 7 ++++++- 11 files changed, 73 insertions(+), 40 deletions(-) diff --git a/Makefile b/Makefile index e308e1e..44f4c8a 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,7 @@ endif # C++ specific options here (added to USE_OPT). ifeq ($(USE_CPPOPT),) - USE_CPPOPT = -std=c++2a -fno-rtti + USE_CPPOPT = -std=c++2a -fno-rtti -fno-exceptions endif # Enable this if you want the linker to remove unused code and data. diff --git a/source/cfg/mcuconf_l4.h b/source/cfg/mcuconf_l4.h index 438e0be..bf19f7a 100644 --- a/source/cfg/mcuconf_l4.h +++ b/source/cfg/mcuconf_l4.h @@ -47,11 +47,11 @@ #define STM32_HSE_ENABLED FALSE #define STM32_LSE_ENABLED FALSE #define STM32_MSIPLL_ENABLED FALSE -#define STM32_MSIRANGE STM32_MSIRANGE_8M +#define STM32_MSIRANGE STM32_MSIRANGE_4M #define STM32_MSISRANGE STM32_MSISRANGE_4M #define STM32_SW STM32_SW_PLL #define STM32_PLLSRC STM32_PLLSRC_MSI -#define STM32_PLLM_VALUE 2 +#define STM32_PLLM_VALUE 1 #define STM32_PLLN_VALUE 72 #define STM32_PLLP_VALUE 7 #define STM32_PLLQ_VALUE 6 diff --git a/source/communication.cpp b/source/communication.cpp index 5835aa5..3a264fb 100644 --- a/source/communication.cpp +++ b/source/communication.cpp @@ -124,6 +124,7 @@ void updateGenerator(unsigned char *cmd) more = DAC::sigGenWantsMore(); } while (more == -1); + // Receive streamed samples in half-buffer chunks. USBSerial::read(reinterpret_cast( more == 0 ? Samples::Generator.data() : Samples::Generator.middata()), Samples::Generator.bytesize() / 2); diff --git a/source/conversion.cpp b/source/conversion.cpp index 27954be..95118f0 100644 --- a/source/conversion.cpp +++ b/source/conversion.cpp @@ -7,13 +7,16 @@ #include "runstatus.hpp" #include "samples.hpp" -constexpr msg_t MSG_CONVFIRST = 1; -constexpr msg_t MSG_CONVSECOND = 2; -constexpr msg_t MSG_CONVFIRST_MEASURE = 3; -constexpr msg_t MSG_CONVSECOND_MEASURE = 4; +// MSG_* things below are macros rather than constexpr +// to ensure inlining. -constexpr auto MSG_FOR_FIRST = [](msg_t m) { return m & 1; }; -constexpr auto MSG_FOR_MEASURE = [](msg_t m) { return m > 2; }; +#define MSG_CONVFIRST (1) +#define MSG_CONVSECOND (2) +#define MSG_CONVFIRST_MEASURE (3) +#define MSG_CONVSECOND_MEASURE (4) + +#define MSG_FOR_FIRST(msg) (msg & 1) +#define MSG_FOR_MEASURE(msg) (msg > 2) time_measurement_t conversion_time_measurement; @@ -24,7 +27,7 @@ thread_t *ConversionManager::m_thread_runner = nullptr; __attribute__((section(".stacks"))) std::array ConversionManager::m_thread_monitor_stack = {}; __attribute__((section(".stacks"))) -std::array ConversionManager::m_thread_runner_entry_stack = {}; +std::array ConversionManager::m_thread_runner_entry_stack = {}; __attribute__((section(".convdata"))) std::array ConversionManager::m_thread_runner_stack = {}; diff --git a/source/conversion.hpp b/source/conversion.hpp index ad949dc..0a18f3b 100644 --- a/source/conversion.hpp +++ b/source/conversion.hpp @@ -53,7 +53,7 @@ private: static thread_t *m_thread_runner; static std::array m_thread_monitor_stack; - static std::array m_thread_runner_entry_stack; + static std::array m_thread_runner_entry_stack; static std::array m_thread_runner_stack; static std::array m_mailbox_buffer; diff --git a/source/elfload.cpp b/source/elfload.cpp index a430ad2..2d75cb0 100644 --- a/source/elfload.cpp +++ b/source/elfload.cpp @@ -21,6 +21,22 @@ std::array ELFManager::m_file_buffer = {}; static const unsigned char elf_header[] = { '\177', 'E', 'L', 'F' }; +__attribute__((section(".convcode"))) +ELFManager::EntryFunc ELFManager::loadedElf() +{ + return m_entry; +} + +unsigned char *ELFManager::fileBuffer() +{ + return m_file_buffer.data(); +} + +void ELFManager::unload() +{ + m_entry = nullptr; +} + template constexpr static auto ptr_from_offset(void *base, uint32_t offset) { diff --git a/source/elfload.hpp b/source/elfload.hpp index ada35e5..84d49d3 100644 --- a/source/elfload.hpp +++ b/source/elfload.hpp @@ -25,18 +25,9 @@ public: using EntryFunc = Sample *(*)(Sample *, size_t); static EntryFunc loadFromInternalBuffer(); - - static EntryFunc loadedElf() { - return m_entry; - } - - static unsigned char *fileBuffer() { - return m_file_buffer.data(); - } - - static void unload() { - m_entry = nullptr; - } + static EntryFunc loadedElf(); + static unsigned char *fileBuffer(); + static void unload(); private: static EntryFunc m_entry; diff --git a/source/monitor.cpp b/source/monitor.cpp index 335a1eb..08a62d5 100644 --- a/source/monitor.cpp +++ b/source/monitor.cpp @@ -14,9 +14,11 @@ #include "error.hpp" #include "runstatus.hpp" -#include "ch.h" #include "hal.h" +__attribute__((section(".stacks"))) +std::array Monitor::m_thread_stack = {}; + void Monitor::begin() { chThdCreateStatic(m_thread_stack.data(), @@ -75,6 +77,3 @@ void Monitor::threadMonitor(void *) } } -__attribute__((section(".stacks"))) -std::array Monitor::m_thread_stack = {}; - diff --git a/source/monitor.hpp b/source/monitor.hpp index 44545c3..93f75e3 100644 --- a/source/monitor.hpp +++ b/source/monitor.hpp @@ -12,6 +12,8 @@ #ifndef STMDSP_MONITOR_HPP #define STMDSP_MONITOR_HPP +#include "ch.h" + #include class Monitor @@ -22,7 +24,7 @@ public: private: static void threadMonitor(void *); - static std::array m_thread_stack; + static std::array m_thread_stack; }; #endif // STMDSP_MONITOR_HPP diff --git a/source/periph/adc.cpp b/source/periph/adc.cpp index 00438f2..4667307 100644 --- a/source/periph/adc.cpp +++ b/source/periph/adc.cpp @@ -39,7 +39,7 @@ ADCConversionGroup ADC::m_group_config = { .end_cb = ADC::conversionCallback, .error_cb = nullptr, .cfgr = ADC_CFGR_EXTEN_RISING | ADC_CFGR_EXTSEL_SRC(13), /* TIM6_TRGO */ - .cfgr2 = ADC_CFGR2_ROVSE | ADC_CFGR2_OVSR_1 | ADC_CFGR2_OVSS_0, // Oversampling 2x + .cfgr2 = 0,//ADC_CFGR2_ROVSE | ADC_CFGR2_OVSR_1 | ADC_CFGR2_OVSS_0, // Oversampling 2x #if defined(TARGET_PLATFORM_H7) .ccr = 0, .pcsel = 0, @@ -73,7 +73,7 @@ ADCConversionGroup ADC::m_group_config2 = { .end_cb = readAltCallback, .error_cb = nullptr, .cfgr = ADC_CFGR_EXTEN_RISING | ADC_CFGR_EXTSEL_SRC(13), /* TIM6_TRGO */ - .cfgr2 = ADC_CFGR2_ROVSE | ADC_CFGR2_OVSR_1 | ADC_CFGR2_OVSS_0, // Oversampling 2x + .cfgr2 = 0,//ADC_CFGR2_ROVSE | ADC_CFGR2_OVSR_1 | ADC_CFGR2_OVSS_0, // Oversampling 2x #if defined(TARGET_PLATFORM_H7) .ccr = 0, .pcsel = 0, @@ -182,13 +182,29 @@ void ADC::setRate(SClock::Rate rate) adcStart(m_driver, &m_config); #elif defined(TARGET_PLATFORM_L4) std::array, 6> m_rate_presets = {{ + // PLLSAI2 sources MSI of 4MHz, divided by PLLM of /1 = 4MHz. + // 4MHz is then multiplied by PLLSAI2N (x8 to x86), with result + // between 64 and 344 MHz. + // + // SAI2N MUST BE AT LEAST 16 TO MAKE 64MHz MINIMUM. + // + // That is then divided by PLLSAI2R: + // R of 0 = /2; 1 = /4, 2 = /6, 3 = /8. + // PLLSAI2 then feeds into the ADC, which has a prescaler of /10. + // Finally, the ADC's SMP value produces the desired sample rate. + // + // 4MHz * N / R / 10 / SMP = sample rate. + // + // With oversampling, must create faster clock + // (x2 oversampling requires x2 sample rate clock). + // // Rate PLLSAI2N R SMPR - {/* 8k */ 8, 1, ADC_SMPR_SMP_12P5}, - {/* 16k */ 16, 1, ADC_SMPR_SMP_12P5}, - {/* 20k */ 20, 1, ADC_SMPR_SMP_12P5}, - {/* 32k */ 32, 1, ADC_SMPR_SMP_12P5}, - {/* 48k */ 24, 0, ADC_SMPR_SMP_12P5}, - {/* 96k */ 73, 1, ADC_SMPR_SMP_6P5} // Technically 96.05263kS/s + {/* 8k */ 16, 1, ADC_SMPR_SMP_12P5}, // R3=32k (min), R1=64k + {/* 16k */ 16, 0, ADC_SMPR_SMP_12P5}, + {/* 20k */ 20, 0, ADC_SMPR_SMP_12P5}, + {/* 32k */ 32, 0, ADC_SMPR_SMP_12P5}, + {/* 48k */ 48, 0, ADC_SMPR_SMP_12P5}, + {/* 96k */ 73, 0, ADC_SMPR_SMP_6P5} // Technically 96.05263kS/s }}; auto& preset = m_rate_presets[static_cast(rate)]; @@ -205,9 +221,9 @@ void ADC::setRate(SClock::Rate rate) m_group_config.smpr[0] = ADC_SMPR1_SMP_AN5(smpr); - // Set 2x oversampling - m_group_config.cfgr2 = ADC_CFGR2_ROVSE | ADC_CFGR2_OVSR_0 | ADC_CFGR2_OVSS_1; - m_group_config2.cfgr2 = ADC_CFGR2_ROVSE | ADC_CFGR2_OVSR_0 | ADC_CFGR2_OVSS_1; + // 8x oversample + m_group_config.cfgr2 = ADC_CFGR2_ROVSE | (2 << ADC_CFGR2_OVSR_Pos) | (3 << ADC_CFGR2_OVSS_Pos); + m_group_config2.cfgr2 = ADC_CFGR2_ROVSE | (2 << ADC_CFGR2_OVSR_Pos) | (3 << ADC_CFGR2_OVSS_Pos); #endif } diff --git a/source/sclock.cpp b/source/sclock.cpp index 317b995..6660f95 100644 --- a/source/sclock.cpp +++ b/source/sclock.cpp @@ -35,7 +35,12 @@ const std::array SClock::m_rate_divs = {{ /* 48k */ 100, /* 96k */ 50 #else - 4500, 2250, 1800, 1125, 750, 375 + /* 8k */ 4500, + /* 16k */ 2250, + /* 20k */ 1800, + /* 32k */ 1125, + /* 48k */ 750, + /* 96k */ 375 #endif }}; From b430a38ce5674b319ef9bf1c6e773c9eb33f1542 Mon Sep 17 00:00:00 2001 From: Clyne Sullivan Date: Tue, 5 Oct 2021 13:58:27 -0400 Subject: [PATCH 07/13] algorithm load fix --- source/communication.cpp | 6 ++++-- source/conversion.cpp | 13 +++++++++++-- source/conversion.hpp | 3 --- source/elfload.cpp | 11 ++++++++--- source/elfload.hpp | 2 +- source/handlers.cpp | 2 ++ 6 files changed, 26 insertions(+), 11 deletions(-) diff --git a/source/communication.cpp b/source/communication.cpp index 3a264fb..ec02a42 100644 --- a/source/communication.cpp +++ b/source/communication.cpp @@ -142,8 +142,8 @@ void loadAlgorithm(unsigned char *cmd) unsigned int size = cmd[1] | (cmd[2] << 8); if (EM.assert(size < MAX_ELF_FILE_SIZE, Error::BadUserCodeSize)) { USBSerial::read(ELFManager::fileBuffer(), size); - auto entry = ELFManager::loadFromInternalBuffer(); - EM.assert(entry != nullptr, Error::BadUserCodeLoad); + auto success = ELFManager::loadFromInternalBuffer(); + EM.assert(success, Error::BadUserCodeLoad); } } } @@ -214,6 +214,8 @@ void readIdentifier(unsigned char *) void readExecTime(unsigned char *) { + // Stores the measured execution time. + extern time_measurement_t conversion_time_measurement; USBSerial::write(reinterpret_cast(&conversion_time_measurement.last), sizeof(rtcnt_t)); } diff --git a/source/conversion.cpp b/source/conversion.cpp index 95118f0..c9dc0c9 100644 --- a/source/conversion.cpp +++ b/source/conversion.cpp @@ -1,3 +1,14 @@ +/** + * @file conversion.cpp + * @brief Manages algorithm application (converts input samples to output). + * + * Copyright (C) 2021 Clyne Sullivan + * + * Distributed under the GNU GPL v3 or later. You should have received a copy of + * the GNU General Public License along with this program. + * If not, see . + */ + #include "conversion.hpp" #include "periph/adc.hpp" @@ -18,8 +29,6 @@ #define MSG_FOR_FIRST(msg) (msg & 1) #define MSG_FOR_MEASURE(msg) (msg > 2) -time_measurement_t conversion_time_measurement; - __attribute__((section(".convdata"))) thread_t *ConversionManager::m_thread_monitor = nullptr; thread_t *ConversionManager::m_thread_runner = nullptr; diff --git a/source/conversion.hpp b/source/conversion.hpp index 0a18f3b..6af4972 100644 --- a/source/conversion.hpp +++ b/source/conversion.hpp @@ -60,8 +60,5 @@ private: static mailbox_t m_mailbox; }; -// Stores the measured execution time. -extern time_measurement_t conversion_time_measurement; - #endif // STMDSP_CONVERSION_HPP diff --git a/source/elfload.cpp b/source/elfload.cpp index 2d75cb0..87461e4 100644 --- a/source/elfload.cpp +++ b/source/elfload.cpp @@ -43,14 +43,16 @@ constexpr static auto ptr_from_offset(void *base, uint32_t offset) return reinterpret_cast(reinterpret_cast(base) + offset); } -ELFManager::EntryFunc ELFManager::loadFromInternalBuffer() +bool ELFManager::loadFromInternalBuffer() { + m_entry = nullptr; + auto elf_data = m_file_buffer.data(); // Check the ELF's header signature auto ehdr = reinterpret_cast(elf_data); if (!std::equal(ehdr->e_ident, ehdr->e_ident + 4, elf_header)) - return nullptr; + return false; // Iterate through program header LOAD sections bool loaded = false; @@ -74,6 +76,9 @@ ELFManager::EntryFunc ELFManager::loadFromInternalBuffer() } - return loaded ? reinterpret_cast(ehdr->e_entry) : nullptr; + if (loaded) + m_entry = reinterpret_cast(ehdr->e_entry); + + return loaded; } diff --git a/source/elfload.hpp b/source/elfload.hpp index 84d49d3..10d95d7 100644 --- a/source/elfload.hpp +++ b/source/elfload.hpp @@ -24,7 +24,7 @@ class ELFManager public: using EntryFunc = Sample *(*)(Sample *, size_t); - static EntryFunc loadFromInternalBuffer(); + static bool loadFromInternalBuffer(); static EntryFunc loadedElf(); static unsigned char *fileBuffer(); static void unload(); diff --git a/source/handlers.cpp b/source/handlers.cpp index 4b0e3eb..07f6ed3 100644 --- a/source/handlers.cpp +++ b/source/handlers.cpp @@ -7,6 +7,8 @@ extern "C" { +time_measurement_t conversion_time_measurement; + __attribute__((naked)) void port_syscall(struct port_extctx *ctxp, uint32_t n) { From d002746e25237738ab45b472c1fff6e8fbe4183b Mon Sep 17 00:00:00 2001 From: Clyne Sullivan Date: Sun, 10 Oct 2021 09:45:37 -0400 Subject: [PATCH 08/13] wip: better samplebuffer filling --- Makefile | 2 +- source/samplebuffer.cpp | 58 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 53 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 44f4c8a..3dcfd94 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ TARGET_PLATFORM = L4 # Compiler options here. ifeq ($(USE_OPT),) - USE_OPT = -O0 -ggdb -fomit-frame-pointer -falign-functions=16 --specs=nosys.specs + USE_OPT = -Os -g3 -ggdb -fomit-frame-pointer -falign-functions=16 --specs=nosys.specs endif # C specific options here (added to USE_OPT). diff --git a/source/samplebuffer.cpp b/source/samplebuffer.cpp index 1acf2f4..6f588b1 100644 --- a/source/samplebuffer.cpp +++ b/source/samplebuffer.cpp @@ -19,17 +19,63 @@ void SampleBuffer::clear() { } __attribute__((section(".convcode"))) void SampleBuffer::modify(Sample *data, unsigned int srcsize) { - auto size = srcsize < m_size ? srcsize : m_size; + auto size = std::min(srcsize, m_size); + size = (size + 15) & 0xFF0; + m_modified = m_buffer; - for (Sample *d = m_buffer, *s = data; s != data + size;) - *d++ = *s++; + const int *src = reinterpret_cast(data); + const int * const srcend = src + (size / 2); + int *dst = reinterpret_cast(m_buffer); + do { + int a = src[0]; + int b = src[1]; + int c = src[2]; + int d = src[3]; + int e = src[4]; + int f = src[5]; + int g = src[6]; + int h = src[7]; + dst[0] = a; + dst[1] = b; + dst[2] = c; + dst[3] = d; + dst[4] = e; + dst[5] = f; + dst[6] = g; + dst[7] = h; + src += 8; + dst += 8; + } while (src < srcend); } __attribute__((section(".convcode"))) void SampleBuffer::midmodify(Sample *data, unsigned int srcsize) { - auto size = srcsize < m_size / 2 ? srcsize : m_size / 2; + auto size = std::min(srcsize, m_size / 2); + size = (size + 15) & 0xFF0; + m_modified = middata(); - for (Sample *d = middata(), *s = data; s != data + size;) - *d++ = *s++; + const int *src = reinterpret_cast(data); + const int * const srcend = src + (size / 2); + int *dst = reinterpret_cast(middata()); + do { + int a = src[0]; + int b = src[1]; + int c = src[2]; + int d = src[3]; + int e = src[4]; + int f = src[5]; + int g = src[6]; + int h = src[7]; + dst[0] = a; + dst[1] = b; + dst[2] = c; + dst[3] = d; + dst[4] = e; + dst[5] = f; + dst[6] = g; + dst[7] = h; + src += 8; + dst += 8; + } while (src < srcend); } void SampleBuffer::setModified() { From e4a8d6eefc267c3a38d5237205421cbbe6eaebe8 Mon Sep 17 00:00:00 2001 From: Clyne Sullivan Date: Sun, 10 Oct 2021 20:19:19 -0400 Subject: [PATCH 09/13] optimized samplebuffer copying --- Makefile | 8 +++---- source/handlers.cpp | 16 +++++++------- source/samplebuffer.cpp | 48 ++++++++++++++++++++--------------------- 3 files changed, 36 insertions(+), 36 deletions(-) diff --git a/Makefile b/Makefile index 3dcfd94..9e98828 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ TARGET_PLATFORM = L4 # Compiler options here. ifeq ($(USE_OPT),) - USE_OPT = -Os -g3 -ggdb -fomit-frame-pointer -falign-functions=16 --specs=nosys.specs + USE_OPT = -O0 -g3 -ggdb -fomit-frame-pointer -falign-functions=16 --specs=nosys.specs endif # C specific options here (added to USE_OPT). @@ -177,9 +177,9 @@ CPPWARN = -Wall -Wextra -Wundef -pedantic -Wno-volatile # List all user C define here, like -D_DEBUG=1 UDEFS = -DCORTEX_ENABLE_WFI_IDLE=TRUE \ - -DPORT_USE_SYSCALL=TRUE \ - -DPORT_USE_GUARD_MPU_REGION=MPU_REGION_0 \ - -DTARGET_PLATFORM_$(TARGET_PLATFORM) + -DPORT_USE_SYSCALL=TRUE \ + -DPORT_USE_GUARD_MPU_REGION=MPU_REGION_0 \ + -DTARGET_PLATFORM_$(TARGET_PLATFORM) # Define ASM defines here UADEFS = diff --git a/source/handlers.cpp b/source/handlers.cpp index 07f6ed3..2ff948d 100644 --- a/source/handlers.cpp +++ b/source/handlers.cpp @@ -105,7 +105,7 @@ void MemManage_Handler() { // 1. Get the stack pointer. uint32_t lr; - asm("mov %0, lr" : "=r" (lr)); + asm("mov %0, lr" : "=r" (lr)); // 2. Recover from the fault. ConversionManager::abort(); @@ -120,14 +120,14 @@ void HardFault_Handler() // Get the stack pointer. //uint32_t *stack; uint32_t lr; - asm("mov %0, lr" : "=r" (lr)); - /*asm("\ - tst lr, #4; \ - ite eq; \ - mrseq %0, msp; \ - mrsne %0, psp; \ + asm("mov %0, lr" : "=r" (lr)); + /*asm("\ + tst lr, #4; \ + ite eq; \ + mrseq %0, msp; \ + mrsne %0, psp; \ mov %1, lr; \ - " : "=r" (stack), "=r" (lr));*/ + " : "=r" (stack), "=r" (lr));*/ // If coming from the algorithm, attempt to recover; otherwise, give up. if (run_status != RunStatus::Running && (lr & 4) != 0) diff --git a/source/samplebuffer.cpp b/source/samplebuffer.cpp index 6f588b1..74c6778 100644 --- a/source/samplebuffer.cpp +++ b/source/samplebuffer.cpp @@ -19,8 +19,8 @@ void SampleBuffer::clear() { } __attribute__((section(".convcode"))) void SampleBuffer::modify(Sample *data, unsigned int srcsize) { - auto size = std::min(srcsize, m_size); - size = (size + 15) & 0xFF0; + auto size = srcsize < m_size ? srcsize : m_size; + size = (size + 15) & (~15); m_modified = m_buffer; const int *src = reinterpret_cast(data); @@ -35,22 +35,22 @@ void SampleBuffer::modify(Sample *data, unsigned int srcsize) { int f = src[5]; int g = src[6]; int h = src[7]; - dst[0] = a; - dst[1] = b; - dst[2] = c; - dst[3] = d; - dst[4] = e; - dst[5] = f; - dst[6] = g; - dst[7] = h; - src += 8; - dst += 8; + dst[0] = a; + dst[1] = b; + dst[2] = c; + dst[3] = d; + dst[4] = e; + dst[5] = f; + dst[6] = g; + dst[7] = h; + src += 8; + dst += 8; } while (src < srcend); } __attribute__((section(".convcode"))) void SampleBuffer::midmodify(Sample *data, unsigned int srcsize) { - auto size = std::min(srcsize, m_size / 2); - size = (size + 15) & 0xFF0; + auto size = srcsize < m_size / 2 ? srcsize : m_size / 2; + size = (size + 15) & (~15); m_modified = middata(); const int *src = reinterpret_cast(data); @@ -65,16 +65,16 @@ void SampleBuffer::midmodify(Sample *data, unsigned int srcsize) { int f = src[5]; int g = src[6]; int h = src[7]; - dst[0] = a; - dst[1] = b; - dst[2] = c; - dst[3] = d; - dst[4] = e; - dst[5] = f; - dst[6] = g; - dst[7] = h; - src += 8; - dst += 8; + dst[0] = a; + dst[1] = b; + dst[2] = c; + dst[3] = d; + dst[4] = e; + dst[5] = f; + dst[6] = g; + dst[7] = h; + src += 8; + dst += 8; } while (src < srcend); } From 6f1c5203f14f82b6a10c9756ef1dc39bc8631ec0 Mon Sep 17 00:00:00 2001 From: Clyne Sullivan Date: Sat, 30 Oct 2021 10:12:07 -0400 Subject: [PATCH 10/13] remove gui (now in stmdspgui repo) --- gui/Hack-License.md | 45 - gui/Hack-Regular.ttf | Bin 383104 -> 0 bytes gui/Makefile | 66 - gui/cmsis/arm_conv_f32.c | 647 - gui/cmsis/arm_conv_q15.c | 734 - gui/cmsis/arm_conv_q31.c | 565 - gui/cmsis/arm_conv_q7.c | 690 - gui/cmsis/arm_fir_f32.c | 997 - gui/cmsis/arm_fir_init_f32.c | 96 - gui/cmsis/arm_fir_init_q15.c | 154 - gui/cmsis/arm_fir_init_q31.c | 96 - gui/cmsis/arm_fir_init_q7.c | 94 - gui/cmsis/arm_fir_q15.c | 691 - gui/cmsis/arm_fir_q31.c | 365 - gui/cmsis/arm_fir_q7.c | 397 - gui/demos/1_fir_twotone.cpp | 474 - gui/demos/2_iir_echo.cpp | 24 - gui/exprtk.hpp | 40121 -------------------- gui/main.cpp | 13 - gui/serial | 1 - gui/stmdsp.cpp | 208 - gui/stmdsp.hpp | 97 - gui/templates/1_convolve_simple.cpp | 29 - gui/templates/2_convolve_overlap_save.cpp | 47 - gui/templates/3_fir.cpp | 47 - gui/templates/4_fir_pro.cpp | 478 - gui/templates/5_fir_differentiator.cpp | 30 - gui/templates/6_iir_test.cpp | 13 - gui/templates/7_iir_echo.cpp | 22 - gui/wav.hpp | 95 - gui/wxapp.hpp | 37 - gui/wxmain.cpp | 476 - gui/wxmain.hpp | 111 - gui/wxmain_devdata.cpp | 198 - gui/wxmain_devdata.h | 16 - gui/wxmain_mfile.cpp | 113 - gui/wxmain_mrun.cpp | 240 - gui/wxmain_mrun_genupload.cpp | 28 - gui/wxsiggen.cpp | 92 - gui/wxsiggen.hpp | 42 - 40 files changed, 48689 deletions(-) delete mode 100644 gui/Hack-License.md delete mode 100644 gui/Hack-Regular.ttf delete mode 100644 gui/Makefile delete mode 100644 gui/cmsis/arm_conv_f32.c delete mode 100644 gui/cmsis/arm_conv_q15.c delete mode 100644 gui/cmsis/arm_conv_q31.c delete mode 100644 gui/cmsis/arm_conv_q7.c delete mode 100644 gui/cmsis/arm_fir_f32.c delete mode 100644 gui/cmsis/arm_fir_init_f32.c delete mode 100644 gui/cmsis/arm_fir_init_q15.c delete mode 100644 gui/cmsis/arm_fir_init_q31.c delete mode 100644 gui/cmsis/arm_fir_init_q7.c delete mode 100644 gui/cmsis/arm_fir_q15.c delete mode 100644 gui/cmsis/arm_fir_q31.c delete mode 100644 gui/cmsis/arm_fir_q7.c delete mode 100644 gui/demos/1_fir_twotone.cpp delete mode 100644 gui/demos/2_iir_echo.cpp delete mode 100644 gui/exprtk.hpp delete mode 100644 gui/main.cpp delete mode 160000 gui/serial delete mode 100644 gui/stmdsp.cpp delete mode 100644 gui/stmdsp.hpp delete mode 100644 gui/templates/1_convolve_simple.cpp delete mode 100644 gui/templates/2_convolve_overlap_save.cpp delete mode 100644 gui/templates/3_fir.cpp delete mode 100644 gui/templates/4_fir_pro.cpp delete mode 100644 gui/templates/5_fir_differentiator.cpp delete mode 100644 gui/templates/6_iir_test.cpp delete mode 100644 gui/templates/7_iir_echo.cpp delete mode 100644 gui/wav.hpp delete mode 100644 gui/wxapp.hpp delete mode 100644 gui/wxmain.cpp delete mode 100644 gui/wxmain.hpp delete mode 100644 gui/wxmain_devdata.cpp delete mode 100644 gui/wxmain_devdata.h delete mode 100644 gui/wxmain_mfile.cpp delete mode 100644 gui/wxmain_mrun.cpp delete mode 100644 gui/wxmain_mrun_genupload.cpp delete mode 100644 gui/wxsiggen.cpp delete mode 100644 gui/wxsiggen.hpp diff --git a/gui/Hack-License.md b/gui/Hack-License.md deleted file mode 100644 index 08927e5..0000000 --- a/gui/Hack-License.md +++ /dev/null @@ -1,45 +0,0 @@ -The work in the Hack project is Copyright 2018 Source Foundry Authors and licensed under the MIT License - -The work in the DejaVu project was committed to the public domain. - -Bitstream Vera Sans Mono Copyright 2003 Bitstream Inc. and licensed under the Bitstream Vera License with Reserved Font Names "Bitstream" and "Vera" - -### MIT License - -Copyright (c) 2018 Source Foundry Authors - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -### BITSTREAM VERA LICENSE - -Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is a trademark of Bitstream, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy of the fonts accompanying this license ("Fonts") and associated documentation files (the "Font Software"), to reproduce and distribute the Font Software, including without limitation the rights to use, copy, merge, publish, distribute, and/or sell copies of the Font Software, and to permit persons to whom the Font Software is furnished to do so, subject to the following conditions: - -The above copyright and trademark notices and this permission notice shall be included in all copies of one or more of the Font Software typefaces. - -The Font Software may be modified, altered, or added to, and in particular the designs of glyphs or characters in the Fonts may be modified and additional glyphs or characters may be added to the Fonts, only if the fonts are renamed to names not containing either the words "Bitstream" or the word "Vera". - -This License becomes null and void to the extent applicable to Fonts or Font Software that has been modified and is distributed under the "Bitstream Vera" names. - -The Font Software may be sold as part of a larger software package but no copy of one or more of the Font Software typefaces may be sold by itself. - -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. - -Except as contained in this notice, the names of Gnome, the Gnome Foundation, and Bitstream Inc., shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Font Software without prior written authorization from the Gnome Foundation or Bitstream Inc., respectively. For further information, contact: fonts at gnome dot org. diff --git a/gui/Hack-Regular.ttf b/gui/Hack-Regular.ttf deleted file mode 100644 index 25578e0928296a26881b5389dc7b6fc6ca876129..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 383104 zcmeEv34B!5_5Z#1y*D%2GugM$1g7oI0Q^?S;p$dt=q6{o$?;L9nVt*_*)s_BA#s(Sxiir zICVBlUfsQEEh{42F!t3~%!&_{*;q15V_7T@Pa>vGpXz3XGpA2;v&IMvXBvxRDJ-33 zvwZoTjR|H!&xvS}!E#tZ_#U%sJxDf>jeAEb9KxEtz|17mbG8CV(k z$$=UAHXgVb_{k%^D!9ghL4rsG&IW#R;F!L(NILcZmr|L$+2>FjsD3)`jheZd078VSVWEvE8LOK!pP@!jEkG_I~Vv3?>8tr z@qU$jzeK*Dhj$^ivUt%bMvErx-`WS-huVL%kF<}q|KiH>A+B&S2X{|n9c(!}k6neQ zwt%8p%!wIN!Ro~brikexAgbkOv8a`wCEC04vs8Oeeg;Lo{4AH0N)|QpuVU?QIutNy z!z{@Wb@J~L?eF^cVx;^m$1|zgKO(S1<7Dlh@~@y66@w5B#_#<0|L?}E;2HmlS6K26 z$xHg?_jrBM=bI<-&1-$W`8mFUWX3zS66_gZVUg$-i}Cv-rr&pg%RgXq*}w7rd<5d( zXtf%1Fps%G&oWlcMzJyA_*T$cXs?S#yuTqv83z=hDquHo-sV*T*VS0L~gYkL9WmUElt zH(tqaU^MhoAZf!y5wi%AV)V6sh5pcgbO}bki^w-aedsL}F+offlf*B@L2ad&CRU3z zqFMBcapHV288gfed<8_YC=sP12&|Qh3Nco+ix0#*;_qULwgQ+)!ptQ7<7OUK#ERJn z(6g2`Ku3ij!`j(&Hj5n#Nw$KmWNX-3woxn>W5f#WMA4z00c@Vd&Sn>|OW3vSI`#v0 zGrN=hgx$@4&h7>7pJKmezhTd^7r~Q%W`AMtfLq@aJ=!v{OuUXqBTZ+AmTO_-*&=od zq~Q12X10}`0jY5*_N7ZJO(o z_NBN+TqX{Ilk&7)=x_%sVWlj{%Gp>p4j>cQ0=5u*eT#OQc8+$YcB*!|cDA-z+p3+V zeV?g`JHZ6YK};(oB?B!gf%((9m8bK3?&Co|f{)~5_+&nf&*$Cz1b#Zdir>cX{_J_j z^PcBF-gIxK*X{Lr%e~Fs3Es)xMc!rJSnASE#qE+to+ZC)MAod(@Y-R4q>%0X)ys zy0r^|=ijA%>D=o4*v;Ijz;mU$*4^N4a!-ihd6WD5?k(<%+?TpD6!1Fw#4JKes3s`KuJNaph9eNkPx%;<^{e5UNu1`9&zSsH5xgVA2-@kni zV{bd~TJrWR`sVG_w_D%c^6vNFzUr-y-ahv&NbR>>Z#(|l_SXA<{eiqb65ou%tASo` z(_giW?a#xDGy&WH54`?{*W3Hw#QSUe_u>7O{k!*LwXlEJ{`>ad^HyO0)o*@=zpx_M z4{LQlB>I~e`CtBm*Bkh~jrV%%J-C0lkG9)tx~Ji$!fd07<|1-U9GNFf2IBg+78cZ{HTwE&v)ZHdVN6OsvoFigY@~)ujpT? zhqMex&@#M$S*@DB)sDq$F#`-Z2L4_ww4S@*UWdpTJ=3N5eJwf{kMth1XiV zR^zo5uX7AIs~2L{ZTvOZrxha_^yf%=_J52{72BcFpb^ER(0R+X)!G(q75lgLiTFrd z0PT1t^krCD@~3E@X~%0{YMWuLeE_{zD@KSq(Z;OMVjA?Hz6P~JpXI>L%ZEPG^;!mW z^#rNgTG@E<37ZVvMjCDrJCRLeFF=Ez0v)~;TKo)XShD>um0J9E=yB5G7ebFe3{CzJ zwD>OZCVLE;{12qd*}Lpl(62VO1vcQRu-{I{3h*4PA4ePEOS%BRHss3ZEFn$C*dIv1iTUZU&9(8Ox8_9mk>e)T8RDZ@s zv-?;xdjPAn`(d~Kf=yz-WE0t=r14?FKFwyb-?AC7h-b6sqy^f^cC&e~mb=(X(9&

Q`v{?KkOs+G5eH##tyK9 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 C6pEby diff --git a/gui/Makefile b/gui/Makefile deleted file mode 100644 index e7e1a74..0000000 --- a/gui/Makefile +++ /dev/null @@ -1,66 +0,0 @@ -UNAME := $(shell uname) - -ifeq ($(UNAME), Linux) - RM = rm -f -else - RM = del -endif - -CXX = g++-10 -CXXFLAGS = --std=c++20 -ggdb -O0 \ - -Wall -Wextra -pedantic \ - -Wno-deprecated-copy \ - -Iserial/include -IMETL/include -IMETL/dependencies/PEGTL/include - -ifeq ($(UNAME), Linux) -CXXFLAGS += $(shell wx-config --cxxflags) -else -CXXFLAGS += -IC:\wx\include -DSTMDSP_WIN32 -Wa,-mbig-obj -endif - -ifeq ($(UNAME), Linux) -CXXFILES = serial/src/serial.cc \ - serial/src/impl/unix.cc \ - serial/src/impl/list_ports/list_ports_linux.cc \ - $(wildcard *.cpp) -else -CXXFILES = serial/src/serial.cc \ - serial/src/impl/win.cc \ - serial/src/impl/list_ports/list_ports_win.cc \ - $(wildcard *.cpp) -endif -OFILES = $(patsubst %.cc, %.o, $(patsubst %.cpp, %.o, $(CXXFILES))) - -ifeq ($(UNAME), Linux) -LIBS = $(shell wx-config --libs) -lwx_gtk3u_stc-3.0 -else -LIBS = -lSetupAPI \ - -LC:\wx\lib\gcc810_x64_dll -lwxbase31u -lwxmsw31u_core -lwxmsw31u_stc -endif - -OUTELF = stmdspgui - -ifeq ($(UNAME), Linux) -CLEANFILES = $(OUTELF) $(OFILES) -else -CLEANFILES = $(subst /,\\,$(OUTELF)) $(subst /,\\,$(OFILES)) -endif - -all: $(OUTELF) - -$(OUTELF): $(OFILES) - @echo " CXX " $(OUTELF) - @$(CXX) $(CXXFLAGS) $(OFILES) $(LIBS) -o $(OUTELF) - -.cc.o: - @echo " CXX " $< - @$(CXX) $(CXXFLAGS) -c $< -o $@ - -.cpp.o: - @echo " CXX " $< - @$(CXX) $(CXXFLAGS) -c $< -o $@ - -clean: - @echo " CLEAN" - @$(RM) $(CLEANFILES) - diff --git a/gui/cmsis/arm_conv_f32.c b/gui/cmsis/arm_conv_f32.c deleted file mode 100644 index 65f7ab8..0000000 --- a/gui/cmsis/arm_conv_f32.c +++ /dev/null @@ -1,647 +0,0 @@ -/* ---------------------------------------------------------------------------- -* Copyright (C) 2010-2014 ARM Limited. All rights reserved. -* -* $Date: 19. March 2015 -* $Revision: V.1.4.5 -* -* Project: CMSIS DSP Library -* Title: arm_conv_f32.c -* -* Description: Convolution of floating-point sequences. -* -* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0 -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* - Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* - Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in -* the documentation and/or other materials provided with the -* distribution. -* - Neither the name of ARM LIMITED nor the names of its contributors -* may be used to endorse or promote products derived from this -* software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -* POSSIBILITY OF SUCH DAMAGE. -* -------------------------------------------------------------------------- */ - -#include "arm_math.h" - -/** - * @ingroup groupFilters - */ - -/** - * @defgroup Conv Convolution - * - * Convolution is a mathematical operation that operates on two finite length vectors to generate a finite length output vector. - * Convolution is similar to correlation and is frequently used in filtering and data analysis. - * The CMSIS DSP library contains functions for convolving Q7, Q15, Q31, and floating-point data types. - * The library also provides fast versions of the Q15 and Q31 functions on Cortex-M4 and Cortex-M3. - * - * \par Algorithm - * Let a[n] and b[n] be sequences of length srcALen and srcBLen samples respectively. - * Then the convolution - * - *

    
- *                   c[n] = a[n] * b[n]    
- * 
- * - * \par - * is defined as - * \image html ConvolutionEquation.gif - * \par - * Note that c[n] is of length srcALen + srcBLen - 1 and is defined over the interval n=0, 1, 2, ..., srcALen + srcBLen - 2. - * pSrcA points to the first input vector of length srcALen and - * pSrcB points to the second input vector of length srcBLen. - * The output result is written to pDst and the calling function must allocate srcALen+srcBLen-1 words for the result. - * - * \par - * Conceptually, when two signals a[n] and b[n] are convolved, - * the signal b[n] slides over a[n]. - * For each offset \c n, the overlapping portions of a[n] and b[n] are multiplied and summed together. - * - * \par - * Note that convolution is a commutative operation: - * - *
    
- *                   a[n] * b[n] = b[n] * a[n].    
- * 
- * - * \par - * This means that switching the A and B arguments to the convolution functions has no effect. - * - * Fixed-Point Behavior - * - * \par - * Convolution requires summing up a large number of intermediate products. - * As such, the Q7, Q15, and Q31 functions run a risk of overflow and saturation. - * Refer to the function specific documentation below for further details of the particular algorithm used. - * - * - * Fast Versions - * - * \par - * Fast versions are supported for Q31 and Q15. Cycles for Fast versions are less compared to Q31 and Q15 of conv and the design requires - * the input signals should be scaled down to avoid intermediate overflows. - * - * - * Opt Versions - * - * \par - * Opt versions are supported for Q15 and Q7. Design uses internal scratch buffer for getting good optimisation. - * These versions are optimised in cycles and consumes more memory(Scratch memory) compared to Q15 and Q7 versions - */ - -/** - * @addtogroup Conv - * @{ - */ - -/** - * @brief Convolution of floating-point sequences. - * @param[in] *pSrcA points to the first input sequence. - * @param[in] srcALen length of the first input sequence. - * @param[in] *pSrcB points to the second input sequence. - * @param[in] srcBLen length of the second input sequence. - * @param[out] *pDst points to the location where the output result is written. Length srcALen+srcBLen-1. - * @return none. - */ - -void arm_conv_f32( - float32_t * pSrcA, - uint32_t srcALen, - float32_t * pSrcB, - uint32_t srcBLen, - float32_t * pDst) -{ - - -#ifndef ARM_MATH_CM0_FAMILY - - /* Run the below code for Cortex-M4 and Cortex-M3 */ - - float32_t *pIn1; /* inputA pointer */ - float32_t *pIn2; /* inputB pointer */ - float32_t *pOut = pDst; /* output pointer */ - float32_t *px; /* Intermediate inputA pointer */ - float32_t *py; /* Intermediate inputB pointer */ - float32_t *pSrc1, *pSrc2; /* Intermediate pointers */ - float32_t sum, acc0, acc1, acc2, acc3; /* Accumulator */ - float32_t x0, x1, x2, x3, c0; /* Temporary variables to hold state and coefficient values */ - uint32_t j, k, count, blkCnt, blockSize1, blockSize2, blockSize3; /* loop counters */ - - /* The algorithm implementation is based on the lengths of the inputs. */ - /* srcB is always made to slide across srcA. */ - /* So srcBLen is always considered as shorter or equal to srcALen */ - if(srcALen >= srcBLen) - { - /* Initialization of inputA pointer */ - pIn1 = pSrcA; - - /* Initialization of inputB pointer */ - pIn2 = pSrcB; - } - else - { - /* Initialization of inputA pointer */ - pIn1 = pSrcB; - - /* Initialization of inputB pointer */ - pIn2 = pSrcA; - - /* srcBLen is always considered as shorter or equal to srcALen */ - j = srcBLen; - srcBLen = srcALen; - srcALen = j; - } - - /* conv(x,y) at n = x[n] * y[0] + x[n-1] * y[1] + x[n-2] * y[2] + ...+ x[n-N+1] * y[N -1] */ - /* The function is internally - * divided into three stages according to the number of multiplications that has to be - * taken place between inputA samples and inputB samples. In the first stage of the - * algorithm, the multiplications increase by one for every iteration. - * In the second stage of the algorithm, srcBLen number of multiplications are done. - * In the third stage of the algorithm, the multiplications decrease by one - * for every iteration. */ - - /* The algorithm is implemented in three stages. - The loop counters of each stage is initiated here. */ - blockSize1 = srcBLen - 1u; - blockSize2 = srcALen - (srcBLen - 1u); - blockSize3 = blockSize1; - - /* -------------------------- - * initializations of stage1 - * -------------------------*/ - - /* sum = x[0] * y[0] - * sum = x[0] * y[1] + x[1] * y[0] - * .... - * sum = x[0] * y[srcBlen - 1] + x[1] * y[srcBlen - 2] +...+ x[srcBLen - 1] * y[0] - */ - - /* In this stage the MAC operations are increased by 1 for every iteration. - The count variable holds the number of MAC operations performed */ - count = 1u; - - /* Working pointer of inputA */ - px = pIn1; - - /* Working pointer of inputB */ - py = pIn2; - - - /* ------------------------ - * Stage1 process - * ----------------------*/ - - /* The first stage starts here */ - while(blockSize1 > 0u) - { - /* Accumulator is made zero for every iteration */ - sum = 0.0f; - - /* Apply loop unrolling and compute 4 MACs simultaneously. */ - k = count >> 2u; - - /* First part of the processing with loop unrolling. Compute 4 MACs at a time. - ** a second loop below computes MACs for the remaining 1 to 3 samples. */ - while(k > 0u) - { - /* x[0] * y[srcBLen - 1] */ - sum += *px++ * *py--; - - /* x[1] * y[srcBLen - 2] */ - sum += *px++ * *py--; - - /* x[2] * y[srcBLen - 3] */ - sum += *px++ * *py--; - - /* x[3] * y[srcBLen - 4] */ - sum += *px++ * *py--; - - /* Decrement the loop counter */ - k--; - } - - /* If the count is not a multiple of 4, compute any remaining MACs here. - ** No loop unrolling is used. */ - k = count % 0x4u; - - while(k > 0u) - { - /* Perform the multiply-accumulate */ - sum += *px++ * *py--; - - /* Decrement the loop counter */ - k--; - } - - /* Store the result in the accumulator in the destination buffer. */ - *pOut++ = sum; - - /* Update the inputA and inputB pointers for next MAC calculation */ - py = pIn2 + count; - px = pIn1; - - /* Increment the MAC count */ - count++; - - /* Decrement the loop counter */ - blockSize1--; - } - - /* -------------------------- - * Initializations of stage2 - * ------------------------*/ - - /* sum = x[0] * y[srcBLen-1] + x[1] * y[srcBLen-2] +...+ x[srcBLen-1] * y[0] - * sum = x[1] * y[srcBLen-1] + x[2] * y[srcBLen-2] +...+ x[srcBLen] * y[0] - * .... - * sum = x[srcALen-srcBLen-2] * y[srcBLen-1] + x[srcALen] * y[srcBLen-2] +...+ x[srcALen-1] * y[0] - */ - - /* Working pointer of inputA */ - px = pIn1; - - /* Working pointer of inputB */ - pSrc2 = pIn2 + (srcBLen - 1u); - py = pSrc2; - - /* count is index by which the pointer pIn1 to be incremented */ - count = 0u; - - /* ------------------- - * Stage2 process - * ------------------*/ - - /* Stage2 depends on srcBLen as in this stage srcBLen number of MACS are performed. - * So, to loop unroll over blockSize2, - * srcBLen should be greater than or equal to 4 */ - if(srcBLen >= 4u) - { - /* Loop unroll over blockSize2, by 4 */ - blkCnt = blockSize2 >> 2u; - - while(blkCnt > 0u) - { - /* Set all accumulators to zero */ - acc0 = 0.0f; - acc1 = 0.0f; - acc2 = 0.0f; - acc3 = 0.0f; - - /* read x[0], x[1], x[2] samples */ - x0 = *(px++); - x1 = *(px++); - x2 = *(px++); - - /* Apply loop unrolling and compute 4 MACs simultaneously. */ - k = srcBLen >> 2u; - - /* First part of the processing with loop unrolling. Compute 4 MACs at a time. - ** a second loop below computes MACs for the remaining 1 to 3 samples. */ - do - { - /* Read y[srcBLen - 1] sample */ - c0 = *(py--); - - /* Read x[3] sample */ - x3 = *(px); - - /* Perform the multiply-accumulate */ - /* acc0 += x[0] * y[srcBLen - 1] */ - acc0 += x0 * c0; - - /* acc1 += x[1] * y[srcBLen - 1] */ - acc1 += x1 * c0; - - /* acc2 += x[2] * y[srcBLen - 1] */ - acc2 += x2 * c0; - - /* acc3 += x[3] * y[srcBLen - 1] */ - acc3 += x3 * c0; - - /* Read y[srcBLen - 2] sample */ - c0 = *(py--); - - /* Read x[4] sample */ - x0 = *(px + 1u); - - /* Perform the multiply-accumulate */ - /* acc0 += x[1] * y[srcBLen - 2] */ - acc0 += x1 * c0; - /* acc1 += x[2] * y[srcBLen - 2] */ - acc1 += x2 * c0; - /* acc2 += x[3] * y[srcBLen - 2] */ - acc2 += x3 * c0; - /* acc3 += x[4] * y[srcBLen - 2] */ - acc3 += x0 * c0; - - /* Read y[srcBLen - 3] sample */ - c0 = *(py--); - - /* Read x[5] sample */ - x1 = *(px + 2u); - - /* Perform the multiply-accumulates */ - /* acc0 += x[2] * y[srcBLen - 3] */ - acc0 += x2 * c0; - /* acc1 += x[3] * y[srcBLen - 2] */ - acc1 += x3 * c0; - /* acc2 += x[4] * y[srcBLen - 2] */ - acc2 += x0 * c0; - /* acc3 += x[5] * y[srcBLen - 2] */ - acc3 += x1 * c0; - - /* Read y[srcBLen - 4] sample */ - c0 = *(py--); - - /* Read x[6] sample */ - x2 = *(px + 3u); - px += 4u; - - /* Perform the multiply-accumulates */ - /* acc0 += x[3] * y[srcBLen - 4] */ - acc0 += x3 * c0; - /* acc1 += x[4] * y[srcBLen - 4] */ - acc1 += x0 * c0; - /* acc2 += x[5] * y[srcBLen - 4] */ - acc2 += x1 * c0; - /* acc3 += x[6] * y[srcBLen - 4] */ - acc3 += x2 * c0; - - - } while(--k); - - /* If the srcBLen is not a multiple of 4, compute any remaining MACs here. - ** No loop unrolling is used. */ - k = srcBLen % 0x4u; - - while(k > 0u) - { - /* Read y[srcBLen - 5] sample */ - c0 = *(py--); - - /* Read x[7] sample */ - x3 = *(px++); - - /* Perform the multiply-accumulates */ - /* acc0 += x[4] * y[srcBLen - 5] */ - acc0 += x0 * c0; - /* acc1 += x[5] * y[srcBLen - 5] */ - acc1 += x1 * c0; - /* acc2 += x[6] * y[srcBLen - 5] */ - acc2 += x2 * c0; - /* acc3 += x[7] * y[srcBLen - 5] */ - acc3 += x3 * c0; - - /* Reuse the present samples for the next MAC */ - x0 = x1; - x1 = x2; - x2 = x3; - - /* Decrement the loop counter */ - k--; - } - - /* Store the result in the accumulator in the destination buffer. */ - *pOut++ = acc0; - *pOut++ = acc1; - *pOut++ = acc2; - *pOut++ = acc3; - - /* Increment the pointer pIn1 index, count by 4 */ - count += 4u; - - /* Update the inputA and inputB pointers for next MAC calculation */ - px = pIn1 + count; - py = pSrc2; - - - /* Decrement the loop counter */ - blkCnt--; - } - - - /* If the blockSize2 is not a multiple of 4, compute any remaining output samples here. - ** No loop unrolling is used. */ - blkCnt = blockSize2 % 0x4u; - - while(blkCnt > 0u) - { - /* Accumulator is made zero for every iteration */ - sum = 0.0f; - - /* Apply loop unrolling and compute 4 MACs simultaneously. */ - k = srcBLen >> 2u; - - /* First part of the processing with loop unrolling. Compute 4 MACs at a time. - ** a second loop below computes MACs for the remaining 1 to 3 samples. */ - while(k > 0u) - { - /* Perform the multiply-accumulates */ - sum += *px++ * *py--; - sum += *px++ * *py--; - sum += *px++ * *py--; - sum += *px++ * *py--; - - /* Decrement the loop counter */ - k--; - } - - /* If the srcBLen is not a multiple of 4, compute any remaining MACs here. - ** No loop unrolling is used. */ - k = srcBLen % 0x4u; - - while(k > 0u) - { - /* Perform the multiply-accumulate */ - sum += *px++ * *py--; - - /* Decrement the loop counter */ - k--; - } - - /* Store the result in the accumulator in the destination buffer. */ - *pOut++ = sum; - - /* Increment the MAC count */ - count++; - - /* Update the inputA and inputB pointers for next MAC calculation */ - px = pIn1 + count; - py = pSrc2; - - /* Decrement the loop counter */ - blkCnt--; - } - } - else - { - /* If the srcBLen is not a multiple of 4, - * the blockSize2 loop cannot be unrolled by 4 */ - blkCnt = blockSize2; - - while(blkCnt > 0u) - { - /* Accumulator is made zero for every iteration */ - sum = 0.0f; - - /* srcBLen number of MACS should be performed */ - k = srcBLen; - - while(k > 0u) - { - /* Perform the multiply-accumulate */ - sum += *px++ * *py--; - - /* Decrement the loop counter */ - k--; - } - - /* Store the result in the accumulator in the destination buffer. */ - *pOut++ = sum; - - /* Increment the MAC count */ - count++; - - /* Update the inputA and inputB pointers for next MAC calculation */ - px = pIn1 + count; - py = pSrc2; - - /* Decrement the loop counter */ - blkCnt--; - } - } - - - /* -------------------------- - * Initializations of stage3 - * -------------------------*/ - - /* sum += x[srcALen-srcBLen+1] * y[srcBLen-1] + x[srcALen-srcBLen+2] * y[srcBLen-2] +...+ x[srcALen-1] * y[1] - * sum += x[srcALen-srcBLen+2] * y[srcBLen-1] + x[srcALen-srcBLen+3] * y[srcBLen-2] +...+ x[srcALen-1] * y[2] - * .... - * sum += x[srcALen-2] * y[srcBLen-1] + x[srcALen-1] * y[srcBLen-2] - * sum += x[srcALen-1] * y[srcBLen-1] - */ - - /* In this stage the MAC operations are decreased by 1 for every iteration. - The blockSize3 variable holds the number of MAC operations performed */ - - /* Working pointer of inputA */ - pSrc1 = (pIn1 + srcALen) - (srcBLen - 1u); - px = pSrc1; - - /* Working pointer of inputB */ - pSrc2 = pIn2 + (srcBLen - 1u); - py = pSrc2; - - /* ------------------- - * Stage3 process - * ------------------*/ - - while(blockSize3 > 0u) - { - /* Accumulator is made zero for every iteration */ - sum = 0.0f; - - /* Apply loop unrolling and compute 4 MACs simultaneously. */ - k = blockSize3 >> 2u; - - /* First part of the processing with loop unrolling. Compute 4 MACs at a time. - ** a second loop below computes MACs for the remaining 1 to 3 samples. */ - while(k > 0u) - { - /* sum += x[srcALen - srcBLen + 1] * y[srcBLen - 1] */ - sum += *px++ * *py--; - - /* sum += x[srcALen - srcBLen + 2] * y[srcBLen - 2] */ - sum += *px++ * *py--; - - /* sum += x[srcALen - srcBLen + 3] * y[srcBLen - 3] */ - sum += *px++ * *py--; - - /* sum += x[srcALen - srcBLen + 4] * y[srcBLen - 4] */ - sum += *px++ * *py--; - - /* Decrement the loop counter */ - k--; - } - - /* If the blockSize3 is not a multiple of 4, compute any remaining MACs here. - ** No loop unrolling is used. */ - k = blockSize3 % 0x4u; - - while(k > 0u) - { - /* Perform the multiply-accumulates */ - /* sum += x[srcALen-1] * y[srcBLen-1] */ - sum += *px++ * *py--; - - /* Decrement the loop counter */ - k--; - } - - /* Store the result in the accumulator in the destination buffer. */ - *pOut++ = sum; - - /* Update the inputA and inputB pointers for next MAC calculation */ - px = ++pSrc1; - py = pSrc2; - - /* Decrement the loop counter */ - blockSize3--; - } - -#else - - /* Run the below code for Cortex-M0 */ - - float32_t *pIn1 = pSrcA; /* inputA pointer */ - float32_t *pIn2 = pSrcB; /* inputB pointer */ - float32_t sum; /* Accumulator */ - uint32_t i, j; /* loop counters */ - - /* Loop to calculate convolution for output length number of times */ - for (i = 0u; i < ((srcALen + srcBLen) - 1u); i++) - { - /* Initialize sum with zero to carry out MAC operations */ - sum = 0.0f; - - /* Loop to perform MAC operations according to convolution equation */ - for (j = 0u; j <= i; j++) - { - /* Check the array limitations */ - if((((i - j) < srcBLen) && (j < srcALen))) - { - /* z[i] += x[i-j] * y[j] */ - sum += pIn1[j] * pIn2[i - j]; - } - } - /* Store the output in the destination buffer */ - pDst[i] = sum; - } - -#endif /* #ifndef ARM_MATH_CM0_FAMILY */ - -} - -/** - * @} end of Conv group - */ diff --git a/gui/cmsis/arm_conv_q15.c b/gui/cmsis/arm_conv_q15.c deleted file mode 100644 index 8454a94..0000000 --- a/gui/cmsis/arm_conv_q15.c +++ /dev/null @@ -1,734 +0,0 @@ -/* ---------------------------------------------------------------------- -* Copyright (C) 2010-2014 ARM Limited. All rights reserved. -* -* $Date: 19. March 2015 -* $Revision: V.1.4.5 -* -* Project: CMSIS DSP Library -* Title: arm_conv_q15.c -* -* Description: Convolution of Q15 sequences. -* -* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0 -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* - Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* - Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in -* the documentation and/or other materials provided with the -* distribution. -* - Neither the name of ARM LIMITED nor the names of its contributors -* may be used to endorse or promote products derived from this -* software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -* POSSIBILITY OF SUCH DAMAGE. -* -------------------------------------------------------------------- */ - -#include "arm_math.h" - -/** - * @ingroup groupFilters - */ - -/** - * @addtogroup Conv - * @{ - */ - -/** - * @brief Convolution of Q15 sequences. - * @param[in] *pSrcA points to the first input sequence. - * @param[in] srcALen length of the first input sequence. - * @param[in] *pSrcB points to the second input sequence. - * @param[in] srcBLen length of the second input sequence. - * @param[out] *pDst points to the location where the output result is written. Length srcALen+srcBLen-1. - * @return none. - * - * @details - * Scaling and Overflow Behavior: - * - * \par - * The function is implemented using a 64-bit internal accumulator. - * Both inputs are in 1.15 format and multiplications yield a 2.30 result. - * The 2.30 intermediate results are accumulated in a 64-bit accumulator in 34.30 format. - * This approach provides 33 guard bits and there is no risk of overflow. - * The 34.30 result is then truncated to 34.15 format by discarding the low 15 bits and then saturated to 1.15 format. - * - * \par - * Refer to arm_conv_fast_q15() for a faster but less precise version of this function for Cortex-M3 and Cortex-M4. - * - * \par - * Refer the function arm_conv_opt_q15() for a faster implementation of this function using scratch buffers. - * - */ - -void arm_conv_q15( - q15_t * pSrcA, - uint32_t srcALen, - q15_t * pSrcB, - uint32_t srcBLen, - q15_t * pDst) -{ - -#if (defined(ARM_MATH_CM4) || defined(ARM_MATH_CM3)) && !defined(UNALIGNED_SUPPORT_DISABLE) - - /* Run the below code for Cortex-M4 and Cortex-M3 */ - - q15_t *pIn1; /* inputA pointer */ - q15_t *pIn2; /* inputB pointer */ - q15_t *pOut = pDst; /* output pointer */ - q63_t sum, acc0, acc1, acc2, acc3; /* Accumulator */ - q15_t *px; /* Intermediate inputA pointer */ - q15_t *py; /* Intermediate inputB pointer */ - q15_t *pSrc1, *pSrc2; /* Intermediate pointers */ - q31_t x0, x1, x2, x3, c0; /* Temporary variables to hold state and coefficient values */ - uint32_t blockSize1, blockSize2, blockSize3, j, k, count, blkCnt; /* loop counter */ - - /* The algorithm implementation is based on the lengths of the inputs. */ - /* srcB is always made to slide across srcA. */ - /* So srcBLen is always considered as shorter or equal to srcALen */ - if(srcALen >= srcBLen) - { - /* Initialization of inputA pointer */ - pIn1 = pSrcA; - - /* Initialization of inputB pointer */ - pIn2 = pSrcB; - } - else - { - /* Initialization of inputA pointer */ - pIn1 = pSrcB; - - /* Initialization of inputB pointer */ - pIn2 = pSrcA; - - /* srcBLen is always considered as shorter or equal to srcALen */ - j = srcBLen; - srcBLen = srcALen; - srcALen = j; - } - - /* conv(x,y) at n = x[n] * y[0] + x[n-1] * y[1] + x[n-2] * y[2] + ...+ x[n-N+1] * y[N -1] */ - /* The function is internally - * divided into three stages according to the number of multiplications that has to be - * taken place between inputA samples and inputB samples. In the first stage of the - * algorithm, the multiplications increase by one for every iteration. - * In the second stage of the algorithm, srcBLen number of multiplications are done. - * In the third stage of the algorithm, the multiplications decrease by one - * for every iteration. */ - - /* The algorithm is implemented in three stages. - The loop counters of each stage is initiated here. */ - blockSize1 = srcBLen - 1u; - blockSize2 = srcALen - (srcBLen - 1u); - - /* -------------------------- - * Initializations of stage1 - * -------------------------*/ - - /* sum = x[0] * y[0] - * sum = x[0] * y[1] + x[1] * y[0] - * .... - * sum = x[0] * y[srcBlen - 1] + x[1] * y[srcBlen - 2] +...+ x[srcBLen - 1] * y[0] - */ - - /* In this stage the MAC operations are increased by 1 for every iteration. - The count variable holds the number of MAC operations performed */ - count = 1u; - - /* Working pointer of inputA */ - px = pIn1; - - /* Working pointer of inputB */ - py = pIn2; - - - /* ------------------------ - * Stage1 process - * ----------------------*/ - - /* For loop unrolling by 4, this stage is divided into two. */ - /* First part of this stage computes the MAC operations less than 4 */ - /* Second part of this stage computes the MAC operations greater than or equal to 4 */ - - /* The first part of the stage starts here */ - while((count < 4u) && (blockSize1 > 0u)) - { - /* Accumulator is made zero for every iteration */ - sum = 0; - - /* Loop over number of MAC operations between - * inputA samples and inputB samples */ - k = count; - - while(k > 0u) - { - /* Perform the multiply-accumulates */ - sum = __SMLALD(*px++, *py--, sum); - - /* Decrement the loop counter */ - k--; - } - - /* Store the result in the accumulator in the destination buffer. */ - *pOut++ = (q15_t) (__SSAT((sum >> 15), 16)); - - /* Update the inputA and inputB pointers for next MAC calculation */ - py = pIn2 + count; - px = pIn1; - - /* Increment the MAC count */ - count++; - - /* Decrement the loop counter */ - blockSize1--; - } - - /* The second part of the stage starts here */ - /* The internal loop, over count, is unrolled by 4 */ - /* To, read the last two inputB samples using SIMD: - * y[srcBLen] and y[srcBLen-1] coefficients, py is decremented by 1 */ - py = py - 1; - - while(blockSize1 > 0u) - { - /* Accumulator is made zero for every iteration */ - sum = 0; - - /* Apply loop unrolling and compute 4 MACs simultaneously. */ - k = count >> 2u; - - /* First part of the processing with loop unrolling. Compute 4 MACs at a time. - ** a second loop below computes MACs for the remaining 1 to 3 samples. */ - while(k > 0u) - { - /* Perform the multiply-accumulates */ - /* x[0], x[1] are multiplied with y[srcBLen - 1], y[srcBLen - 2] respectively */ - sum = __SMLALDX(*__SIMD32(px)++, *__SIMD32(py)--, sum); - /* x[2], x[3] are multiplied with y[srcBLen - 3], y[srcBLen - 4] respectively */ - sum = __SMLALDX(*__SIMD32(px)++, *__SIMD32(py)--, sum); - - /* Decrement the loop counter */ - k--; - } - - /* For the next MAC operations, the pointer py is used without SIMD - * So, py is incremented by 1 */ - py = py + 1u; - - /* If the count is not a multiple of 4, compute any remaining MACs here. - ** No loop unrolling is used. */ - k = count % 0x4u; - - while(k > 0u) - { - /* Perform the multiply-accumulates */ - sum = __SMLALD(*px++, *py--, sum); - - /* Decrement the loop counter */ - k--; - } - - /* Store the result in the accumulator in the destination buffer. */ - *pOut++ = (q15_t) (__SSAT((sum >> 15), 16)); - - /* Update the inputA and inputB pointers for next MAC calculation */ - py = pIn2 + (count - 1u); - px = pIn1; - - /* Increment the MAC count */ - count++; - - /* Decrement the loop counter */ - blockSize1--; - } - - /* -------------------------- - * Initializations of stage2 - * ------------------------*/ - - /* sum = x[0] * y[srcBLen-1] + x[1] * y[srcBLen-2] +...+ x[srcBLen-1] * y[0] - * sum = x[1] * y[srcBLen-1] + x[2] * y[srcBLen-2] +...+ x[srcBLen] * y[0] - * .... - * sum = x[srcALen-srcBLen-2] * y[srcBLen-1] + x[srcALen] * y[srcBLen-2] +...+ x[srcALen-1] * y[0] - */ - - /* Working pointer of inputA */ - px = pIn1; - - /* Working pointer of inputB */ - pSrc2 = pIn2 + (srcBLen - 1u); - py = pSrc2; - - /* count is the index by which the pointer pIn1 to be incremented */ - count = 0u; - - - /* -------------------- - * Stage2 process - * -------------------*/ - - /* Stage2 depends on srcBLen as in this stage srcBLen number of MACS are performed. - * So, to loop unroll over blockSize2, - * srcBLen should be greater than or equal to 4 */ - if(srcBLen >= 4u) - { - /* Loop unroll over blockSize2, by 4 */ - blkCnt = blockSize2 >> 2u; - - while(blkCnt > 0u) - { - py = py - 1u; - - /* Set all accumulators to zero */ - acc0 = 0; - acc1 = 0; - acc2 = 0; - acc3 = 0; - - - /* read x[0], x[1] samples */ - x0 = *__SIMD32(px); - /* read x[1], x[2] samples */ - x1 = _SIMD32_OFFSET(px+1); - px+= 2u; - - - /* Apply loop unrolling and compute 4 MACs simultaneously. */ - k = srcBLen >> 2u; - - /* First part of the processing with loop unrolling. Compute 4 MACs at a time. - ** a second loop below computes MACs for the remaining 1 to 3 samples. */ - do - { - /* Read the last two inputB samples using SIMD: - * y[srcBLen - 1] and y[srcBLen - 2] */ - c0 = *__SIMD32(py)--; - - /* acc0 += x[0] * y[srcBLen - 1] + x[1] * y[srcBLen - 2] */ - acc0 = __SMLALDX(x0, c0, acc0); - - /* acc1 += x[1] * y[srcBLen - 1] + x[2] * y[srcBLen - 2] */ - acc1 = __SMLALDX(x1, c0, acc1); - - /* Read x[2], x[3] */ - x2 = *__SIMD32(px); - - /* Read x[3], x[4] */ - x3 = _SIMD32_OFFSET(px+1); - - /* acc2 += x[2] * y[srcBLen - 1] + x[3] * y[srcBLen - 2] */ - acc2 = __SMLALDX(x2, c0, acc2); - - /* acc3 += x[3] * y[srcBLen - 1] + x[4] * y[srcBLen - 2] */ - acc3 = __SMLALDX(x3, c0, acc3); - - /* Read y[srcBLen - 3] and y[srcBLen - 4] */ - c0 = *__SIMD32(py)--; - - /* acc0 += x[2] * y[srcBLen - 3] + x[3] * y[srcBLen - 4] */ - acc0 = __SMLALDX(x2, c0, acc0); - - /* acc1 += x[3] * y[srcBLen - 3] + x[4] * y[srcBLen - 4] */ - acc1 = __SMLALDX(x3, c0, acc1); - - /* Read x[4], x[5] */ - x0 = _SIMD32_OFFSET(px+2); - - /* Read x[5], x[6] */ - x1 = _SIMD32_OFFSET(px+3); - px += 4u; - - /* acc2 += x[4] * y[srcBLen - 3] + x[5] * y[srcBLen - 4] */ - acc2 = __SMLALDX(x0, c0, acc2); - - /* acc3 += x[5] * y[srcBLen - 3] + x[6] * y[srcBLen - 4] */ - acc3 = __SMLALDX(x1, c0, acc3); - - } while(--k); - - /* For the next MAC operations, SIMD is not used - * So, the 16 bit pointer if inputB, py is updated */ - - /* If the srcBLen is not a multiple of 4, compute any remaining MACs here. - ** No loop unrolling is used. */ - k = srcBLen % 0x4u; - - if(k == 1u) - { - /* Read y[srcBLen - 5] */ - c0 = *(py+1); - -#ifdef ARM_MATH_BIG_ENDIAN - - c0 = c0 << 16u; - -#else - - c0 = c0 & 0x0000FFFF; - -#endif /* #ifdef ARM_MATH_BIG_ENDIAN */ - /* Read x[7] */ - x3 = *__SIMD32(px); - px++; - - /* Perform the multiply-accumulates */ - acc0 = __SMLALD(x0, c0, acc0); - acc1 = __SMLALD(x1, c0, acc1); - acc2 = __SMLALDX(x1, c0, acc2); - acc3 = __SMLALDX(x3, c0, acc3); - } - - if(k == 2u) - { - /* Read y[srcBLen - 5], y[srcBLen - 6] */ - c0 = _SIMD32_OFFSET(py); - - /* Read x[7], x[8] */ - x3 = *__SIMD32(px); - - /* Read x[9] */ - x2 = _SIMD32_OFFSET(px+1); - px += 2u; - - /* Perform the multiply-accumulates */ - acc0 = __SMLALDX(x0, c0, acc0); - acc1 = __SMLALDX(x1, c0, acc1); - acc2 = __SMLALDX(x3, c0, acc2); - acc3 = __SMLALDX(x2, c0, acc3); - } - - if(k == 3u) - { - /* Read y[srcBLen - 5], y[srcBLen - 6] */ - c0 = _SIMD32_OFFSET(py); - - /* Read x[7], x[8] */ - x3 = *__SIMD32(px); - - /* Read x[9] */ - x2 = _SIMD32_OFFSET(px+1); - - /* Perform the multiply-accumulates */ - acc0 = __SMLALDX(x0, c0, acc0); - acc1 = __SMLALDX(x1, c0, acc1); - acc2 = __SMLALDX(x3, c0, acc2); - acc3 = __SMLALDX(x2, c0, acc3); - - c0 = *(py-1); - -#ifdef ARM_MATH_BIG_ENDIAN - - c0 = c0 << 16u; -#else - - c0 = c0 & 0x0000FFFF; -#endif /* #ifdef ARM_MATH_BIG_ENDIAN */ - /* Read x[10] */ - x3 = _SIMD32_OFFSET(px+2); - px += 3u; - - /* Perform the multiply-accumulates */ - acc0 = __SMLALDX(x1, c0, acc0); - acc1 = __SMLALD(x2, c0, acc1); - acc2 = __SMLALDX(x2, c0, acc2); - acc3 = __SMLALDX(x3, c0, acc3); - } - - - /* Store the results in the accumulators in the destination buffer. */ - -#ifndef ARM_MATH_BIG_ENDIAN - - *__SIMD32(pOut)++ = - __PKHBT(__SSAT((acc0 >> 15), 16), __SSAT((acc1 >> 15), 16), 16); - *__SIMD32(pOut)++ = - __PKHBT(__SSAT((acc2 >> 15), 16), __SSAT((acc3 >> 15), 16), 16); - -#else - - *__SIMD32(pOut)++ = - __PKHBT(__SSAT((acc1 >> 15), 16), __SSAT((acc0 >> 15), 16), 16); - *__SIMD32(pOut)++ = - __PKHBT(__SSAT((acc3 >> 15), 16), __SSAT((acc2 >> 15), 16), 16); - -#endif /* #ifndef ARM_MATH_BIG_ENDIAN */ - - /* Increment the pointer pIn1 index, count by 4 */ - count += 4u; - - /* Update the inputA and inputB pointers for next MAC calculation */ - px = pIn1 + count; - py = pSrc2; - - /* Decrement the loop counter */ - blkCnt--; - } - - /* If the blockSize2 is not a multiple of 4, compute any remaining output samples here. - ** No loop unrolling is used. */ - blkCnt = blockSize2 % 0x4u; - - while(blkCnt > 0u) - { - /* Accumulator is made zero for every iteration */ - sum = 0; - - /* Apply loop unrolling and compute 4 MACs simultaneously. */ - k = srcBLen >> 2u; - - /* First part of the processing with loop unrolling. Compute 4 MACs at a time. - ** a second loop below computes MACs for the remaining 1 to 3 samples. */ - while(k > 0u) - { - /* Perform the multiply-accumulates */ - sum += (q63_t) ((q31_t) * px++ * *py--); - sum += (q63_t) ((q31_t) * px++ * *py--); - sum += (q63_t) ((q31_t) * px++ * *py--); - sum += (q63_t) ((q31_t) * px++ * *py--); - - /* Decrement the loop counter */ - k--; - } - - /* If the srcBLen is not a multiple of 4, compute any remaining MACs here. - ** No loop unrolling is used. */ - k = srcBLen % 0x4u; - - while(k > 0u) - { - /* Perform the multiply-accumulates */ - sum += (q63_t) ((q31_t) * px++ * *py--); - - /* Decrement the loop counter */ - k--; - } - - /* Store the result in the accumulator in the destination buffer. */ - *pOut++ = (q15_t) (__SSAT(sum >> 15, 16)); - - /* Increment the pointer pIn1 index, count by 1 */ - count++; - - /* Update the inputA and inputB pointers for next MAC calculation */ - px = pIn1 + count; - py = pSrc2; - - /* Decrement the loop counter */ - blkCnt--; - } - } - else - { - /* If the srcBLen is not a multiple of 4, - * the blockSize2 loop cannot be unrolled by 4 */ - blkCnt = blockSize2; - - while(blkCnt > 0u) - { - /* Accumulator is made zero for every iteration */ - sum = 0; - - /* srcBLen number of MACS should be performed */ - k = srcBLen; - - while(k > 0u) - { - /* Perform the multiply-accumulate */ - sum += (q63_t) ((q31_t) * px++ * *py--); - - /* Decrement the loop counter */ - k--; - } - - /* Store the result in the accumulator in the destination buffer. */ - *pOut++ = (q15_t) (__SSAT(sum >> 15, 16)); - - /* Increment the MAC count */ - count++; - - /* Update the inputA and inputB pointers for next MAC calculation */ - px = pIn1 + count; - py = pSrc2; - - /* Decrement the loop counter */ - blkCnt--; - } - } - - - /* -------------------------- - * Initializations of stage3 - * -------------------------*/ - - /* sum += x[srcALen-srcBLen+1] * y[srcBLen-1] + x[srcALen-srcBLen+2] * y[srcBLen-2] +...+ x[srcALen-1] * y[1] - * sum += x[srcALen-srcBLen+2] * y[srcBLen-1] + x[srcALen-srcBLen+3] * y[srcBLen-2] +...+ x[srcALen-1] * y[2] - * .... - * sum += x[srcALen-2] * y[srcBLen-1] + x[srcALen-1] * y[srcBLen-2] - * sum += x[srcALen-1] * y[srcBLen-1] - */ - - /* In this stage the MAC operations are decreased by 1 for every iteration. - The blockSize3 variable holds the number of MAC operations performed */ - - blockSize3 = srcBLen - 1u; - - /* Working pointer of inputA */ - pSrc1 = (pIn1 + srcALen) - (srcBLen - 1u); - px = pSrc1; - - /* Working pointer of inputB */ - pSrc2 = pIn2 + (srcBLen - 1u); - pIn2 = pSrc2 - 1u; - py = pIn2; - - /* ------------------- - * Stage3 process - * ------------------*/ - - /* For loop unrolling by 4, this stage is divided into two. */ - /* First part of this stage computes the MAC operations greater than 4 */ - /* Second part of this stage computes the MAC operations less than or equal to 4 */ - - /* The first part of the stage starts here */ - j = blockSize3 >> 2u; - - while((j > 0u) && (blockSize3 > 0u)) - { - /* Accumulator is made zero for every iteration */ - sum = 0; - - /* Apply loop unrolling and compute 4 MACs simultaneously. */ - k = blockSize3 >> 2u; - - /* First part of the processing with loop unrolling. Compute 4 MACs at a time. - ** a second loop below computes MACs for the remaining 1 to 3 samples. */ - while(k > 0u) - { - /* x[srcALen - srcBLen + 1], x[srcALen - srcBLen + 2] are multiplied - * with y[srcBLen - 1], y[srcBLen - 2] respectively */ - sum = __SMLALDX(*__SIMD32(px)++, *__SIMD32(py)--, sum); - /* x[srcALen - srcBLen + 3], x[srcALen - srcBLen + 4] are multiplied - * with y[srcBLen - 3], y[srcBLen - 4] respectively */ - sum = __SMLALDX(*__SIMD32(px)++, *__SIMD32(py)--, sum); - - /* Decrement the loop counter */ - k--; - } - - /* For the next MAC operations, the pointer py is used without SIMD - * So, py is incremented by 1 */ - py = py + 1u; - - /* If the blockSize3 is not a multiple of 4, compute any remaining MACs here. - ** No loop unrolling is used. */ - k = blockSize3 % 0x4u; - - while(k > 0u) - { - /* sum += x[srcALen - srcBLen + 5] * y[srcBLen - 5] */ - sum = __SMLALD(*px++, *py--, sum); - - /* Decrement the loop counter */ - k--; - } - - /* Store the result in the accumulator in the destination buffer. */ - *pOut++ = (q15_t) (__SSAT((sum >> 15), 16)); - - /* Update the inputA and inputB pointers for next MAC calculation */ - px = ++pSrc1; - py = pIn2; - - /* Decrement the loop counter */ - blockSize3--; - - j--; - } - - /* The second part of the stage starts here */ - /* SIMD is not used for the next MAC operations, - * so pointer py is updated to read only one sample at a time */ - py = py + 1u; - - while(blockSize3 > 0u) - { - /* Accumulator is made zero for every iteration */ - sum = 0; - - /* Apply loop unrolling and compute 4 MACs simultaneously. */ - k = blockSize3; - - while(k > 0u) - { - /* Perform the multiply-accumulates */ - /* sum += x[srcALen-1] * y[srcBLen-1] */ - sum = __SMLALD(*px++, *py--, sum); - - /* Decrement the loop counter */ - k--; - } - - /* Store the result in the accumulator in the destination buffer. */ - *pOut++ = (q15_t) (__SSAT((sum >> 15), 16)); - - /* Update the inputA and inputB pointers for next MAC calculation */ - px = ++pSrc1; - py = pSrc2; - - /* Decrement the loop counter */ - blockSize3--; - } - -#else - -/* Run the below code for Cortex-M0 */ - - q15_t *pIn1 = pSrcA; /* input pointer */ - q15_t *pIn2 = pSrcB; /* coefficient pointer */ - q63_t sum; /* Accumulator */ - uint32_t i, j; /* loop counter */ - - /* Loop to calculate output of convolution for output length number of times */ - for (i = 0; i < (srcALen + srcBLen - 1); i++) - { - /* Initialize sum with zero to carry on MAC operations */ - sum = 0; - - /* Loop to perform MAC operations according to convolution equation */ - for (j = 0; j <= i; j++) - { - /* Check the array limitations */ - if(((i - j) < srcBLen) && (j < srcALen)) - { - /* z[i] += x[i-j] * y[j] */ - sum += (q31_t) pIn1[j] * (pIn2[i - j]); - } - } - - /* Store the output in the destination buffer */ - pDst[i] = (q15_t) __SSAT((sum >> 15u), 16u); - } - -#endif /* #if (defined(ARM_MATH_CM4) || defined(ARM_MATH_CM3)) && !defined(UNALIGNED_SUPPORT_DISABLE)*/ - -} - -/** - * @} end of Conv group - */ diff --git a/gui/cmsis/arm_conv_q31.c b/gui/cmsis/arm_conv_q31.c deleted file mode 100644 index ffa972f..0000000 --- a/gui/cmsis/arm_conv_q31.c +++ /dev/null @@ -1,565 +0,0 @@ -/* ---------------------------------------------------------------------- -* Copyright (C) 2010-2014 ARM Limited. All rights reserved. -* -* $Date: 19. March 2015 -* $Revision: V.1.4.5 -* -* Project: CMSIS DSP Library -* Title: arm_conv_q31.c -* -* Description: Convolution of Q31 sequences. -* -* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0 -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* - Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* - Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in -* the documentation and/or other materials provided with the -* distribution. -* - Neither the name of ARM LIMITED nor the names of its contributors -* may be used to endorse or promote products derived from this -* software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -* POSSIBILITY OF SUCH DAMAGE. -* -------------------------------------------------------------------- */ - -#include "arm_math.h" - -/** - * @ingroup groupFilters - */ - -/** - * @addtogroup Conv - * @{ - */ - -/** - * @brief Convolution of Q31 sequences. - * @param[in] *pSrcA points to the first input sequence. - * @param[in] srcALen length of the first input sequence. - * @param[in] *pSrcB points to the second input sequence. - * @param[in] srcBLen length of the second input sequence. - * @param[out] *pDst points to the location where the output result is written. Length srcALen+srcBLen-1. - * @return none. - * - * @details - * Scaling and Overflow Behavior: - * - * \par - * The function is implemented using an internal 64-bit accumulator. - * The accumulator has a 2.62 format and maintains full precision of the intermediate multiplication results but provides only a single guard bit. - * There is no saturation on intermediate additions. - * Thus, if the accumulator overflows it wraps around and distorts the result. - * The input signals should be scaled down to avoid intermediate overflows. - * Scale down the inputs by log2(min(srcALen, srcBLen)) (log2 is read as log to the base 2) times to avoid overflows, - * as maximum of min(srcALen, srcBLen) number of additions are carried internally. - * The 2.62 accumulator is right shifted by 31 bits and saturated to 1.31 format to yield the final result. - * - * \par - * See arm_conv_fast_q31() for a faster but less precise implementation of this function for Cortex-M3 and Cortex-M4. - */ - -void arm_conv_q31( - q31_t * pSrcA, - uint32_t srcALen, - q31_t * pSrcB, - uint32_t srcBLen, - q31_t * pDst) -{ - - -#ifndef ARM_MATH_CM0_FAMILY - - /* Run the below code for Cortex-M4 and Cortex-M3 */ - - q31_t *pIn1; /* inputA pointer */ - q31_t *pIn2; /* inputB pointer */ - q31_t *pOut = pDst; /* output pointer */ - q31_t *px; /* Intermediate inputA pointer */ - q31_t *py; /* Intermediate inputB pointer */ - q31_t *pSrc1, *pSrc2; /* Intermediate pointers */ - q63_t sum; /* Accumulator */ - q63_t acc0, acc1, acc2; /* Accumulator */ - q31_t x0, x1, x2, c0; /* Temporary variables to hold state and coefficient values */ - uint32_t j, k, count, blkCnt, blockSize1, blockSize2, blockSize3; /* loop counter */ - - /* The algorithm implementation is based on the lengths of the inputs. */ - /* srcB is always made to slide across srcA. */ - /* So srcBLen is always considered as shorter or equal to srcALen */ - if(srcALen >= srcBLen) - { - /* Initialization of inputA pointer */ - pIn1 = pSrcA; - - /* Initialization of inputB pointer */ - pIn2 = pSrcB; - } - else - { - /* Initialization of inputA pointer */ - pIn1 = (q31_t *) pSrcB; - - /* Initialization of inputB pointer */ - pIn2 = (q31_t *) pSrcA; - - /* srcBLen is always considered as shorter or equal to srcALen */ - j = srcBLen; - srcBLen = srcALen; - srcALen = j; - } - - /* conv(x,y) at n = x[n] * y[0] + x[n-1] * y[1] + x[n-2] * y[2] + ...+ x[n-N+1] * y[N -1] */ - /* The function is internally - * divided into three stages according to the number of multiplications that has to be - * taken place between inputA samples and inputB samples. In the first stage of the - * algorithm, the multiplications increase by one for every iteration. - * In the second stage of the algorithm, srcBLen number of multiplications are done. - * In the third stage of the algorithm, the multiplications decrease by one - * for every iteration. */ - - /* The algorithm is implemented in three stages. - The loop counters of each stage is initiated here. */ - blockSize1 = srcBLen - 1u; - blockSize2 = srcALen - (srcBLen - 1u); - blockSize3 = blockSize1; - - /* -------------------------- - * Initializations of stage1 - * -------------------------*/ - - /* sum = x[0] * y[0] - * sum = x[0] * y[1] + x[1] * y[0] - * .... - * sum = x[0] * y[srcBlen - 1] + x[1] * y[srcBlen - 2] +...+ x[srcBLen - 1] * y[0] - */ - - /* In this stage the MAC operations are increased by 1 for every iteration. - The count variable holds the number of MAC operations performed */ - count = 1u; - - /* Working pointer of inputA */ - px = pIn1; - - /* Working pointer of inputB */ - py = pIn2; - - - /* ------------------------ - * Stage1 process - * ----------------------*/ - - /* The first stage starts here */ - while(blockSize1 > 0u) - { - /* Accumulator is made zero for every iteration */ - sum = 0; - - /* Apply loop unrolling and compute 4 MACs simultaneously. */ - k = count >> 2u; - - /* First part of the processing with loop unrolling. Compute 4 MACs at a time. - ** a second loop below computes MACs for the remaining 1 to 3 samples. */ - while(k > 0u) - { - /* x[0] * y[srcBLen - 1] */ - sum += (q63_t) * px++ * (*py--); - /* x[1] * y[srcBLen - 2] */ - sum += (q63_t) * px++ * (*py--); - /* x[2] * y[srcBLen - 3] */ - sum += (q63_t) * px++ * (*py--); - /* x[3] * y[srcBLen - 4] */ - sum += (q63_t) * px++ * (*py--); - - /* Decrement the loop counter */ - k--; - } - - /* If the count is not a multiple of 4, compute any remaining MACs here. - ** No loop unrolling is used. */ - k = count % 0x4u; - - while(k > 0u) - { - /* Perform the multiply-accumulate */ - sum += (q63_t) * px++ * (*py--); - - /* Decrement the loop counter */ - k--; - } - - /* Store the result in the accumulator in the destination buffer. */ - *pOut++ = (q31_t) (sum >> 31); - - /* Update the inputA and inputB pointers for next MAC calculation */ - py = pIn2 + count; - px = pIn1; - - /* Increment the MAC count */ - count++; - - /* Decrement the loop counter */ - blockSize1--; - } - - /* -------------------------- - * Initializations of stage2 - * ------------------------*/ - - /* sum = x[0] * y[srcBLen-1] + x[1] * y[srcBLen-2] +...+ x[srcBLen-1] * y[0] - * sum = x[1] * y[srcBLen-1] + x[2] * y[srcBLen-2] +...+ x[srcBLen] * y[0] - * .... - * sum = x[srcALen-srcBLen-2] * y[srcBLen-1] + x[srcALen] * y[srcBLen-2] +...+ x[srcALen-1] * y[0] - */ - - /* Working pointer of inputA */ - px = pIn1; - - /* Working pointer of inputB */ - pSrc2 = pIn2 + (srcBLen - 1u); - py = pSrc2; - - /* count is index by which the pointer pIn1 to be incremented */ - count = 0u; - - /* ------------------- - * Stage2 process - * ------------------*/ - - /* Stage2 depends on srcBLen as in this stage srcBLen number of MACS are performed. - * So, to loop unroll over blockSize2, - * srcBLen should be greater than or equal to 4 */ - if(srcBLen >= 4u) - { - /* Loop unroll by 3 */ - blkCnt = blockSize2 / 3; - - while(blkCnt > 0u) - { - /* Set all accumulators to zero */ - acc0 = 0; - acc1 = 0; - acc2 = 0; - - /* read x[0], x[1], x[2] samples */ - x0 = *(px++); - x1 = *(px++); - - /* Apply loop unrolling and compute 3 MACs simultaneously. */ - k = srcBLen / 3; - - /* First part of the processing with loop unrolling. Compute 3 MACs at a time. - ** a second loop below computes MACs for the remaining 1 to 2 samples. */ - do - { - /* Read y[srcBLen - 1] sample */ - c0 = *(py); - - /* Read x[3] sample */ - x2 = *(px); - - /* Perform the multiply-accumulates */ - /* acc0 += x[0] * y[srcBLen - 1] */ - acc0 += ((q63_t) x0 * c0); - /* acc1 += x[1] * y[srcBLen - 1] */ - acc1 += ((q63_t) x1 * c0); - /* acc2 += x[2] * y[srcBLen - 1] */ - acc2 += ((q63_t) x2 * c0); - - /* Read y[srcBLen - 2] sample */ - c0 = *(py - 1u); - - /* Read x[4] sample */ - x0 = *(px + 1u); - - /* Perform the multiply-accumulate */ - /* acc0 += x[1] * y[srcBLen - 2] */ - acc0 += ((q63_t) x1 * c0); - /* acc1 += x[2] * y[srcBLen - 2] */ - acc1 += ((q63_t) x2 * c0); - /* acc2 += x[3] * y[srcBLen - 2] */ - acc2 += ((q63_t) x0 * c0); - - /* Read y[srcBLen - 3] sample */ - c0 = *(py - 2u); - - /* Read x[5] sample */ - x1 = *(px + 2u); - - /* Perform the multiply-accumulates */ - /* acc0 += x[2] * y[srcBLen - 3] */ - acc0 += ((q63_t) x2 * c0); - /* acc1 += x[3] * y[srcBLen - 2] */ - acc1 += ((q63_t) x0 * c0); - /* acc2 += x[4] * y[srcBLen - 2] */ - acc2 += ((q63_t) x1 * c0); - - /* update scratch pointers */ - px += 3u; - py -= 3u; - - } while(--k); - - /* If the srcBLen is not a multiple of 3, compute any remaining MACs here. - ** No loop unrolling is used. */ - k = srcBLen - (3 * (srcBLen / 3)); - - while(k > 0u) - { - /* Read y[srcBLen - 5] sample */ - c0 = *(py--); - - /* Read x[7] sample */ - x2 = *(px++); - - /* Perform the multiply-accumulates */ - /* acc0 += x[4] * y[srcBLen - 5] */ - acc0 += ((q63_t) x0 * c0); - /* acc1 += x[5] * y[srcBLen - 5] */ - acc1 += ((q63_t) x1 * c0); - /* acc2 += x[6] * y[srcBLen - 5] */ - acc2 += ((q63_t) x2 * c0); - - /* Reuse the present samples for the next MAC */ - x0 = x1; - x1 = x2; - - /* Decrement the loop counter */ - k--; - } - - /* Store the results in the accumulators in the destination buffer. */ - *pOut++ = (q31_t) (acc0 >> 31); - *pOut++ = (q31_t) (acc1 >> 31); - *pOut++ = (q31_t) (acc2 >> 31); - - /* Increment the pointer pIn1 index, count by 3 */ - count += 3u; - - /* Update the inputA and inputB pointers for next MAC calculation */ - px = pIn1 + count; - py = pSrc2; - - /* Decrement the loop counter */ - blkCnt--; - } - - /* If the blockSize2 is not a multiple of 3, compute any remaining output samples here. - ** No loop unrolling is used. */ - blkCnt = blockSize2 - 3 * (blockSize2 / 3); - - while(blkCnt > 0u) - { - /* Accumulator is made zero for every iteration */ - sum = 0; - - /* Apply loop unrolling and compute 4 MACs simultaneously. */ - k = srcBLen >> 2u; - - /* First part of the processing with loop unrolling. Compute 4 MACs at a time. - ** a second loop below computes MACs for the remaining 1 to 3 samples. */ - while(k > 0u) - { - /* Perform the multiply-accumulates */ - sum += (q63_t) * px++ * (*py--); - sum += (q63_t) * px++ * (*py--); - sum += (q63_t) * px++ * (*py--); - sum += (q63_t) * px++ * (*py--); - - /* Decrement the loop counter */ - k--; - } - - /* If the srcBLen is not a multiple of 4, compute any remaining MACs here. - ** No loop unrolling is used. */ - k = srcBLen % 0x4u; - - while(k > 0u) - { - /* Perform the multiply-accumulate */ - sum += (q63_t) * px++ * (*py--); - - /* Decrement the loop counter */ - k--; - } - - /* Store the result in the accumulator in the destination buffer. */ - *pOut++ = (q31_t) (sum >> 31); - - /* Increment the MAC count */ - count++; - - /* Update the inputA and inputB pointers for next MAC calculation */ - px = pIn1 + count; - py = pSrc2; - - /* Decrement the loop counter */ - blkCnt--; - } - } - else - { - /* If the srcBLen is not a multiple of 4, - * the blockSize2 loop cannot be unrolled by 4 */ - blkCnt = blockSize2; - - while(blkCnt > 0u) - { - /* Accumulator is made zero for every iteration */ - sum = 0; - - /* srcBLen number of MACS should be performed */ - k = srcBLen; - - while(k > 0u) - { - /* Perform the multiply-accumulate */ - sum += (q63_t) * px++ * (*py--); - - /* Decrement the loop counter */ - k--; - } - - /* Store the result in the accumulator in the destination buffer. */ - *pOut++ = (q31_t) (sum >> 31); - - /* Increment the MAC count */ - count++; - - /* Update the inputA and inputB pointers for next MAC calculation */ - px = pIn1 + count; - py = pSrc2; - - /* Decrement the loop counter */ - blkCnt--; - } - } - - - /* -------------------------- - * Initializations of stage3 - * -------------------------*/ - - /* sum += x[srcALen-srcBLen+1] * y[srcBLen-1] + x[srcALen-srcBLen+2] * y[srcBLen-2] +...+ x[srcALen-1] * y[1] - * sum += x[srcALen-srcBLen+2] * y[srcBLen-1] + x[srcALen-srcBLen+3] * y[srcBLen-2] +...+ x[srcALen-1] * y[2] - * .... - * sum += x[srcALen-2] * y[srcBLen-1] + x[srcALen-1] * y[srcBLen-2] - * sum += x[srcALen-1] * y[srcBLen-1] - */ - - /* In this stage the MAC operations are decreased by 1 for every iteration. - The blockSize3 variable holds the number of MAC operations performed */ - - /* Working pointer of inputA */ - pSrc1 = (pIn1 + srcALen) - (srcBLen - 1u); - px = pSrc1; - - /* Working pointer of inputB */ - pSrc2 = pIn2 + (srcBLen - 1u); - py = pSrc2; - - /* ------------------- - * Stage3 process - * ------------------*/ - - while(blockSize3 > 0u) - { - /* Accumulator is made zero for every iteration */ - sum = 0; - - /* Apply loop unrolling and compute 4 MACs simultaneously. */ - k = blockSize3 >> 2u; - - /* First part of the processing with loop unrolling. Compute 4 MACs at a time. - ** a second loop below computes MACs for the remaining 1 to 3 samples. */ - while(k > 0u) - { - /* sum += x[srcALen - srcBLen + 1] * y[srcBLen - 1] */ - sum += (q63_t) * px++ * (*py--); - /* sum += x[srcALen - srcBLen + 2] * y[srcBLen - 2] */ - sum += (q63_t) * px++ * (*py--); - /* sum += x[srcALen - srcBLen + 3] * y[srcBLen - 3] */ - sum += (q63_t) * px++ * (*py--); - /* sum += x[srcALen - srcBLen + 4] * y[srcBLen - 4] */ - sum += (q63_t) * px++ * (*py--); - - /* Decrement the loop counter */ - k--; - } - - /* If the blockSize3 is not a multiple of 4, compute any remaining MACs here. - ** No loop unrolling is used. */ - k = blockSize3 % 0x4u; - - while(k > 0u) - { - /* Perform the multiply-accumulate */ - sum += (q63_t) * px++ * (*py--); - - /* Decrement the loop counter */ - k--; - } - - /* Store the result in the accumulator in the destination buffer. */ - *pOut++ = (q31_t) (sum >> 31); - - /* Update the inputA and inputB pointers for next MAC calculation */ - px = ++pSrc1; - py = pSrc2; - - /* Decrement the loop counter */ - blockSize3--; - } - -#else - - /* Run the below code for Cortex-M0 */ - - q31_t *pIn1 = pSrcA; /* input pointer */ - q31_t *pIn2 = pSrcB; /* coefficient pointer */ - q63_t sum; /* Accumulator */ - uint32_t i, j; /* loop counter */ - - /* Loop to calculate output of convolution for output length number of times */ - for (i = 0; i < (srcALen + srcBLen - 1); i++) - { - /* Initialize sum with zero to carry on MAC operations */ - sum = 0; - - /* Loop to perform MAC operations according to convolution equation */ - for (j = 0; j <= i; j++) - { - /* Check the array limitations */ - if(((i - j) < srcBLen) && (j < srcALen)) - { - /* z[i] += x[i-j] * y[j] */ - sum += ((q63_t) pIn1[j] * (pIn2[i - j])); - } - } - - /* Store the output in the destination buffer */ - pDst[i] = (q31_t) (sum >> 31u); - } - -#endif /* #ifndef ARM_MATH_CM0_FAMILY */ - -} - -/** - * @} end of Conv group - */ diff --git a/gui/cmsis/arm_conv_q7.c b/gui/cmsis/arm_conv_q7.c deleted file mode 100644 index 79b08fc..0000000 --- a/gui/cmsis/arm_conv_q7.c +++ /dev/null @@ -1,690 +0,0 @@ -/* ---------------------------------------------------------------------- -* Copyright (C) 2010-2014 ARM Limited. All rights reserved. -* -* $Date: 19. March 2015 -* $Revision: V.1.4.5 -* -* Project: CMSIS DSP Library -* Title: arm_conv_q7.c -* -* Description: Convolution of Q7 sequences. -* -* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0 -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* - Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* - Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in -* the documentation and/or other materials provided with the -* distribution. -* - Neither the name of ARM LIMITED nor the names of its contributors -* may be used to endorse or promote products derived from this -* software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -* POSSIBILITY OF SUCH DAMAGE. -* -------------------------------------------------------------------- */ - -#include "arm_math.h" - -/** - * @ingroup groupFilters - */ - -/** - * @addtogroup Conv - * @{ - */ - -/** - * @brief Convolution of Q7 sequences. - * @param[in] *pSrcA points to the first input sequence. - * @param[in] srcALen length of the first input sequence. - * @param[in] *pSrcB points to the second input sequence. - * @param[in] srcBLen length of the second input sequence. - * @param[out] *pDst points to the location where the output result is written. Length srcALen+srcBLen-1. - * @return none. - * - * @details - * Scaling and Overflow Behavior: - * - * \par - * The function is implemented using a 32-bit internal accumulator. - * Both the inputs are represented in 1.7 format and multiplications yield a 2.14 result. - * The 2.14 intermediate results are accumulated in a 32-bit accumulator in 18.14 format. - * This approach provides 17 guard bits and there is no risk of overflow as long as max(srcALen, srcBLen)<131072. - * The 18.14 result is then truncated to 18.7 format by discarding the low 7 bits and then saturated to 1.7 format. - * - * \par - * Refer the function arm_conv_opt_q7() for a faster implementation of this function. - * - */ - -void arm_conv_q7( - q7_t * pSrcA, - uint32_t srcALen, - q7_t * pSrcB, - uint32_t srcBLen, - q7_t * pDst) -{ - - -#ifndef ARM_MATH_CM0_FAMILY - - /* Run the below code for Cortex-M4 and Cortex-M3 */ - - q7_t *pIn1; /* inputA pointer */ - q7_t *pIn2; /* inputB pointer */ - q7_t *pOut = pDst; /* output pointer */ - q7_t *px; /* Intermediate inputA pointer */ - q7_t *py; /* Intermediate inputB pointer */ - q7_t *pSrc1, *pSrc2; /* Intermediate pointers */ - q7_t x0, x1, x2, x3, c0, c1; /* Temporary variables to hold state and coefficient values */ - q31_t sum, acc0, acc1, acc2, acc3; /* Accumulator */ - q31_t input1, input2; /* Temporary input variables */ - q15_t in1, in2; /* Temporary input variables */ - uint32_t j, k, count, blkCnt, blockSize1, blockSize2, blockSize3; /* loop counter */ - - /* The algorithm implementation is based on the lengths of the inputs. */ - /* srcB is always made to slide across srcA. */ - /* So srcBLen is always considered as shorter or equal to srcALen */ - if(srcALen >= srcBLen) - { - /* Initialization of inputA pointer */ - pIn1 = pSrcA; - - /* Initialization of inputB pointer */ - pIn2 = pSrcB; - } - else - { - /* Initialization of inputA pointer */ - pIn1 = pSrcB; - - /* Initialization of inputB pointer */ - pIn2 = pSrcA; - - /* srcBLen is always considered as shorter or equal to srcALen */ - j = srcBLen; - srcBLen = srcALen; - srcALen = j; - } - - /* conv(x,y) at n = x[n] * y[0] + x[n-1] * y[1] + x[n-2] * y[2] + ...+ x[n-N+1] * y[N -1] */ - /* The function is internally - * divided into three stages according to the number of multiplications that has to be - * taken place between inputA samples and inputB samples. In the first stage of the - * algorithm, the multiplications increase by one for every iteration. - * In the second stage of the algorithm, srcBLen number of multiplications are done. - * In the third stage of the algorithm, the multiplications decrease by one - * for every iteration. */ - - /* The algorithm is implemented in three stages. - The loop counters of each stage is initiated here. */ - blockSize1 = srcBLen - 1u; - blockSize2 = (srcALen - srcBLen) + 1u; - blockSize3 = blockSize1; - - /* -------------------------- - * Initializations of stage1 - * -------------------------*/ - - /* sum = x[0] * y[0] - * sum = x[0] * y[1] + x[1] * y[0] - * .... - * sum = x[0] * y[srcBlen - 1] + x[1] * y[srcBlen - 2] +...+ x[srcBLen - 1] * y[0] - */ - - /* In this stage the MAC operations are increased by 1 for every iteration. - The count variable holds the number of MAC operations performed */ - count = 1u; - - /* Working pointer of inputA */ - px = pIn1; - - /* Working pointer of inputB */ - py = pIn2; - - - /* ------------------------ - * Stage1 process - * ----------------------*/ - - /* The first stage starts here */ - while(blockSize1 > 0u) - { - /* Accumulator is made zero for every iteration */ - sum = 0; - - /* Apply loop unrolling and compute 4 MACs simultaneously. */ - k = count >> 2u; - - /* First part of the processing with loop unrolling. Compute 4 MACs at a time. - ** a second loop below computes MACs for the remaining 1 to 3 samples. */ - while(k > 0u) - { - /* x[0] , x[1] */ - in1 = (q15_t) * px++; - in2 = (q15_t) * px++; - input1 = ((q31_t) in1 & 0x0000FFFF) | ((q31_t) in2 << 16u); - - /* y[srcBLen - 1] , y[srcBLen - 2] */ - in1 = (q15_t) * py--; - in2 = (q15_t) * py--; - input2 = ((q31_t) in1 & 0x0000FFFF) | ((q31_t) in2 << 16u); - - /* x[0] * y[srcBLen - 1] */ - /* x[1] * y[srcBLen - 2] */ - sum = __SMLAD(input1, input2, sum); - - /* x[2] , x[3] */ - in1 = (q15_t) * px++; - in2 = (q15_t) * px++; - input1 = ((q31_t) in1 & 0x0000FFFF) | ((q31_t) in2 << 16u); - - /* y[srcBLen - 3] , y[srcBLen - 4] */ - in1 = (q15_t) * py--; - in2 = (q15_t) * py--; - input2 = ((q31_t) in1 & 0x0000FFFF) | ((q31_t) in2 << 16u); - - /* x[2] * y[srcBLen - 3] */ - /* x[3] * y[srcBLen - 4] */ - sum = __SMLAD(input1, input2, sum); - - /* Decrement the loop counter */ - k--; - } - - /* If the count is not a multiple of 4, compute any remaining MACs here. - ** No loop unrolling is used. */ - k = count % 0x4u; - - while(k > 0u) - { - /* Perform the multiply-accumulates */ - sum += ((q15_t) * px++ * *py--); - - /* Decrement the loop counter */ - k--; - } - - /* Store the result in the accumulator in the destination buffer. */ - *pOut++ = (q7_t) (__SSAT(sum >> 7u, 8)); - - /* Update the inputA and inputB pointers for next MAC calculation */ - py = pIn2 + count; - px = pIn1; - - /* Increment the MAC count */ - count++; - - /* Decrement the loop counter */ - blockSize1--; - } - - /* -------------------------- - * Initializations of stage2 - * ------------------------*/ - - /* sum = x[0] * y[srcBLen-1] + x[1] * y[srcBLen-2] +...+ x[srcBLen-1] * y[0] - * sum = x[1] * y[srcBLen-1] + x[2] * y[srcBLen-2] +...+ x[srcBLen] * y[0] - * .... - * sum = x[srcALen-srcBLen-2] * y[srcBLen-1] + x[srcALen] * y[srcBLen-2] +...+ x[srcALen-1] * y[0] - */ - - /* Working pointer of inputA */ - px = pIn1; - - /* Working pointer of inputB */ - pSrc2 = pIn2 + (srcBLen - 1u); - py = pSrc2; - - /* count is index by which the pointer pIn1 to be incremented */ - count = 0u; - - /* ------------------- - * Stage2 process - * ------------------*/ - - /* Stage2 depends on srcBLen as in this stage srcBLen number of MACS are performed. - * So, to loop unroll over blockSize2, - * srcBLen should be greater than or equal to 4 */ - if(srcBLen >= 4u) - { - /* Loop unroll over blockSize2, by 4 */ - blkCnt = blockSize2 >> 2u; - - while(blkCnt > 0u) - { - /* Set all accumulators to zero */ - acc0 = 0; - acc1 = 0; - acc2 = 0; - acc3 = 0; - - /* read x[0], x[1], x[2] samples */ - x0 = *(px++); - x1 = *(px++); - x2 = *(px++); - - /* Apply loop unrolling and compute 4 MACs simultaneously. */ - k = srcBLen >> 2u; - - /* First part of the processing with loop unrolling. Compute 4 MACs at a time. - ** a second loop below computes MACs for the remaining 1 to 3 samples. */ - do - { - /* Read y[srcBLen - 1] sample */ - c0 = *(py--); - /* Read y[srcBLen - 2] sample */ - c1 = *(py--); - - /* Read x[3] sample */ - x3 = *(px++); - - /* x[0] and x[1] are packed */ - in1 = (q15_t) x0; - in2 = (q15_t) x1; - - input1 = ((q31_t) in1 & 0x0000FFFF) | ((q31_t) in2 << 16u); - - /* y[srcBLen - 1] and y[srcBLen - 2] are packed */ - in1 = (q15_t) c0; - in2 = (q15_t) c1; - - input2 = ((q31_t) in1 & 0x0000FFFF) | ((q31_t) in2 << 16u); - - /* acc0 += x[0] * y[srcBLen - 1] + x[1] * y[srcBLen - 2] */ - acc0 = __SMLAD(input1, input2, acc0); - - /* x[1] and x[2] are packed */ - in1 = (q15_t) x1; - in2 = (q15_t) x2; - - input1 = ((q31_t) in1 & 0x0000FFFF) | ((q31_t) in2 << 16u); - - /* acc1 += x[1] * y[srcBLen - 1] + x[2] * y[srcBLen - 2] */ - acc1 = __SMLAD(input1, input2, acc1); - - /* x[2] and x[3] are packed */ - in1 = (q15_t) x2; - in2 = (q15_t) x3; - - input1 = ((q31_t) in1 & 0x0000FFFF) | ((q31_t) in2 << 16u); - - /* acc2 += x[2] * y[srcBLen - 1] + x[3] * y[srcBLen - 2] */ - acc2 = __SMLAD(input1, input2, acc2); - - /* Read x[4] sample */ - x0 = *(px++); - - /* x[3] and x[4] are packed */ - in1 = (q15_t) x3; - in2 = (q15_t) x0; - - input1 = ((q31_t) in1 & 0x0000FFFF) | ((q31_t) in2 << 16u); - - /* acc3 += x[3] * y[srcBLen - 1] + x[4] * y[srcBLen - 2] */ - acc3 = __SMLAD(input1, input2, acc3); - - /* Read y[srcBLen - 3] sample */ - c0 = *(py--); - /* Read y[srcBLen - 4] sample */ - c1 = *(py--); - - /* Read x[5] sample */ - x1 = *(px++); - - /* x[2] and x[3] are packed */ - in1 = (q15_t) x2; - in2 = (q15_t) x3; - - input1 = ((q31_t) in1 & 0x0000FFFF) | ((q31_t) in2 << 16u); - - /* y[srcBLen - 3] and y[srcBLen - 4] are packed */ - in1 = (q15_t) c0; - in2 = (q15_t) c1; - - input2 = ((q31_t) in1 & 0x0000FFFF) | ((q31_t) in2 << 16u); - - /* acc0 += x[2] * y[srcBLen - 3] + x[3] * y[srcBLen - 4] */ - acc0 = __SMLAD(input1, input2, acc0); - - /* x[3] and x[4] are packed */ - in1 = (q15_t) x3; - in2 = (q15_t) x0; - - input1 = ((q31_t) in1 & 0x0000FFFF) | ((q31_t) in2 << 16u); - - /* acc1 += x[3] * y[srcBLen - 3] + x[4] * y[srcBLen - 4] */ - acc1 = __SMLAD(input1, input2, acc1); - - /* x[4] and x[5] are packed */ - in1 = (q15_t) x0; - in2 = (q15_t) x1; - - input1 = ((q31_t) in1 & 0x0000FFFF) | ((q31_t) in2 << 16u); - - /* acc2 += x[4] * y[srcBLen - 3] + x[5] * y[srcBLen - 4] */ - acc2 = __SMLAD(input1, input2, acc2); - - /* Read x[6] sample */ - x2 = *(px++); - - /* x[5] and x[6] are packed */ - in1 = (q15_t) x1; - in2 = (q15_t) x2; - - input1 = ((q31_t) in1 & 0x0000FFFF) | ((q31_t) in2 << 16u); - - /* acc3 += x[5] * y[srcBLen - 3] + x[6] * y[srcBLen - 4] */ - acc3 = __SMLAD(input1, input2, acc3); - - } while(--k); - - /* If the srcBLen is not a multiple of 4, compute any remaining MACs here. - ** No loop unrolling is used. */ - k = srcBLen % 0x4u; - - while(k > 0u) - { - /* Read y[srcBLen - 5] sample */ - c0 = *(py--); - - /* Read x[7] sample */ - x3 = *(px++); - - /* Perform the multiply-accumulates */ - /* acc0 += x[4] * y[srcBLen - 5] */ - acc0 += ((q15_t) x0 * c0); - /* acc1 += x[5] * y[srcBLen - 5] */ - acc1 += ((q15_t) x1 * c0); - /* acc2 += x[6] * y[srcBLen - 5] */ - acc2 += ((q15_t) x2 * c0); - /* acc3 += x[7] * y[srcBLen - 5] */ - acc3 += ((q15_t) x3 * c0); - - /* Reuse the present samples for the next MAC */ - x0 = x1; - x1 = x2; - x2 = x3; - - /* Decrement the loop counter */ - k--; - } - - - /* Store the result in the accumulator in the destination buffer. */ - *pOut++ = (q7_t) (__SSAT(acc0 >> 7u, 8)); - *pOut++ = (q7_t) (__SSAT(acc1 >> 7u, 8)); - *pOut++ = (q7_t) (__SSAT(acc2 >> 7u, 8)); - *pOut++ = (q7_t) (__SSAT(acc3 >> 7u, 8)); - - /* Increment the pointer pIn1 index, count by 4 */ - count += 4u; - - /* Update the inputA and inputB pointers for next MAC calculation */ - px = pIn1 + count; - py = pSrc2; - - /* Decrement the loop counter */ - blkCnt--; - } - - /* If the blockSize2 is not a multiple of 4, compute any remaining output samples here. - ** No loop unrolling is used. */ - blkCnt = blockSize2 % 0x4u; - - while(blkCnt > 0u) - { - /* Accumulator is made zero for every iteration */ - sum = 0; - - /* Apply loop unrolling and compute 4 MACs simultaneously. */ - k = srcBLen >> 2u; - - /* First part of the processing with loop unrolling. Compute 4 MACs at a time. - ** a second loop below computes MACs for the remaining 1 to 3 samples. */ - while(k > 0u) - { - - /* Reading two inputs of SrcA buffer and packing */ - in1 = (q15_t) * px++; - in2 = (q15_t) * px++; - input1 = ((q31_t) in1 & 0x0000FFFF) | ((q31_t) in2 << 16u); - - /* Reading two inputs of SrcB buffer and packing */ - in1 = (q15_t) * py--; - in2 = (q15_t) * py--; - input2 = ((q31_t) in1 & 0x0000FFFF) | ((q31_t) in2 << 16u); - - /* Perform the multiply-accumulates */ - sum = __SMLAD(input1, input2, sum); - - /* Reading two inputs of SrcA buffer and packing */ - in1 = (q15_t) * px++; - in2 = (q15_t) * px++; - input1 = ((q31_t) in1 & 0x0000FFFF) | ((q31_t) in2 << 16u); - - /* Reading two inputs of SrcB buffer and packing */ - in1 = (q15_t) * py--; - in2 = (q15_t) * py--; - input2 = ((q31_t) in1 & 0x0000FFFF) | ((q31_t) in2 << 16u); - - /* Perform the multiply-accumulates */ - sum = __SMLAD(input1, input2, sum); - - /* Decrement the loop counter */ - k--; - } - - /* If the srcBLen is not a multiple of 4, compute any remaining MACs here. - ** No loop unrolling is used. */ - k = srcBLen % 0x4u; - - while(k > 0u) - { - /* Perform the multiply-accumulates */ - sum += ((q15_t) * px++ * *py--); - - /* Decrement the loop counter */ - k--; - } - - /* Store the result in the accumulator in the destination buffer. */ - *pOut++ = (q7_t) (__SSAT(sum >> 7u, 8)); - - /* Increment the pointer pIn1 index, count by 1 */ - count++; - - /* Update the inputA and inputB pointers for next MAC calculation */ - px = pIn1 + count; - py = pSrc2; - - /* Decrement the loop counter */ - blkCnt--; - } - } - else - { - /* If the srcBLen is not a multiple of 4, - * the blockSize2 loop cannot be unrolled by 4 */ - blkCnt = blockSize2; - - while(blkCnt > 0u) - { - /* Accumulator is made zero for every iteration */ - sum = 0; - - /* srcBLen number of MACS should be performed */ - k = srcBLen; - - while(k > 0u) - { - /* Perform the multiply-accumulate */ - sum += ((q15_t) * px++ * *py--); - - /* Decrement the loop counter */ - k--; - } - - /* Store the result in the accumulator in the destination buffer. */ - *pOut++ = (q7_t) (__SSAT(sum >> 7u, 8)); - - /* Increment the MAC count */ - count++; - - /* Update the inputA and inputB pointers for next MAC calculation */ - px = pIn1 + count; - py = pSrc2; - - /* Decrement the loop counter */ - blkCnt--; - } - } - - - /* -------------------------- - * Initializations of stage3 - * -------------------------*/ - - /* sum += x[srcALen-srcBLen+1] * y[srcBLen-1] + x[srcALen-srcBLen+2] * y[srcBLen-2] +...+ x[srcALen-1] * y[1] - * sum += x[srcALen-srcBLen+2] * y[srcBLen-1] + x[srcALen-srcBLen+3] * y[srcBLen-2] +...+ x[srcALen-1] * y[2] - * .... - * sum += x[srcALen-2] * y[srcBLen-1] + x[srcALen-1] * y[srcBLen-2] - * sum += x[srcALen-1] * y[srcBLen-1] - */ - - /* In this stage the MAC operations are decreased by 1 for every iteration. - The blockSize3 variable holds the number of MAC operations performed */ - - /* Working pointer of inputA */ - pSrc1 = pIn1 + (srcALen - (srcBLen - 1u)); - px = pSrc1; - - /* Working pointer of inputB */ - pSrc2 = pIn2 + (srcBLen - 1u); - py = pSrc2; - - /* ------------------- - * Stage3 process - * ------------------*/ - - while(blockSize3 > 0u) - { - /* Accumulator is made zero for every iteration */ - sum = 0; - - /* Apply loop unrolling and compute 4 MACs simultaneously. */ - k = blockSize3 >> 2u; - - /* First part of the processing with loop unrolling. Compute 4 MACs at a time. - ** a second loop below computes MACs for the remaining 1 to 3 samples. */ - while(k > 0u) - { - /* Reading two inputs, x[srcALen - srcBLen + 1] and x[srcALen - srcBLen + 2] of SrcA buffer and packing */ - in1 = (q15_t) * px++; - in2 = (q15_t) * px++; - input1 = ((q31_t) in1 & 0x0000FFFF) | ((q31_t) in2 << 16u); - - /* Reading two inputs, y[srcBLen - 1] and y[srcBLen - 2] of SrcB buffer and packing */ - in1 = (q15_t) * py--; - in2 = (q15_t) * py--; - input2 = ((q31_t) in1 & 0x0000FFFF) | ((q31_t) in2 << 16u); - - /* sum += x[srcALen - srcBLen + 1] * y[srcBLen - 1] */ - /* sum += x[srcALen - srcBLen + 2] * y[srcBLen - 2] */ - sum = __SMLAD(input1, input2, sum); - - /* Reading two inputs, x[srcALen - srcBLen + 3] and x[srcALen - srcBLen + 4] of SrcA buffer and packing */ - in1 = (q15_t) * px++; - in2 = (q15_t) * px++; - input1 = ((q31_t) in1 & 0x0000FFFF) | ((q31_t) in2 << 16u); - - /* Reading two inputs, y[srcBLen - 3] and y[srcBLen - 4] of SrcB buffer and packing */ - in1 = (q15_t) * py--; - in2 = (q15_t) * py--; - input2 = ((q31_t) in1 & 0x0000FFFF) | ((q31_t) in2 << 16u); - - /* sum += x[srcALen - srcBLen + 3] * y[srcBLen - 3] */ - /* sum += x[srcALen - srcBLen + 4] * y[srcBLen - 4] */ - sum = __SMLAD(input1, input2, sum); - - /* Decrement the loop counter */ - k--; - } - - /* If the blockSize3 is not a multiple of 4, compute any remaining MACs here. - ** No loop unrolling is used. */ - k = blockSize3 % 0x4u; - - while(k > 0u) - { - /* Perform the multiply-accumulates */ - sum += ((q15_t) * px++ * *py--); - - /* Decrement the loop counter */ - k--; - } - - /* Store the result in the accumulator in the destination buffer. */ - *pOut++ = (q7_t) (__SSAT(sum >> 7u, 8)); - - /* Update the inputA and inputB pointers for next MAC calculation */ - px = ++pSrc1; - py = pSrc2; - - /* Decrement the loop counter */ - blockSize3--; - } - -#else - - /* Run the below code for Cortex-M0 */ - - q7_t *pIn1 = pSrcA; /* input pointer */ - q7_t *pIn2 = pSrcB; /* coefficient pointer */ - q31_t sum; /* Accumulator */ - uint32_t i, j; /* loop counter */ - - /* Loop to calculate output of convolution for output length number of times */ - for (i = 0; i < (srcALen + srcBLen - 1); i++) - { - /* Initialize sum with zero to carry on MAC operations */ - sum = 0; - - /* Loop to perform MAC operations according to convolution equation */ - for (j = 0; j <= i; j++) - { - /* Check the array limitations */ - if(((i - j) < srcBLen) && (j < srcALen)) - { - /* z[i] += x[i-j] * y[j] */ - sum += (q15_t) pIn1[j] * (pIn2[i - j]); - } - } - - /* Store the output in the destination buffer */ - pDst[i] = (q7_t) __SSAT((sum >> 7u), 8u); - } - -#endif /* #ifndef ARM_MATH_CM0_FAMILY */ - -} - -/** - * @} end of Conv group - */ diff --git a/gui/cmsis/arm_fir_f32.c b/gui/cmsis/arm_fir_f32.c deleted file mode 100644 index 3ecb7b5..0000000 --- a/gui/cmsis/arm_fir_f32.c +++ /dev/null @@ -1,997 +0,0 @@ -/* ---------------------------------------------------------------------- -* Copyright (C) 2010-2014 ARM Limited. All rights reserved. -* -* $Date: 19. March 2015 -* $Revision: V.1.4.5 -* -* Project: CMSIS DSP Library -* Title: arm_fir_f32.c -* -* Description: Floating-point FIR filter processing function. -* -* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0 -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* - Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* - Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in -* the documentation and/or other materials provided with the -* distribution. -* - Neither the name of ARM LIMITED nor the names of its contributors -* may be used to endorse or promote products derived from this -* software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -* POSSIBILITY OF SUCH DAMAGE. -* -------------------------------------------------------------------- */ - -#include "arm_math.h" - -/** -* @ingroup groupFilters -*/ - -/** -* @defgroup FIR Finite Impulse Response (FIR) Filters -* -* This set of functions implements Finite Impulse Response (FIR) filters -* for Q7, Q15, Q31, and floating-point data types. Fast versions of Q15 and Q31 are also provided. -* The functions operate on blocks of input and output data and each call to the function processes -* blockSize samples through the filter. pSrc and -* pDst points to input and output arrays containing blockSize values. -* -* \par Algorithm: -* The FIR filter algorithm is based upon a sequence of multiply-accumulate (MAC) operations. -* Each filter coefficient b[n] is multiplied by a state variable which equals a previous input sample x[n]. -*
  
-*    y[n] = b[0] * x[n] + b[1] * x[n-1] + b[2] * x[n-2] + ...+ b[numTaps-1] * x[n-numTaps+1]  
-* 
-* \par -* \image html FIR.gif "Finite Impulse Response filter" -* \par -* pCoeffs points to a coefficient array of size numTaps. -* Coefficients are stored in time reversed order. -* \par -*
  
-*    {b[numTaps-1], b[numTaps-2], b[N-2], ..., b[1], b[0]}  
-* 
-* \par -* pState points to a state array of size numTaps + blockSize - 1. -* Samples in the state buffer are stored in the following order. -* \par -*
  
-*    {x[n-numTaps+1], x[n-numTaps], x[n-numTaps-1], x[n-numTaps-2]....x[0], x[1], ..., x[blockSize-1]}  
-* 
-* \par -* Note that the length of the state buffer exceeds the length of the coefficient array by blockSize-1. -* The increased state buffer length allows circular addressing, which is traditionally used in the FIR filters, -* to be avoided and yields a significant speed improvement. -* The state variables are updated after each block of data is processed; the coefficients are untouched. -* \par Instance Structure -* The coefficients and state variables for a filter are stored together in an instance data structure. -* A separate instance structure must be defined for each filter. -* Coefficient arrays may be shared among several instances while state variable arrays cannot be shared. -* There are separate instance structure declarations for each of the 4 supported data types. -* -* \par Initialization Functions -* There is also an associated initialization function for each data type. -* The initialization function performs the following operations: -* - Sets the values of the internal structure fields. -* - Zeros out the values in the state buffer. -* To do this manually without calling the init function, assign the follow subfields of the instance structure: -* numTaps, pCoeffs, pState. Also set all of the values in pState to zero. -* -* \par -* Use of the initialization function is optional. -* However, if the initialization function is used, then the instance structure cannot be placed into a const data section. -* To place an instance structure into a const data section, the instance structure must be manually initialized. -* Set the values in the state buffer to zeros before static initialization. -* The code below statically initializes each of the 4 different data type filter instance structures -*
  
-*arm_fir_instance_f32 S = {numTaps, pState, pCoeffs};  
-*arm_fir_instance_q31 S = {numTaps, pState, pCoeffs};  
-*arm_fir_instance_q15 S = {numTaps, pState, pCoeffs};  
-*arm_fir_instance_q7 S =  {numTaps, pState, pCoeffs};  
-* 
-* -* where numTaps is the number of filter coefficients in the filter; pState is the address of the state buffer; -* pCoeffs is the address of the coefficient buffer. -* -* \par Fixed-Point Behavior -* Care must be taken when using the fixed-point versions of the FIR filter functions. -* In particular, the overflow and saturation behavior of the accumulator used in each function must be considered. -* Refer to the function specific documentation below for usage guidelines. -*/ - -/** -* @addtogroup FIR -* @{ -*/ - -/** -* -* @param[in] *S points to an instance of the floating-point FIR filter structure. -* @param[in] *pSrc points to the block of input data. -* @param[out] *pDst points to the block of output data. -* @param[in] blockSize number of samples to process per call. -* @return none. -* -*/ - -#if defined(ARM_MATH_CM7) - -void arm_fir_f32( -const arm_fir_instance_f32 * S, -float32_t * pSrc, -float32_t * pDst, -uint32_t blockSize) -{ - float32_t *pState = S->pState; /* State pointer */ - float32_t *pCoeffs = S->pCoeffs; /* Coefficient pointer */ - float32_t *pStateCurnt; /* Points to the current sample of the state */ - float32_t *px, *pb; /* Temporary pointers for state and coefficient buffers */ - float32_t acc0, acc1, acc2, acc3, acc4, acc5, acc6, acc7; /* Accumulators */ - float32_t x0, x1, x2, x3, x4, x5, x6, x7, c0; /* Temporary variables to hold state and coefficient values */ - uint32_t numTaps = S->numTaps; /* Number of filter coefficients in the filter */ - uint32_t i, tapCnt, blkCnt; /* Loop counters */ - - /* S->pState points to state array which contains previous frame (numTaps - 1) samples */ - /* pStateCurnt points to the location where the new input data should be written */ - pStateCurnt = &(S->pState[(numTaps - 1u)]); - - /* Apply loop unrolling and compute 8 output values simultaneously. - * The variables acc0 ... acc7 hold output values that are being computed: - * - * acc0 = b[numTaps-1] * x[n-numTaps-1] + b[numTaps-2] * x[n-numTaps-2] + b[numTaps-3] * x[n-numTaps-3] +...+ b[0] * x[0] - * acc1 = b[numTaps-1] * x[n-numTaps] + b[numTaps-2] * x[n-numTaps-1] + b[numTaps-3] * x[n-numTaps-2] +...+ b[0] * x[1] - * acc2 = b[numTaps-1] * x[n-numTaps+1] + b[numTaps-2] * x[n-numTaps] + b[numTaps-3] * x[n-numTaps-1] +...+ b[0] * x[2] - * acc3 = b[numTaps-1] * x[n-numTaps+2] + b[numTaps-2] * x[n-numTaps+1] + b[numTaps-3] * x[n-numTaps] +...+ b[0] * x[3] - */ - blkCnt = blockSize >> 3; - - /* First part of the processing with loop unrolling. Compute 8 outputs at a time. - ** a second loop below computes the remaining 1 to 7 samples. */ - while(blkCnt > 0u) - { - /* Copy four new input samples into the state buffer */ - *pStateCurnt++ = *pSrc++; - *pStateCurnt++ = *pSrc++; - *pStateCurnt++ = *pSrc++; - *pStateCurnt++ = *pSrc++; - - /* Set all accumulators to zero */ - acc0 = 0.0f; - acc1 = 0.0f; - acc2 = 0.0f; - acc3 = 0.0f; - acc4 = 0.0f; - acc5 = 0.0f; - acc6 = 0.0f; - acc7 = 0.0f; - - /* Initialize state pointer */ - px = pState; - - /* Initialize coeff pointer */ - pb = (pCoeffs); - - /* This is separated from the others to avoid - * a call to __aeabi_memmove which would be slower - */ - *pStateCurnt++ = *pSrc++; - *pStateCurnt++ = *pSrc++; - *pStateCurnt++ = *pSrc++; - *pStateCurnt++ = *pSrc++; - - /* Read the first seven samples from the state buffer: x[n-numTaps], x[n-numTaps-1], x[n-numTaps-2] */ - x0 = *px++; - x1 = *px++; - x2 = *px++; - x3 = *px++; - x4 = *px++; - x5 = *px++; - x6 = *px++; - - /* Loop unrolling. Process 8 taps at a time. */ - tapCnt = numTaps >> 3u; - - /* Loop over the number of taps. Unroll by a factor of 8. - ** Repeat until we've computed numTaps-8 coefficients. */ - while(tapCnt > 0u) - { - /* Read the b[numTaps-1] coefficient */ - c0 = *(pb++); - - /* Read x[n-numTaps-3] sample */ - x7 = *(px++); - - /* acc0 += b[numTaps-1] * x[n-numTaps] */ - acc0 += x0 * c0; - - /* acc1 += b[numTaps-1] * x[n-numTaps-1] */ - acc1 += x1 * c0; - - /* acc2 += b[numTaps-1] * x[n-numTaps-2] */ - acc2 += x2 * c0; - - /* acc3 += b[numTaps-1] * x[n-numTaps-3] */ - acc3 += x3 * c0; - - /* acc4 += b[numTaps-1] * x[n-numTaps-4] */ - acc4 += x4 * c0; - - /* acc1 += b[numTaps-1] * x[n-numTaps-5] */ - acc5 += x5 * c0; - - /* acc2 += b[numTaps-1] * x[n-numTaps-6] */ - acc6 += x6 * c0; - - /* acc3 += b[numTaps-1] * x[n-numTaps-7] */ - acc7 += x7 * c0; - - /* Read the b[numTaps-2] coefficient */ - c0 = *(pb++); - - /* Read x[n-numTaps-4] sample */ - x0 = *(px++); - - /* Perform the multiply-accumulate */ - acc0 += x1 * c0; - acc1 += x2 * c0; - acc2 += x3 * c0; - acc3 += x4 * c0; - acc4 += x5 * c0; - acc5 += x6 * c0; - acc6 += x7 * c0; - acc7 += x0 * c0; - - /* Read the b[numTaps-3] coefficient */ - c0 = *(pb++); - - /* Read x[n-numTaps-5] sample */ - x1 = *(px++); - - /* Perform the multiply-accumulates */ - acc0 += x2 * c0; - acc1 += x3 * c0; - acc2 += x4 * c0; - acc3 += x5 * c0; - acc4 += x6 * c0; - acc5 += x7 * c0; - acc6 += x0 * c0; - acc7 += x1 * c0; - - /* Read the b[numTaps-4] coefficient */ - c0 = *(pb++); - - /* Read x[n-numTaps-6] sample */ - x2 = *(px++); - - /* Perform the multiply-accumulates */ - acc0 += x3 * c0; - acc1 += x4 * c0; - acc2 += x5 * c0; - acc3 += x6 * c0; - acc4 += x7 * c0; - acc5 += x0 * c0; - acc6 += x1 * c0; - acc7 += x2 * c0; - - /* Read the b[numTaps-4] coefficient */ - c0 = *(pb++); - - /* Read x[n-numTaps-6] sample */ - x3 = *(px++); - /* Perform the multiply-accumulates */ - acc0 += x4 * c0; - acc1 += x5 * c0; - acc2 += x6 * c0; - acc3 += x7 * c0; - acc4 += x0 * c0; - acc5 += x1 * c0; - acc6 += x2 * c0; - acc7 += x3 * c0; - - /* Read the b[numTaps-4] coefficient */ - c0 = *(pb++); - - /* Read x[n-numTaps-6] sample */ - x4 = *(px++); - - /* Perform the multiply-accumulates */ - acc0 += x5 * c0; - acc1 += x6 * c0; - acc2 += x7 * c0; - acc3 += x0 * c0; - acc4 += x1 * c0; - acc5 += x2 * c0; - acc6 += x3 * c0; - acc7 += x4 * c0; - - /* Read the b[numTaps-4] coefficient */ - c0 = *(pb++); - - /* Read x[n-numTaps-6] sample */ - x5 = *(px++); - - /* Perform the multiply-accumulates */ - acc0 += x6 * c0; - acc1 += x7 * c0; - acc2 += x0 * c0; - acc3 += x1 * c0; - acc4 += x2 * c0; - acc5 += x3 * c0; - acc6 += x4 * c0; - acc7 += x5 * c0; - - /* Read the b[numTaps-4] coefficient */ - c0 = *(pb++); - - /* Read x[n-numTaps-6] sample */ - x6 = *(px++); - - /* Perform the multiply-accumulates */ - acc0 += x7 * c0; - acc1 += x0 * c0; - acc2 += x1 * c0; - acc3 += x2 * c0; - acc4 += x3 * c0; - acc5 += x4 * c0; - acc6 += x5 * c0; - acc7 += x6 * c0; - - tapCnt--; - } - - /* If the filter length is not a multiple of 8, compute the remaining filter taps */ - tapCnt = numTaps % 0x8u; - - while(tapCnt > 0u) - { - /* Read coefficients */ - c0 = *(pb++); - - /* Fetch 1 state variable */ - x7 = *(px++); - - /* Perform the multiply-accumulates */ - acc0 += x0 * c0; - acc1 += x1 * c0; - acc2 += x2 * c0; - acc3 += x3 * c0; - acc4 += x4 * c0; - acc5 += x5 * c0; - acc6 += x6 * c0; - acc7 += x7 * c0; - - /* Reuse the present sample states for next sample */ - x0 = x1; - x1 = x2; - x2 = x3; - x3 = x4; - x4 = x5; - x5 = x6; - x6 = x7; - - /* Decrement the loop counter */ - tapCnt--; - } - - /* Advance the state pointer by 8 to process the next group of 8 samples */ - pState = pState + 8; - - /* The results in the 8 accumulators, store in the destination buffer. */ - *pDst++ = acc0; - *pDst++ = acc1; - *pDst++ = acc2; - *pDst++ = acc3; - *pDst++ = acc4; - *pDst++ = acc5; - *pDst++ = acc6; - *pDst++ = acc7; - - blkCnt--; - } - - /* If the blockSize is not a multiple of 8, compute any remaining output samples here. - ** No loop unrolling is used. */ - blkCnt = blockSize % 0x8u; - - while(blkCnt > 0u) - { - /* Copy one sample at a time into state buffer */ - *pStateCurnt++ = *pSrc++; - - /* Set the accumulator to zero */ - acc0 = 0.0f; - - /* Initialize state pointer */ - px = pState; - - /* Initialize Coefficient pointer */ - pb = (pCoeffs); - - i = numTaps; - - /* Perform the multiply-accumulates */ - do - { - acc0 += *px++ * *pb++; - i--; - - } while(i > 0u); - - /* The result is store in the destination buffer. */ - *pDst++ = acc0; - - /* Advance state pointer by 1 for the next sample */ - pState = pState + 1; - - blkCnt--; - } - - /* Processing is complete. - ** Now copy the last numTaps - 1 samples to the start of the state buffer. - ** This prepares the state buffer for the next function call. */ - - /* Points to the start of the state buffer */ - pStateCurnt = S->pState; - - tapCnt = (numTaps - 1u) >> 2u; - - /* copy data */ - while(tapCnt > 0u) - { - *pStateCurnt++ = *pState++; - *pStateCurnt++ = *pState++; - *pStateCurnt++ = *pState++; - *pStateCurnt++ = *pState++; - - /* Decrement the loop counter */ - tapCnt--; - } - - /* Calculate remaining number of copies */ - tapCnt = (numTaps - 1u) % 0x4u; - - /* Copy the remaining q31_t data */ - while(tapCnt > 0u) - { - *pStateCurnt++ = *pState++; - - /* Decrement the loop counter */ - tapCnt--; - } -} - -#elif defined(ARM_MATH_CM0_FAMILY) - -void arm_fir_f32( -const arm_fir_instance_f32 * S, -float32_t * pSrc, -float32_t * pDst, -uint32_t blockSize) -{ - float32_t *pState = S->pState; /* State pointer */ - float32_t *pCoeffs = S->pCoeffs; /* Coefficient pointer */ - float32_t *pStateCurnt; /* Points to the current sample of the state */ - float32_t *px, *pb; /* Temporary pointers for state and coefficient buffers */ - uint32_t numTaps = S->numTaps; /* Number of filter coefficients in the filter */ - uint32_t i, tapCnt, blkCnt; /* Loop counters */ - - /* Run the below code for Cortex-M0 */ - - float32_t acc; - - /* S->pState points to state array which contains previous frame (numTaps - 1) samples */ - /* pStateCurnt points to the location where the new input data should be written */ - pStateCurnt = &(S->pState[(numTaps - 1u)]); - - /* Initialize blkCnt with blockSize */ - blkCnt = blockSize; - - while(blkCnt > 0u) - { - /* Copy one sample at a time into state buffer */ - *pStateCurnt++ = *pSrc++; - - /* Set the accumulator to zero */ - acc = 0.0f; - - /* Initialize state pointer */ - px = pState; - - /* Initialize Coefficient pointer */ - pb = pCoeffs; - - i = numTaps; - - /* Perform the multiply-accumulates */ - do - { - /* acc = b[numTaps-1] * x[n-numTaps-1] + b[numTaps-2] * x[n-numTaps-2] + b[numTaps-3] * x[n-numTaps-3] +...+ b[0] * x[0] */ - acc += *px++ * *pb++; - i--; - - } while(i > 0u); - - /* The result is store in the destination buffer. */ - *pDst++ = acc; - - /* Advance state pointer by 1 for the next sample */ - pState = pState + 1; - - blkCnt--; - } - - /* Processing is complete. - ** Now copy the last numTaps - 1 samples to the starting of the state buffer. - ** This prepares the state buffer for the next function call. */ - - /* Points to the start of the state buffer */ - pStateCurnt = S->pState; - - /* Copy numTaps number of values */ - tapCnt = numTaps - 1u; - - /* Copy data */ - while(tapCnt > 0u) - { - *pStateCurnt++ = *pState++; - - /* Decrement the loop counter */ - tapCnt--; - } - -} - -#else - -/* Run the below code for Cortex-M4 and Cortex-M3 */ - -void arm_fir_f32( -const arm_fir_instance_f32 * S, -float32_t * pSrc, -float32_t * pDst, -uint32_t blockSize) -{ - float32_t *pState = S->pState; /* State pointer */ - float32_t *pCoeffs = S->pCoeffs; /* Coefficient pointer */ - float32_t *pStateCurnt; /* Points to the current sample of the state */ - float32_t *px, *pb; /* Temporary pointers for state and coefficient buffers */ - float32_t acc0, acc1, acc2, acc3, acc4, acc5, acc6, acc7; /* Accumulators */ - float32_t x0, x1, x2, x3, x4, x5, x6, x7, c0; /* Temporary variables to hold state and coefficient values */ - uint32_t numTaps = S->numTaps; /* Number of filter coefficients in the filter */ - uint32_t i, tapCnt, blkCnt; /* Loop counters */ - float32_t p0,p1,p2,p3,p4,p5,p6,p7; /* Temporary product values */ - - /* S->pState points to state array which contains previous frame (numTaps - 1) samples */ - /* pStateCurnt points to the location where the new input data should be written */ - pStateCurnt = &(S->pState[(numTaps - 1u)]); - - /* Apply loop unrolling and compute 8 output values simultaneously. - * The variables acc0 ... acc7 hold output values that are being computed: - * - * acc0 = b[numTaps-1] * x[n-numTaps-1] + b[numTaps-2] * x[n-numTaps-2] + b[numTaps-3] * x[n-numTaps-3] +...+ b[0] * x[0] - * acc1 = b[numTaps-1] * x[n-numTaps] + b[numTaps-2] * x[n-numTaps-1] + b[numTaps-3] * x[n-numTaps-2] +...+ b[0] * x[1] - * acc2 = b[numTaps-1] * x[n-numTaps+1] + b[numTaps-2] * x[n-numTaps] + b[numTaps-3] * x[n-numTaps-1] +...+ b[0] * x[2] - * acc3 = b[numTaps-1] * x[n-numTaps+2] + b[numTaps-2] * x[n-numTaps+1] + b[numTaps-3] * x[n-numTaps] +...+ b[0] * x[3] - */ - blkCnt = blockSize >> 3; - - /* First part of the processing with loop unrolling. Compute 8 outputs at a time. - ** a second loop below computes the remaining 1 to 7 samples. */ - while(blkCnt > 0u) - { - /* Copy four new input samples into the state buffer */ - *pStateCurnt++ = *pSrc++; - *pStateCurnt++ = *pSrc++; - *pStateCurnt++ = *pSrc++; - *pStateCurnt++ = *pSrc++; - - /* Set all accumulators to zero */ - acc0 = 0.0f; - acc1 = 0.0f; - acc2 = 0.0f; - acc3 = 0.0f; - acc4 = 0.0f; - acc5 = 0.0f; - acc6 = 0.0f; - acc7 = 0.0f; - - /* Initialize state pointer */ - px = pState; - - /* Initialize coeff pointer */ - pb = (pCoeffs); - - /* This is separated from the others to avoid - * a call to __aeabi_memmove which would be slower - */ - *pStateCurnt++ = *pSrc++; - *pStateCurnt++ = *pSrc++; - *pStateCurnt++ = *pSrc++; - *pStateCurnt++ = *pSrc++; - - /* Read the first seven samples from the state buffer: x[n-numTaps], x[n-numTaps-1], x[n-numTaps-2] */ - x0 = *px++; - x1 = *px++; - x2 = *px++; - x3 = *px++; - x4 = *px++; - x5 = *px++; - x6 = *px++; - - /* Loop unrolling. Process 8 taps at a time. */ - tapCnt = numTaps >> 3u; - - /* Loop over the number of taps. Unroll by a factor of 8. - ** Repeat until we've computed numTaps-8 coefficients. */ - while(tapCnt > 0u) - { - /* Read the b[numTaps-1] coefficient */ - c0 = *(pb++); - - /* Read x[n-numTaps-3] sample */ - x7 = *(px++); - - /* acc0 += b[numTaps-1] * x[n-numTaps] */ - p0 = x0 * c0; - - /* acc1 += b[numTaps-1] * x[n-numTaps-1] */ - p1 = x1 * c0; - - /* acc2 += b[numTaps-1] * x[n-numTaps-2] */ - p2 = x2 * c0; - - /* acc3 += b[numTaps-1] * x[n-numTaps-3] */ - p3 = x3 * c0; - - /* acc4 += b[numTaps-1] * x[n-numTaps-4] */ - p4 = x4 * c0; - - /* acc1 += b[numTaps-1] * x[n-numTaps-5] */ - p5 = x5 * c0; - - /* acc2 += b[numTaps-1] * x[n-numTaps-6] */ - p6 = x6 * c0; - - /* acc3 += b[numTaps-1] * x[n-numTaps-7] */ - p7 = x7 * c0; - - /* Read the b[numTaps-2] coefficient */ - c0 = *(pb++); - - /* Read x[n-numTaps-4] sample */ - x0 = *(px++); - - acc0 += p0; - acc1 += p1; - acc2 += p2; - acc3 += p3; - acc4 += p4; - acc5 += p5; - acc6 += p6; - acc7 += p7; - - - /* Perform the multiply-accumulate */ - p0 = x1 * c0; - p1 = x2 * c0; - p2 = x3 * c0; - p3 = x4 * c0; - p4 = x5 * c0; - p5 = x6 * c0; - p6 = x7 * c0; - p7 = x0 * c0; - - /* Read the b[numTaps-3] coefficient */ - c0 = *(pb++); - - /* Read x[n-numTaps-5] sample */ - x1 = *(px++); - - acc0 += p0; - acc1 += p1; - acc2 += p2; - acc3 += p3; - acc4 += p4; - acc5 += p5; - acc6 += p6; - acc7 += p7; - - /* Perform the multiply-accumulates */ - p0 = x2 * c0; - p1 = x3 * c0; - p2 = x4 * c0; - p3 = x5 * c0; - p4 = x6 * c0; - p5 = x7 * c0; - p6 = x0 * c0; - p7 = x1 * c0; - - /* Read the b[numTaps-4] coefficient */ - c0 = *(pb++); - - /* Read x[n-numTaps-6] sample */ - x2 = *(px++); - - acc0 += p0; - acc1 += p1; - acc2 += p2; - acc3 += p3; - acc4 += p4; - acc5 += p5; - acc6 += p6; - acc7 += p7; - - /* Perform the multiply-accumulates */ - p0 = x3 * c0; - p1 = x4 * c0; - p2 = x5 * c0; - p3 = x6 * c0; - p4 = x7 * c0; - p5 = x0 * c0; - p6 = x1 * c0; - p7 = x2 * c0; - - /* Read the b[numTaps-4] coefficient */ - c0 = *(pb++); - - /* Read x[n-numTaps-6] sample */ - x3 = *(px++); - - acc0 += p0; - acc1 += p1; - acc2 += p2; - acc3 += p3; - acc4 += p4; - acc5 += p5; - acc6 += p6; - acc7 += p7; - - /* Perform the multiply-accumulates */ - p0 = x4 * c0; - p1 = x5 * c0; - p2 = x6 * c0; - p3 = x7 * c0; - p4 = x0 * c0; - p5 = x1 * c0; - p6 = x2 * c0; - p7 = x3 * c0; - - /* Read the b[numTaps-4] coefficient */ - c0 = *(pb++); - - /* Read x[n-numTaps-6] sample */ - x4 = *(px++); - - acc0 += p0; - acc1 += p1; - acc2 += p2; - acc3 += p3; - acc4 += p4; - acc5 += p5; - acc6 += p6; - acc7 += p7; - - /* Perform the multiply-accumulates */ - p0 = x5 * c0; - p1 = x6 * c0; - p2 = x7 * c0; - p3 = x0 * c0; - p4 = x1 * c0; - p5 = x2 * c0; - p6 = x3 * c0; - p7 = x4 * c0; - - /* Read the b[numTaps-4] coefficient */ - c0 = *(pb++); - - /* Read x[n-numTaps-6] sample */ - x5 = *(px++); - - acc0 += p0; - acc1 += p1; - acc2 += p2; - acc3 += p3; - acc4 += p4; - acc5 += p5; - acc6 += p6; - acc7 += p7; - - /* Perform the multiply-accumulates */ - p0 = x6 * c0; - p1 = x7 * c0; - p2 = x0 * c0; - p3 = x1 * c0; - p4 = x2 * c0; - p5 = x3 * c0; - p6 = x4 * c0; - p7 = x5 * c0; - - /* Read the b[numTaps-4] coefficient */ - c0 = *(pb++); - - /* Read x[n-numTaps-6] sample */ - x6 = *(px++); - - acc0 += p0; - acc1 += p1; - acc2 += p2; - acc3 += p3; - acc4 += p4; - acc5 += p5; - acc6 += p6; - acc7 += p7; - - /* Perform the multiply-accumulates */ - p0 = x7 * c0; - p1 = x0 * c0; - p2 = x1 * c0; - p3 = x2 * c0; - p4 = x3 * c0; - p5 = x4 * c0; - p6 = x5 * c0; - p7 = x6 * c0; - - tapCnt--; - - acc0 += p0; - acc1 += p1; - acc2 += p2; - acc3 += p3; - acc4 += p4; - acc5 += p5; - acc6 += p6; - acc7 += p7; - } - - /* If the filter length is not a multiple of 8, compute the remaining filter taps */ - tapCnt = numTaps % 0x8u; - - while(tapCnt > 0u) - { - /* Read coefficients */ - c0 = *(pb++); - - /* Fetch 1 state variable */ - x7 = *(px++); - - /* Perform the multiply-accumulates */ - p0 = x0 * c0; - p1 = x1 * c0; - p2 = x2 * c0; - p3 = x3 * c0; - p4 = x4 * c0; - p5 = x5 * c0; - p6 = x6 * c0; - p7 = x7 * c0; - - /* Reuse the present sample states for next sample */ - x0 = x1; - x1 = x2; - x2 = x3; - x3 = x4; - x4 = x5; - x5 = x6; - x6 = x7; - - acc0 += p0; - acc1 += p1; - acc2 += p2; - acc3 += p3; - acc4 += p4; - acc5 += p5; - acc6 += p6; - acc7 += p7; - - /* Decrement the loop counter */ - tapCnt--; - } - - /* Advance the state pointer by 8 to process the next group of 8 samples */ - pState = pState + 8; - - /* The results in the 8 accumulators, store in the destination buffer. */ - *pDst++ = acc0; - *pDst++ = acc1; - *pDst++ = acc2; - *pDst++ = acc3; - *pDst++ = acc4; - *pDst++ = acc5; - *pDst++ = acc6; - *pDst++ = acc7; - - blkCnt--; - } - - /* If the blockSize is not a multiple of 8, compute any remaining output samples here. - ** No loop unrolling is used. */ - blkCnt = blockSize % 0x8u; - - while(blkCnt > 0u) - { - /* Copy one sample at a time into state buffer */ - *pStateCurnt++ = *pSrc++; - - /* Set the accumulator to zero */ - acc0 = 0.0f; - - /* Initialize state pointer */ - px = pState; - - /* Initialize Coefficient pointer */ - pb = (pCoeffs); - - i = numTaps; - - /* Perform the multiply-accumulates */ - do - { - acc0 += *px++ * *pb++; - i--; - - } while(i > 0u); - - /* The result is store in the destination buffer. */ - *pDst++ = acc0; - - /* Advance state pointer by 1 for the next sample */ - pState = pState + 1; - - blkCnt--; - } - - /* Processing is complete. - ** Now copy the last numTaps - 1 samples to the start of the state buffer. - ** This prepares the state buffer for the next function call. */ - - /* Points to the start of the state buffer */ - pStateCurnt = S->pState; - - tapCnt = (numTaps - 1u) >> 2u; - - /* copy data */ - while(tapCnt > 0u) - { - *pStateCurnt++ = *pState++; - *pStateCurnt++ = *pState++; - *pStateCurnt++ = *pState++; - *pStateCurnt++ = *pState++; - - /* Decrement the loop counter */ - tapCnt--; - } - - /* Calculate remaining number of copies */ - tapCnt = (numTaps - 1u) % 0x4u; - - /* Copy the remaining q31_t data */ - while(tapCnt > 0u) - { - *pStateCurnt++ = *pState++; - - /* Decrement the loop counter */ - tapCnt--; - } -} - -#endif - -/** -* @} end of FIR group -*/ diff --git a/gui/cmsis/arm_fir_init_f32.c b/gui/cmsis/arm_fir_init_f32.c deleted file mode 100644 index 92bdc9e..0000000 --- a/gui/cmsis/arm_fir_init_f32.c +++ /dev/null @@ -1,96 +0,0 @@ -/*----------------------------------------------------------------------------- -* Copyright (C) 2010-2014 ARM Limited. All rights reserved. -* -* $Date: 19. March 2015 -* $Revision: V.1.4.5 -* -* Project: CMSIS DSP Library -* Title: arm_fir_init_f32.c -* -* Description: Floating-point FIR filter initialization function. -* -* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0 -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* - Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* - Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in -* the documentation and/or other materials provided with the -* distribution. -* - Neither the name of ARM LIMITED nor the names of its contributors -* may be used to endorse or promote products derived from this -* software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -* POSSIBILITY OF SUCH DAMAGE. -* ---------------------------------------------------------------------------*/ - -#include "arm_math.h" - -/** - * @ingroup groupFilters - */ - -/** - * @addtogroup FIR - * @{ - */ - -/** - * @details - * - * @param[in,out] *S points to an instance of the floating-point FIR filter structure. - * @param[in] numTaps Number of filter coefficients in the filter. - * @param[in] *pCoeffs points to the filter coefficients buffer. - * @param[in] *pState points to the state buffer. - * @param[in] blockSize number of samples that are processed per call. - * @return none. - * - * Description: - * \par - * pCoeffs points to the array of filter coefficients stored in time reversed order: - *
    
- *    {b[numTaps-1], b[numTaps-2], b[N-2], ..., b[1], b[0]}    
- * 
- * \par - * pState points to the array of state variables. - * pState is of length numTaps+blockSize-1 samples, where blockSize is the number of input samples processed by each call to arm_fir_f32(). - */ - -void arm_fir_init_f32( - arm_fir_instance_f32 * S, - uint16_t numTaps, - float32_t * pCoeffs, - float32_t * pState, - uint32_t blockSize) -{ - /* Assign filter taps */ - S->numTaps = numTaps; - - /* Assign coefficient pointer */ - S->pCoeffs = pCoeffs; - - /* Clear state buffer and the size of state buffer is (blockSize + numTaps - 1) */ - memset(pState, 0, (numTaps + (blockSize - 1u)) * sizeof(float32_t)); - - /* Assign state pointer */ - S->pState = pState; - -} - -/** - * @} end of FIR group - */ diff --git a/gui/cmsis/arm_fir_init_q15.c b/gui/cmsis/arm_fir_init_q15.c deleted file mode 100644 index d976d73..0000000 --- a/gui/cmsis/arm_fir_init_q15.c +++ /dev/null @@ -1,154 +0,0 @@ -/* ---------------------------------------------------------------------- -* Copyright (C) 2010-2014 ARM Limited. All rights reserved. -* -* $Date: 19. March 2015 -* $Revision: V.1.4.5 -* -* Project: CMSIS DSP Library -* Title: arm_fir_init_q15.c -* -* Description: Q15 FIR filter initialization function. -* -* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0 -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* - Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* - Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in -* the documentation and/or other materials provided with the -* distribution. -* - Neither the name of ARM LIMITED nor the names of its contributors -* may be used to endorse or promote products derived from this -* software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -* POSSIBILITY OF SUCH DAMAGE. -* ------------------------------------------------------------------- */ - -#include "arm_math.h" - -/** - * @ingroup groupFilters - */ - -/** - * @addtogroup FIR - * @{ - */ - -/** - * @param[in,out] *S points to an instance of the Q15 FIR filter structure. - * @param[in] numTaps Number of filter coefficients in the filter. Must be even and greater than or equal to 4. - * @param[in] *pCoeffs points to the filter coefficients buffer. - * @param[in] *pState points to the state buffer. - * @param[in] blockSize is number of samples processed per call. - * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if - * numTaps is not greater than or equal to 4 and even. - * - * Description: - * \par - * pCoeffs points to the array of filter coefficients stored in time reversed order: - *
    
- *    {b[numTaps-1], b[numTaps-2], b[N-2], ..., b[1], b[0]}    
- * 
- * Note that numTaps must be even and greater than or equal to 4. - * To implement an odd length filter simply increase numTaps by 1 and set the last coefficient to zero. - * For example, to implement a filter with numTaps=3 and coefficients - *
    
- *     {0.3, -0.8, 0.3}    
- * 
- * set numTaps=4 and use the coefficients: - *
    
- *     {0.3, -0.8, 0.3, 0}.    
- * 
- * Similarly, to implement a two point filter - *
    
- *     {0.3, -0.3}    
- * 
- * set numTaps=4 and use the coefficients: - *
    
- *     {0.3, -0.3, 0, 0}.    
- * 
- * \par - * pState points to the array of state variables. - * pState is of length numTaps+blockSize, when running on Cortex-M4 and Cortex-M3 and is of length numTaps+blockSize-1, when running on Cortex-M0 where blockSize is the number of input samples processed by each call to arm_fir_q15(). - */ - -arm_status arm_fir_init_q15( - arm_fir_instance_q15 * S, - uint16_t numTaps, - q15_t * pCoeffs, - q15_t * pState, - uint32_t blockSize) -{ - arm_status status; - - -#ifndef ARM_MATH_CM0_FAMILY - - /* Run the below code for Cortex-M4 and Cortex-M3 */ - - /* The Number of filter coefficients in the filter must be even and at least 4 */ - if(numTaps & 0x1u) - { - status = ARM_MATH_ARGUMENT_ERROR; - } - else - { - /* Assign filter taps */ - S->numTaps = numTaps; - - /* Assign coefficient pointer */ - S->pCoeffs = pCoeffs; - - /* Clear the state buffer. The size is always (blockSize + numTaps ) */ - memset(pState, 0, (numTaps + (blockSize)) * sizeof(q15_t)); - - /* Assign state pointer */ - S->pState = pState; - - status = ARM_MATH_SUCCESS; - } - - return (status); - -#else - - /* Run the below code for Cortex-M0 */ - - /* Assign filter taps */ - S->numTaps = numTaps; - - /* Assign coefficient pointer */ - S->pCoeffs = pCoeffs; - - /* Clear the state buffer. The size is always (blockSize + numTaps - 1) */ - memset(pState, 0, (numTaps + (blockSize - 1u)) * sizeof(q15_t)); - - /* Assign state pointer */ - S->pState = pState; - - status = ARM_MATH_SUCCESS; - - return (status); - -#endif /* #ifndef ARM_MATH_CM0_FAMILY */ - -} - -/** - * @} end of FIR group - */ diff --git a/gui/cmsis/arm_fir_init_q31.c b/gui/cmsis/arm_fir_init_q31.c deleted file mode 100644 index 726cdfc..0000000 --- a/gui/cmsis/arm_fir_init_q31.c +++ /dev/null @@ -1,96 +0,0 @@ -/* ---------------------------------------------------------------------- -* Copyright (C) 2010-2014 ARM Limited. All rights reserved. -* -* $Date: 19. March 2015 -* $Revision: V.1.4.5 -* -* Project: CMSIS DSP Library -* Title: arm_fir_init_q31.c -* -* Description: Q31 FIR filter initialization function. -* -* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0 -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* - Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* - Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in -* the documentation and/or other materials provided with the -* distribution. -* - Neither the name of ARM LIMITED nor the names of its contributors -* may be used to endorse or promote products derived from this -* software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -* POSSIBILITY OF SUCH DAMAGE. -* -------------------------------------------------------------------- */ - -#include "arm_math.h" - -/** - * @ingroup groupFilters - */ - -/** - * @addtogroup FIR - * @{ - */ - -/** - * @details - * - * @param[in,out] *S points to an instance of the Q31 FIR filter structure. - * @param[in] numTaps Number of filter coefficients in the filter. - * @param[in] *pCoeffs points to the filter coefficients buffer. - * @param[in] *pState points to the state buffer. - * @param[in] blockSize number of samples that are processed per call. - * @return none. - * - * Description: - * \par - * pCoeffs points to the array of filter coefficients stored in time reversed order: - *
    
- *    {b[numTaps-1], b[numTaps-2], b[N-2], ..., b[1], b[0]}    
- * 
- * \par - * pState points to the array of state variables. - * pState is of length numTaps+blockSize-1 samples, where blockSize is the number of input samples processed by each call to arm_fir_q31(). - */ - -void arm_fir_init_q31( - arm_fir_instance_q31 * S, - uint16_t numTaps, - q31_t * pCoeffs, - q31_t * pState, - uint32_t blockSize) -{ - /* Assign filter taps */ - S->numTaps = numTaps; - - /* Assign coefficient pointer */ - S->pCoeffs = pCoeffs; - - /* Clear state buffer and state array size is (blockSize + numTaps - 1) */ - memset(pState, 0, (blockSize + ((uint32_t) numTaps - 1u)) * sizeof(q31_t)); - - /* Assign state pointer */ - S->pState = pState; - -} - -/** - * @} end of FIR group - */ diff --git a/gui/cmsis/arm_fir_init_q7.c b/gui/cmsis/arm_fir_init_q7.c deleted file mode 100644 index 083d58e..0000000 --- a/gui/cmsis/arm_fir_init_q7.c +++ /dev/null @@ -1,94 +0,0 @@ -/* ---------------------------------------------------------------------- -* Copyright (C) 2010-2014 ARM Limited. All rights reserved. -* -* $Date: 19. March 2015 -* $Revision: V.1.4.5 -* -* Project: CMSIS DSP Library -* Title: arm_fir_init_q7.c -* -* Description: Q7 FIR filter initialization function. -* -* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0 -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* - Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* - Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in -* the documentation and/or other materials provided with the -* distribution. -* - Neither the name of ARM LIMITED nor the names of its contributors -* may be used to endorse or promote products derived from this -* software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -* POSSIBILITY OF SUCH DAMAGE. -* ------------------------------------------------------------------- */ - -#include "arm_math.h" - -/** - * @ingroup groupFilters - */ - -/** - * @addtogroup FIR - * @{ - */ -/** - * @param[in,out] *S points to an instance of the Q7 FIR filter structure. - * @param[in] numTaps Number of filter coefficients in the filter. - * @param[in] *pCoeffs points to the filter coefficients buffer. - * @param[in] *pState points to the state buffer. - * @param[in] blockSize number of samples that are processed per call. - * @return none - * - * Description: - * \par - * pCoeffs points to the array of filter coefficients stored in time reversed order: - *
    
- *    {b[numTaps-1], b[numTaps-2], b[N-2], ..., b[1], b[0]}    
- * 
- * \par - * pState points to the array of state variables. - * pState is of length numTaps+blockSize-1 samples, where blockSize is the number of input samples processed by each call to arm_fir_q7(). - */ - -void arm_fir_init_q7( - arm_fir_instance_q7 * S, - uint16_t numTaps, - q7_t * pCoeffs, - q7_t * pState, - uint32_t blockSize) -{ - - /* Assign filter taps */ - S->numTaps = numTaps; - - /* Assign coefficient pointer */ - S->pCoeffs = pCoeffs; - - /* Clear the state buffer. The size is always (blockSize + numTaps - 1) */ - memset(pState, 0, (numTaps + (blockSize - 1u)) * sizeof(q7_t)); - - /* Assign state pointer */ - S->pState = pState; - -} - -/** - * @} end of FIR group - */ diff --git a/gui/cmsis/arm_fir_q15.c b/gui/cmsis/arm_fir_q15.c deleted file mode 100644 index f3c595f..0000000 --- a/gui/cmsis/arm_fir_q15.c +++ /dev/null @@ -1,691 +0,0 @@ -/* ---------------------------------------------------------------------- -* Copyright (C) 2010-2014 ARM Limited. All rights reserved. -* -* $Date: 19. March 2015 -* $Revision: V.1.4.5 -* -* Project: CMSIS DSP Library -* Title: arm_fir_q15.c -* -* Description: Q15 FIR filter processing function. -* -* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0 -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* - Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* - Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in -* the documentation and/or other materials provided with the -* distribution. -* - Neither the name of ARM LIMITED nor the names of its contributors -* may be used to endorse or promote products derived from this -* software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -* POSSIBILITY OF SUCH DAMAGE. -* -------------------------------------------------------------------- */ - -#include "arm_math.h" - -/** - * @ingroup groupFilters - */ - -/** - * @addtogroup FIR - * @{ - */ - -/** - * @brief Processing function for the Q15 FIR filter. - * @param[in] *S points to an instance of the Q15 FIR structure. - * @param[in] *pSrc points to the block of input data. - * @param[out] *pDst points to the block of output data. - * @param[in] blockSize number of samples to process per call. - * @return none. - * - * - * \par Restrictions - * If the silicon does not support unaligned memory access enable the macro UNALIGNED_SUPPORT_DISABLE - * In this case input, output, state buffers should be aligned by 32-bit - * - * Scaling and Overflow Behavior: - * \par - * The function is implemented using a 64-bit internal accumulator. - * Both coefficients and state variables are represented in 1.15 format and multiplications yield a 2.30 result. - * The 2.30 intermediate results are accumulated in a 64-bit accumulator in 34.30 format. - * There is no risk of internal overflow with this approach and the full precision of intermediate multiplications is preserved. - * After all additions have been performed, the accumulator is truncated to 34.15 format by discarding low 15 bits. - * Lastly, the accumulator is saturated to yield a result in 1.15 format. - * - * \par - * Refer to the function arm_fir_fast_q15() for a faster but less precise implementation of this function. - */ - -#ifndef ARM_MATH_CM0_FAMILY - -/* Run the below code for Cortex-M4 and Cortex-M3 */ - -#ifndef UNALIGNED_SUPPORT_DISABLE - - -void arm_fir_q15( - const arm_fir_instance_q15 * S, - q15_t * pSrc, - q15_t * pDst, - uint32_t blockSize) -{ - q15_t *pState = S->pState; /* State pointer */ - q15_t *pCoeffs = S->pCoeffs; /* Coefficient pointer */ - q15_t *pStateCurnt; /* Points to the current sample of the state */ - q15_t *px1; /* Temporary q15 pointer for state buffer */ - q15_t *pb; /* Temporary pointer for coefficient buffer */ - q31_t x0, x1, x2, x3, c0; /* Temporary variables to hold SIMD state and coefficient values */ - q63_t acc0, acc1, acc2, acc3; /* Accumulators */ - uint32_t numTaps = S->numTaps; /* Number of taps in the filter */ - uint32_t tapCnt, blkCnt; /* Loop counters */ - - - /* S->pState points to state array which contains previous frame (numTaps - 1) samples */ - /* pStateCurnt points to the location where the new input data should be written */ - pStateCurnt = &(S->pState[(numTaps - 1u)]); - - /* Apply loop unrolling and compute 4 output values simultaneously. - * The variables acc0 ... acc3 hold output values that are being computed: - * - * acc0 = b[numTaps-1] * x[n-numTaps-1] + b[numTaps-2] * x[n-numTaps-2] + b[numTaps-3] * x[n-numTaps-3] +...+ b[0] * x[0] - * acc1 = b[numTaps-1] * x[n-numTaps] + b[numTaps-2] * x[n-numTaps-1] + b[numTaps-3] * x[n-numTaps-2] +...+ b[0] * x[1] - * acc2 = b[numTaps-1] * x[n-numTaps+1] + b[numTaps-2] * x[n-numTaps] + b[numTaps-3] * x[n-numTaps-1] +...+ b[0] * x[2] - * acc3 = b[numTaps-1] * x[n-numTaps+2] + b[numTaps-2] * x[n-numTaps+1] + b[numTaps-3] * x[n-numTaps] +...+ b[0] * x[3] - */ - - blkCnt = blockSize >> 2; - - /* First part of the processing with loop unrolling. Compute 4 outputs at a time. - ** a second loop below computes the remaining 1 to 3 samples. */ - while(blkCnt > 0u) - { - /* Copy four new input samples into the state buffer. - ** Use 32-bit SIMD to move the 16-bit data. Only requires two copies. */ - *__SIMD32(pStateCurnt)++ = *__SIMD32(pSrc)++; - *__SIMD32(pStateCurnt)++ = *__SIMD32(pSrc)++; - - /* Set all accumulators to zero */ - acc0 = 0; - acc1 = 0; - acc2 = 0; - acc3 = 0; - - /* Initialize state pointer of type q15 */ - px1 = pState; - - /* Initialize coeff pointer of type q31 */ - pb = pCoeffs; - - /* Read the first two samples from the state buffer: x[n-N], x[n-N-1] */ - x0 = _SIMD32_OFFSET(px1); - - /* Read the third and forth samples from the state buffer: x[n-N-1], x[n-N-2] */ - x1 = _SIMD32_OFFSET(px1 + 1u); - - px1 += 2u; - - /* Loop over the number of taps. Unroll by a factor of 4. - ** Repeat until we've computed numTaps-4 coefficients. */ - tapCnt = numTaps >> 2; - - while(tapCnt > 0u) - { - /* Read the first two coefficients using SIMD: b[N] and b[N-1] coefficients */ - c0 = *__SIMD32(pb)++; - - /* acc0 += b[N] * x[n-N] + b[N-1] * x[n-N-1] */ - acc0 = __SMLALD(x0, c0, acc0); - - /* acc1 += b[N] * x[n-N-1] + b[N-1] * x[n-N-2] */ - acc1 = __SMLALD(x1, c0, acc1); - - /* Read state x[n-N-2], x[n-N-3] */ - x2 = _SIMD32_OFFSET(px1); - - /* Read state x[n-N-3], x[n-N-4] */ - x3 = _SIMD32_OFFSET(px1 + 1u); - - /* acc2 += b[N] * x[n-N-2] + b[N-1] * x[n-N-3] */ - acc2 = __SMLALD(x2, c0, acc2); - - /* acc3 += b[N] * x[n-N-3] + b[N-1] * x[n-N-4] */ - acc3 = __SMLALD(x3, c0, acc3); - - /* Read coefficients b[N-2], b[N-3] */ - c0 = *__SIMD32(pb)++; - - /* acc0 += b[N-2] * x[n-N-2] + b[N-3] * x[n-N-3] */ - acc0 = __SMLALD(x2, c0, acc0); - - /* acc1 += b[N-2] * x[n-N-3] + b[N-3] * x[n-N-4] */ - acc1 = __SMLALD(x3, c0, acc1); - - /* Read state x[n-N-4], x[n-N-5] */ - x0 = _SIMD32_OFFSET(px1 + 2u); - - /* Read state x[n-N-5], x[n-N-6] */ - x1 = _SIMD32_OFFSET(px1 + 3u); - - /* acc2 += b[N-2] * x[n-N-4] + b[N-3] * x[n-N-5] */ - acc2 = __SMLALD(x0, c0, acc2); - - /* acc3 += b[N-2] * x[n-N-5] + b[N-3] * x[n-N-6] */ - acc3 = __SMLALD(x1, c0, acc3); - - px1 += 4u; - - tapCnt--; - - } - - - /* If the filter length is not a multiple of 4, compute the remaining filter taps. - ** This is always be 2 taps since the filter length is even. */ - if((numTaps & 0x3u) != 0u) - { - /* Read 2 coefficients */ - c0 = *__SIMD32(pb)++; - - /* Fetch 4 state variables */ - x2 = _SIMD32_OFFSET(px1); - - x3 = _SIMD32_OFFSET(px1 + 1u); - - /* Perform the multiply-accumulates */ - acc0 = __SMLALD(x0, c0, acc0); - - px1 += 2u; - - acc1 = __SMLALD(x1, c0, acc1); - acc2 = __SMLALD(x2, c0, acc2); - acc3 = __SMLALD(x3, c0, acc3); - } - - /* The results in the 4 accumulators are in 2.30 format. Convert to 1.15 with saturation. - ** Then store the 4 outputs in the destination buffer. */ - -#ifndef ARM_MATH_BIG_ENDIAN - - *__SIMD32(pDst)++ = - __PKHBT(__SSAT((acc0 >> 15), 16), __SSAT((acc1 >> 15), 16), 16); - *__SIMD32(pDst)++ = - __PKHBT(__SSAT((acc2 >> 15), 16), __SSAT((acc3 >> 15), 16), 16); - -#else - - *__SIMD32(pDst)++ = - __PKHBT(__SSAT((acc1 >> 15), 16), __SSAT((acc0 >> 15), 16), 16); - *__SIMD32(pDst)++ = - __PKHBT(__SSAT((acc3 >> 15), 16), __SSAT((acc2 >> 15), 16), 16); - -#endif /* #ifndef ARM_MATH_BIG_ENDIAN */ - - - - /* Advance the state pointer by 4 to process the next group of 4 samples */ - pState = pState + 4; - - /* Decrement the loop counter */ - blkCnt--; - } - - /* If the blockSize is not a multiple of 4, compute any remaining output samples here. - ** No loop unrolling is used. */ - blkCnt = blockSize % 0x4u; - while(blkCnt > 0u) - { - /* Copy two samples into state buffer */ - *pStateCurnt++ = *pSrc++; - - /* Set the accumulator to zero */ - acc0 = 0; - - /* Initialize state pointer of type q15 */ - px1 = pState; - - /* Initialize coeff pointer of type q31 */ - pb = pCoeffs; - - tapCnt = numTaps >> 1; - - do - { - - c0 = *__SIMD32(pb)++; - x0 = *__SIMD32(px1)++; - - acc0 = __SMLALD(x0, c0, acc0); - tapCnt--; - } - while(tapCnt > 0u); - - /* The result is in 2.30 format. Convert to 1.15 with saturation. - ** Then store the output in the destination buffer. */ - *pDst++ = (q15_t) (__SSAT((acc0 >> 15), 16)); - - /* Advance state pointer by 1 for the next sample */ - pState = pState + 1; - - /* Decrement the loop counter */ - blkCnt--; - } - - /* Processing is complete. - ** Now copy the last numTaps - 1 samples to the satrt of the state buffer. - ** This prepares the state buffer for the next function call. */ - - /* Points to the start of the state buffer */ - pStateCurnt = S->pState; - - /* Calculation of count for copying integer writes */ - tapCnt = (numTaps - 1u) >> 2; - - while(tapCnt > 0u) - { - - /* Copy state values to start of state buffer */ - *__SIMD32(pStateCurnt)++ = *__SIMD32(pState)++; - *__SIMD32(pStateCurnt)++ = *__SIMD32(pState)++; - - tapCnt--; - - } - - /* Calculation of count for remaining q15_t data */ - tapCnt = (numTaps - 1u) % 0x4u; - - /* copy remaining data */ - while(tapCnt > 0u) - { - *pStateCurnt++ = *pState++; - - /* Decrement the loop counter */ - tapCnt--; - } -} - -#else /* UNALIGNED_SUPPORT_DISABLE */ - -void arm_fir_q15( - const arm_fir_instance_q15 * S, - q15_t * pSrc, - q15_t * pDst, - uint32_t blockSize) -{ - q15_t *pState = S->pState; /* State pointer */ - q15_t *pCoeffs = S->pCoeffs; /* Coefficient pointer */ - q15_t *pStateCurnt; /* Points to the current sample of the state */ - q63_t acc0, acc1, acc2, acc3; /* Accumulators */ - q15_t *pb; /* Temporary pointer for coefficient buffer */ - q15_t *px; /* Temporary q31 pointer for SIMD state buffer accesses */ - q31_t x0, x1, x2, c0; /* Temporary variables to hold SIMD state and coefficient values */ - uint32_t numTaps = S->numTaps; /* Number of taps in the filter */ - uint32_t tapCnt, blkCnt; /* Loop counters */ - - - /* S->pState points to state array which contains previous frame (numTaps - 1) samples */ - /* pStateCurnt points to the location where the new input data should be written */ - pStateCurnt = &(S->pState[(numTaps - 1u)]); - - /* Apply loop unrolling and compute 4 output values simultaneously. - * The variables acc0 ... acc3 hold output values that are being computed: - * - * acc0 = b[numTaps-1] * x[n-numTaps-1] + b[numTaps-2] * x[n-numTaps-2] + b[numTaps-3] * x[n-numTaps-3] +...+ b[0] * x[0] - * acc1 = b[numTaps-1] * x[n-numTaps] + b[numTaps-2] * x[n-numTaps-1] + b[numTaps-3] * x[n-numTaps-2] +...+ b[0] * x[1] - * acc2 = b[numTaps-1] * x[n-numTaps+1] + b[numTaps-2] * x[n-numTaps] + b[numTaps-3] * x[n-numTaps-1] +...+ b[0] * x[2] - * acc3 = b[numTaps-1] * x[n-numTaps+2] + b[numTaps-2] * x[n-numTaps+1] + b[numTaps-3] * x[n-numTaps] +...+ b[0] * x[3] - */ - - blkCnt = blockSize >> 2; - - /* First part of the processing with loop unrolling. Compute 4 outputs at a time. - ** a second loop below computes the remaining 1 to 3 samples. */ - while(blkCnt > 0u) - { - /* Copy four new input samples into the state buffer. - ** Use 32-bit SIMD to move the 16-bit data. Only requires two copies. */ - *pStateCurnt++ = *pSrc++; - *pStateCurnt++ = *pSrc++; - *pStateCurnt++ = *pSrc++; - *pStateCurnt++ = *pSrc++; - - - /* Set all accumulators to zero */ - acc0 = 0; - acc1 = 0; - acc2 = 0; - acc3 = 0; - - /* Typecast q15_t pointer to q31_t pointer for state reading in q31_t */ - px = pState; - - /* Typecast q15_t pointer to q31_t pointer for coefficient reading in q31_t */ - pb = pCoeffs; - - /* Read the first two samples from the state buffer: x[n-N], x[n-N-1] */ - x0 = *__SIMD32(px)++; - - /* Read the third and forth samples from the state buffer: x[n-N-2], x[n-N-3] */ - x2 = *__SIMD32(px)++; - - /* Loop over the number of taps. Unroll by a factor of 4. - ** Repeat until we've computed numTaps-(numTaps%4) coefficients. */ - tapCnt = numTaps >> 2; - - while(tapCnt > 0) - { - /* Read the first two coefficients using SIMD: b[N] and b[N-1] coefficients */ - c0 = *__SIMD32(pb)++; - - /* acc0 += b[N] * x[n-N] + b[N-1] * x[n-N-1] */ - acc0 = __SMLALD(x0, c0, acc0); - - /* acc2 += b[N] * x[n-N-2] + b[N-1] * x[n-N-3] */ - acc2 = __SMLALD(x2, c0, acc2); - - /* pack x[n-N-1] and x[n-N-2] */ -#ifndef ARM_MATH_BIG_ENDIAN - x1 = __PKHBT(x2, x0, 0); -#else - x1 = __PKHBT(x0, x2, 0); -#endif - - /* Read state x[n-N-4], x[n-N-5] */ - x0 = _SIMD32_OFFSET(px); - - /* acc1 += b[N] * x[n-N-1] + b[N-1] * x[n-N-2] */ - acc1 = __SMLALDX(x1, c0, acc1); - - /* pack x[n-N-3] and x[n-N-4] */ -#ifndef ARM_MATH_BIG_ENDIAN - x1 = __PKHBT(x0, x2, 0); -#else - x1 = __PKHBT(x2, x0, 0); -#endif - - /* acc3 += b[N] * x[n-N-3] + b[N-1] * x[n-N-4] */ - acc3 = __SMLALDX(x1, c0, acc3); - - /* Read coefficients b[N-2], b[N-3] */ - c0 = *__SIMD32(pb)++; - - /* acc0 += b[N-2] * x[n-N-2] + b[N-3] * x[n-N-3] */ - acc0 = __SMLALD(x2, c0, acc0); - - /* Read state x[n-N-6], x[n-N-7] with offset */ - x2 = _SIMD32_OFFSET(px + 2u); - - /* acc2 += b[N-2] * x[n-N-4] + b[N-3] * x[n-N-5] */ - acc2 = __SMLALD(x0, c0, acc2); - - /* acc1 += b[N-2] * x[n-N-3] + b[N-3] * x[n-N-4] */ - acc1 = __SMLALDX(x1, c0, acc1); - - /* pack x[n-N-5] and x[n-N-6] */ -#ifndef ARM_MATH_BIG_ENDIAN - x1 = __PKHBT(x2, x0, 0); -#else - x1 = __PKHBT(x0, x2, 0); -#endif - - /* acc3 += b[N-2] * x[n-N-5] + b[N-3] * x[n-N-6] */ - acc3 = __SMLALDX(x1, c0, acc3); - - /* Update state pointer for next state reading */ - px += 4u; - - /* Decrement tap count */ - tapCnt--; - - } - - /* If the filter length is not a multiple of 4, compute the remaining filter taps. - ** This is always be 2 taps since the filter length is even. */ - if((numTaps & 0x3u) != 0u) - { - - /* Read last two coefficients */ - c0 = *__SIMD32(pb)++; - - /* Perform the multiply-accumulates */ - acc0 = __SMLALD(x0, c0, acc0); - acc2 = __SMLALD(x2, c0, acc2); - - /* pack state variables */ -#ifndef ARM_MATH_BIG_ENDIAN - x1 = __PKHBT(x2, x0, 0); -#else - x1 = __PKHBT(x0, x2, 0); -#endif - - /* Read last state variables */ - x0 = *__SIMD32(px); - - /* Perform the multiply-accumulates */ - acc1 = __SMLALDX(x1, c0, acc1); - - /* pack state variables */ -#ifndef ARM_MATH_BIG_ENDIAN - x1 = __PKHBT(x0, x2, 0); -#else - x1 = __PKHBT(x2, x0, 0); -#endif - - /* Perform the multiply-accumulates */ - acc3 = __SMLALDX(x1, c0, acc3); - } - - /* The results in the 4 accumulators are in 2.30 format. Convert to 1.15 with saturation. - ** Then store the 4 outputs in the destination buffer. */ - -#ifndef ARM_MATH_BIG_ENDIAN - - *__SIMD32(pDst)++ = - __PKHBT(__SSAT((acc0 >> 15), 16), __SSAT((acc1 >> 15), 16), 16); - - *__SIMD32(pDst)++ = - __PKHBT(__SSAT((acc2 >> 15), 16), __SSAT((acc3 >> 15), 16), 16); - -#else - - *__SIMD32(pDst)++ = - __PKHBT(__SSAT((acc1 >> 15), 16), __SSAT((acc0 >> 15), 16), 16); - - *__SIMD32(pDst)++ = - __PKHBT(__SSAT((acc3 >> 15), 16), __SSAT((acc2 >> 15), 16), 16); - -#endif /* #ifndef ARM_MATH_BIG_ENDIAN */ - - /* Advance the state pointer by 4 to process the next group of 4 samples */ - pState = pState + 4; - - /* Decrement the loop counter */ - blkCnt--; - } - - /* If the blockSize is not a multiple of 4, compute any remaining output samples here. - ** No loop unrolling is used. */ - blkCnt = blockSize % 0x4u; - while(blkCnt > 0u) - { - /* Copy two samples into state buffer */ - *pStateCurnt++ = *pSrc++; - - /* Set the accumulator to zero */ - acc0 = 0; - - /* Use SIMD to hold states and coefficients */ - px = pState; - pb = pCoeffs; - - tapCnt = numTaps >> 1u; - - do - { - acc0 += (q31_t) * px++ * *pb++; - acc0 += (q31_t) * px++ * *pb++; - tapCnt--; - } - while(tapCnt > 0u); - - /* The result is in 2.30 format. Convert to 1.15 with saturation. - ** Then store the output in the destination buffer. */ - *pDst++ = (q15_t) (__SSAT((acc0 >> 15), 16)); - - /* Advance state pointer by 1 for the next sample */ - pState = pState + 1u; - - /* Decrement the loop counter */ - blkCnt--; - } - - /* Processing is complete. - ** Now copy the last numTaps - 1 samples to the satrt of the state buffer. - ** This prepares the state buffer for the next function call. */ - - /* Points to the start of the state buffer */ - pStateCurnt = S->pState; - - /* Calculation of count for copying integer writes */ - tapCnt = (numTaps - 1u) >> 2; - - while(tapCnt > 0u) - { - *pStateCurnt++ = *pState++; - *pStateCurnt++ = *pState++; - *pStateCurnt++ = *pState++; - *pStateCurnt++ = *pState++; - - tapCnt--; - - } - - /* Calculation of count for remaining q15_t data */ - tapCnt = (numTaps - 1u) % 0x4u; - - /* copy remaining data */ - while(tapCnt > 0u) - { - *pStateCurnt++ = *pState++; - - /* Decrement the loop counter */ - tapCnt--; - } -} - - -#endif /* #ifndef UNALIGNED_SUPPORT_DISABLE */ - -#else /* ARM_MATH_CM0_FAMILY */ - - -/* Run the below code for Cortex-M0 */ - -void arm_fir_q15( - const arm_fir_instance_q15 * S, - q15_t * pSrc, - q15_t * pDst, - uint32_t blockSize) -{ - q15_t *pState = S->pState; /* State pointer */ - q15_t *pCoeffs = S->pCoeffs; /* Coefficient pointer */ - q15_t *pStateCurnt; /* Points to the current sample of the state */ - - - - q15_t *px; /* Temporary pointer for state buffer */ - q15_t *pb; /* Temporary pointer for coefficient buffer */ - q63_t acc; /* Accumulator */ - uint32_t numTaps = S->numTaps; /* Number of nTaps in the filter */ - uint32_t tapCnt, blkCnt; /* Loop counters */ - - /* S->pState buffer contains previous frame (numTaps - 1) samples */ - /* pStateCurnt points to the location where the new input data should be written */ - pStateCurnt = &(S->pState[(numTaps - 1u)]); - - /* Initialize blkCnt with blockSize */ - blkCnt = blockSize; - - while(blkCnt > 0u) - { - /* Copy one sample at a time into state buffer */ - *pStateCurnt++ = *pSrc++; - - /* Set the accumulator to zero */ - acc = 0; - - /* Initialize state pointer */ - px = pState; - - /* Initialize Coefficient pointer */ - pb = pCoeffs; - - tapCnt = numTaps; - - /* Perform the multiply-accumulates */ - do - { - /* acc = b[numTaps-1] * x[n-numTaps-1] + b[numTaps-2] * x[n-numTaps-2] + b[numTaps-3] * x[n-numTaps-3] +...+ b[0] * x[0] */ - acc += (q31_t) * px++ * *pb++; - tapCnt--; - } while(tapCnt > 0u); - - /* The result is in 2.30 format. Convert to 1.15 - ** Then store the output in the destination buffer. */ - *pDst++ = (q15_t) __SSAT((acc >> 15u), 16); - - /* Advance state pointer by 1 for the next sample */ - pState = pState + 1; - - /* Decrement the samples loop counter */ - blkCnt--; - } - - /* Processing is complete. - ** Now copy the last numTaps - 1 samples to the satrt of the state buffer. - ** This prepares the state buffer for the next function call. */ - - /* Points to the start of the state buffer */ - pStateCurnt = S->pState; - - /* Copy numTaps number of values */ - tapCnt = (numTaps - 1u); - - /* copy data */ - while(tapCnt > 0u) - { - *pStateCurnt++ = *pState++; - - /* Decrement the loop counter */ - tapCnt--; - } - -} - -#endif /* #ifndef ARM_MATH_CM0_FAMILY */ - - - - -/** - * @} end of FIR group - */ diff --git a/gui/cmsis/arm_fir_q31.c b/gui/cmsis/arm_fir_q31.c deleted file mode 100644 index af5707f..0000000 --- a/gui/cmsis/arm_fir_q31.c +++ /dev/null @@ -1,365 +0,0 @@ -/* ---------------------------------------------------------------------- -* Copyright (C) 2010-2014 ARM Limited. All rights reserved. -* -* $Date: 19. March 2015 -* $Revision: V.1.4.5 -* -* Project: CMSIS DSP Library -* Title: arm_fir_q31.c -* -* Description: Q31 FIR filter processing function. -* -* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0 -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* - Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* - Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in -* the documentation and/or other materials provided with the -* distribution. -* - Neither the name of ARM LIMITED nor the names of its contributors -* may be used to endorse or promote products derived from this -* software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -* POSSIBILITY OF SUCH DAMAGE. -* -------------------------------------------------------------------- */ - -#include "arm_math.h" - -/** - * @ingroup groupFilters - */ - -/** - * @addtogroup FIR - * @{ - */ - -/** - * @param[in] *S points to an instance of the Q31 FIR filter structure. - * @param[in] *pSrc points to the block of input data. - * @param[out] *pDst points to the block of output data. - * @param[in] blockSize number of samples to process per call. - * @return none. - * - * @details - * Scaling and Overflow Behavior: - * \par - * The function is implemented using an internal 64-bit accumulator. - * The accumulator has a 2.62 format and maintains full precision of the intermediate multiplication results but provides only a single guard bit. - * Thus, if the accumulator result overflows it wraps around rather than clip. - * In order to avoid overflows completely the input signal must be scaled down by log2(numTaps) bits. - * After all multiply-accumulates are performed, the 2.62 accumulator is right shifted by 31 bits and saturated to 1.31 format to yield the final result. - * - * \par - * Refer to the function arm_fir_fast_q31() for a faster but less precise implementation of this filter for Cortex-M3 and Cortex-M4. - */ - -void arm_fir_q31( - const arm_fir_instance_q31 * S, - q31_t * pSrc, - q31_t * pDst, - uint32_t blockSize) -{ - q31_t *pState = S->pState; /* State pointer */ - q31_t *pCoeffs = S->pCoeffs; /* Coefficient pointer */ - q31_t *pStateCurnt; /* Points to the current sample of the state */ - - -#ifndef ARM_MATH_CM0_FAMILY - - /* Run the below code for Cortex-M4 and Cortex-M3 */ - - q31_t x0, x1, x2; /* Temporary variables to hold state */ - q31_t c0; /* Temporary variable to hold coefficient value */ - q31_t *px; /* Temporary pointer for state */ - q31_t *pb; /* Temporary pointer for coefficient buffer */ - q63_t acc0, acc1, acc2; /* Accumulators */ - uint32_t numTaps = S->numTaps; /* Number of filter coefficients in the filter */ - uint32_t i, tapCnt, blkCnt, tapCntN3; /* Loop counters */ - - /* S->pState points to state array which contains previous frame (numTaps - 1) samples */ - /* pStateCurnt points to the location where the new input data should be written */ - pStateCurnt = &(S->pState[(numTaps - 1u)]); - - /* Apply loop unrolling and compute 4 output values simultaneously. - * The variables acc0 ... acc3 hold output values that are being computed: - * - * acc0 = b[numTaps-1] * x[n-numTaps-1] + b[numTaps-2] * x[n-numTaps-2] + b[numTaps-3] * x[n-numTaps-3] +...+ b[0] * x[0] - * acc1 = b[numTaps-1] * x[n-numTaps] + b[numTaps-2] * x[n-numTaps-1] + b[numTaps-3] * x[n-numTaps-2] +...+ b[0] * x[1] - * acc2 = b[numTaps-1] * x[n-numTaps+1] + b[numTaps-2] * x[n-numTaps] + b[numTaps-3] * x[n-numTaps-1] +...+ b[0] * x[2] - * acc3 = b[numTaps-1] * x[n-numTaps+2] + b[numTaps-2] * x[n-numTaps+1] + b[numTaps-3] * x[n-numTaps] +...+ b[0] * x[3] - */ - blkCnt = blockSize / 3; - blockSize = blockSize - (3 * blkCnt); - - tapCnt = numTaps / 3; - tapCntN3 = numTaps - (3 * tapCnt); - - /* First part of the processing with loop unrolling. Compute 4 outputs at a time. - ** a second loop below computes the remaining 1 to 3 samples. */ - while(blkCnt > 0u) - { - /* Copy three new input samples into the state buffer */ - *pStateCurnt++ = *pSrc++; - *pStateCurnt++ = *pSrc++; - *pStateCurnt++ = *pSrc++; - - /* Set all accumulators to zero */ - acc0 = 0; - acc1 = 0; - acc2 = 0; - - /* Initialize state pointer */ - px = pState; - - /* Initialize coefficient pointer */ - pb = pCoeffs; - - /* Read the first two samples from the state buffer: - * x[n-numTaps], x[n-numTaps-1] */ - x0 = *(px++); - x1 = *(px++); - - /* Loop unrolling. Process 3 taps at a time. */ - i = tapCnt; - - while(i > 0u) - { - /* Read the b[numTaps] coefficient */ - c0 = *pb; - - /* Read x[n-numTaps-2] sample */ - x2 = *(px++); - - /* Perform the multiply-accumulates */ - acc0 += ((q63_t) x0 * c0); - acc1 += ((q63_t) x1 * c0); - acc2 += ((q63_t) x2 * c0); - - /* Read the coefficient and state */ - c0 = *(pb + 1u); - x0 = *(px++); - - /* Perform the multiply-accumulates */ - acc0 += ((q63_t) x1 * c0); - acc1 += ((q63_t) x2 * c0); - acc2 += ((q63_t) x0 * c0); - - /* Read the coefficient and state */ - c0 = *(pb + 2u); - x1 = *(px++); - - /* update coefficient pointer */ - pb += 3u; - - /* Perform the multiply-accumulates */ - acc0 += ((q63_t) x2 * c0); - acc1 += ((q63_t) x0 * c0); - acc2 += ((q63_t) x1 * c0); - - /* Decrement the loop counter */ - i--; - } - - /* If the filter length is not a multiple of 3, compute the remaining filter taps */ - - i = tapCntN3; - - while(i > 0u) - { - /* Read coefficients */ - c0 = *(pb++); - - /* Fetch 1 state variable */ - x2 = *(px++); - - /* Perform the multiply-accumulates */ - acc0 += ((q63_t) x0 * c0); - acc1 += ((q63_t) x1 * c0); - acc2 += ((q63_t) x2 * c0); - - /* Reuse the present sample states for next sample */ - x0 = x1; - x1 = x2; - - /* Decrement the loop counter */ - i--; - } - - /* Advance the state pointer by 3 to process the next group of 3 samples */ - pState = pState + 3; - - /* The results in the 3 accumulators are in 2.30 format. Convert to 1.31 - ** Then store the 3 outputs in the destination buffer. */ - *pDst++ = (q31_t) (acc0 >> 31u); - *pDst++ = (q31_t) (acc1 >> 31u); - *pDst++ = (q31_t) (acc2 >> 31u); - - /* Decrement the samples loop counter */ - blkCnt--; - } - - /* If the blockSize is not a multiple of 3, compute any remaining output samples here. - ** No loop unrolling is used. */ - - while(blockSize > 0u) - { - /* Copy one sample at a time into state buffer */ - *pStateCurnt++ = *pSrc++; - - /* Set the accumulator to zero */ - acc0 = 0; - - /* Initialize state pointer */ - px = pState; - - /* Initialize Coefficient pointer */ - pb = (pCoeffs); - - i = numTaps; - - /* Perform the multiply-accumulates */ - do - { - acc0 += (q63_t) * (px++) * (*(pb++)); - i--; - } while(i > 0u); - - /* The result is in 2.62 format. Convert to 1.31 - ** Then store the output in the destination buffer. */ - *pDst++ = (q31_t) (acc0 >> 31u); - - /* Advance state pointer by 1 for the next sample */ - pState = pState + 1; - - /* Decrement the samples loop counter */ - blockSize--; - } - - /* Processing is complete. - ** Now copy the last numTaps - 1 samples to the satrt of the state buffer. - ** This prepares the state buffer for the next function call. */ - - /* Points to the start of the state buffer */ - pStateCurnt = S->pState; - - tapCnt = (numTaps - 1u) >> 2u; - - /* copy data */ - while(tapCnt > 0u) - { - *pStateCurnt++ = *pState++; - *pStateCurnt++ = *pState++; - *pStateCurnt++ = *pState++; - *pStateCurnt++ = *pState++; - - /* Decrement the loop counter */ - tapCnt--; - } - - /* Calculate remaining number of copies */ - tapCnt = (numTaps - 1u) % 0x4u; - - /* Copy the remaining q31_t data */ - while(tapCnt > 0u) - { - *pStateCurnt++ = *pState++; - - /* Decrement the loop counter */ - tapCnt--; - } - -#else - -/* Run the below code for Cortex-M0 */ - - q31_t *px; /* Temporary pointer for state */ - q31_t *pb; /* Temporary pointer for coefficient buffer */ - q63_t acc; /* Accumulator */ - uint32_t numTaps = S->numTaps; /* Length of the filter */ - uint32_t i, tapCnt, blkCnt; /* Loop counters */ - - /* S->pState buffer contains previous frame (numTaps - 1) samples */ - /* pStateCurnt points to the location where the new input data should be written */ - pStateCurnt = &(S->pState[(numTaps - 1u)]); - - /* Initialize blkCnt with blockSize */ - blkCnt = blockSize; - - while(blkCnt > 0u) - { - /* Copy one sample at a time into state buffer */ - *pStateCurnt++ = *pSrc++; - - /* Set the accumulator to zero */ - acc = 0; - - /* Initialize state pointer */ - px = pState; - - /* Initialize Coefficient pointer */ - pb = pCoeffs; - - i = numTaps; - - /* Perform the multiply-accumulates */ - do - { - /* acc = b[numTaps-1] * x[n-numTaps-1] + b[numTaps-2] * x[n-numTaps-2] + b[numTaps-3] * x[n-numTaps-3] +...+ b[0] * x[0] */ - acc += (q63_t) * px++ * *pb++; - i--; - } while(i > 0u); - - /* The result is in 2.62 format. Convert to 1.31 - ** Then store the output in the destination buffer. */ - *pDst++ = (q31_t) (acc >> 31u); - - /* Advance state pointer by 1 for the next sample */ - pState = pState + 1; - - /* Decrement the samples loop counter */ - blkCnt--; - } - - /* Processing is complete. - ** Now copy the last numTaps - 1 samples to the starting of the state buffer. - ** This prepares the state buffer for the next function call. */ - - /* Points to the start of the state buffer */ - pStateCurnt = S->pState; - - /* Copy numTaps number of values */ - tapCnt = numTaps - 1u; - - /* Copy the data */ - while(tapCnt > 0u) - { - *pStateCurnt++ = *pState++; - - /* Decrement the loop counter */ - tapCnt--; - } - - -#endif /* #ifndef ARM_MATH_CM0_FAMILY */ - -} - -/** - * @} end of FIR group - */ diff --git a/gui/cmsis/arm_fir_q7.c b/gui/cmsis/arm_fir_q7.c deleted file mode 100644 index 54a30e2..0000000 --- a/gui/cmsis/arm_fir_q7.c +++ /dev/null @@ -1,397 +0,0 @@ -/* ---------------------------------------------------------------------- -* Copyright (C) 2010-2014 ARM Limited. All rights reserved. -* -* $Date: 19. March 2015 -* $Revision: V.1.4.5 -* -* Project: CMSIS DSP Library -* Title: arm_fir_q7.c -* -* Description: Q7 FIR filter processing function. -* -* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0 -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* - Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* - Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in -* the documentation and/or other materials provided with the -* distribution. -* - Neither the name of ARM LIMITED nor the names of its contributors -* may be used to endorse or promote products derived from this -* software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -* POSSIBILITY OF SUCH DAMAGE. -* -------------------------------------------------------------------- */ - -#include "arm_math.h" - -/** - * @ingroup groupFilters - */ - -/** - * @addtogroup FIR - * @{ - */ - -/** - * @param[in] *S points to an instance of the Q7 FIR filter structure. - * @param[in] *pSrc points to the block of input data. - * @param[out] *pDst points to the block of output data. - * @param[in] blockSize number of samples to process per call. - * @return none. - * - * Scaling and Overflow Behavior: - * \par - * The function is implemented using a 32-bit internal accumulator. - * Both coefficients and state variables are represented in 1.7 format and multiplications yield a 2.14 result. - * The 2.14 intermediate results are accumulated in a 32-bit accumulator in 18.14 format. - * There is no risk of internal overflow with this approach and the full precision of intermediate multiplications is preserved. - * The accumulator is converted to 18.7 format by discarding the low 7 bits. - * Finally, the result is truncated to 1.7 format. - */ - -void arm_fir_q7( - const arm_fir_instance_q7 * S, - q7_t * pSrc, - q7_t * pDst, - uint32_t blockSize) -{ - -#ifndef ARM_MATH_CM0_FAMILY - - /* Run the below code for Cortex-M4 and Cortex-M3 */ - - q7_t *pState = S->pState; /* State pointer */ - q7_t *pCoeffs = S->pCoeffs; /* Coefficient pointer */ - q7_t *pStateCurnt; /* Points to the current sample of the state */ - q7_t x0, x1, x2, x3; /* Temporary variables to hold state */ - q7_t c0; /* Temporary variable to hold coefficient value */ - q7_t *px; /* Temporary pointer for state */ - q7_t *pb; /* Temporary pointer for coefficient buffer */ - q31_t acc0, acc1, acc2, acc3; /* Accumulators */ - uint32_t numTaps = S->numTaps; /* Number of filter coefficients in the filter */ - uint32_t i, tapCnt, blkCnt; /* Loop counters */ - - /* S->pState points to state array which contains previous frame (numTaps - 1) samples */ - /* pStateCurnt points to the location where the new input data should be written */ - pStateCurnt = &(S->pState[(numTaps - 1u)]); - - /* Apply loop unrolling and compute 4 output values simultaneously. - * The variables acc0 ... acc3 hold output values that are being computed: - * - * acc0 = b[numTaps-1] * x[n-numTaps-1] + b[numTaps-2] * x[n-numTaps-2] + b[numTaps-3] * x[n-numTaps-3] +...+ b[0] * x[0] - * acc1 = b[numTaps-1] * x[n-numTaps] + b[numTaps-2] * x[n-numTaps-1] + b[numTaps-3] * x[n-numTaps-2] +...+ b[0] * x[1] - * acc2 = b[numTaps-1] * x[n-numTaps+1] + b[numTaps-2] * x[n-numTaps] + b[numTaps-3] * x[n-numTaps-1] +...+ b[0] * x[2] - * acc3 = b[numTaps-1] * x[n-numTaps+2] + b[numTaps-2] * x[n-numTaps+1] + b[numTaps-3] * x[n-numTaps] +...+ b[0] * x[3] - */ - blkCnt = blockSize >> 2; - - /* First part of the processing with loop unrolling. Compute 4 outputs at a time. - ** a second loop below computes the remaining 1 to 3 samples. */ - while(blkCnt > 0u) - { - /* Copy four new input samples into the state buffer */ - *pStateCurnt++ = *pSrc++; - *pStateCurnt++ = *pSrc++; - *pStateCurnt++ = *pSrc++; - *pStateCurnt++ = *pSrc++; - - /* Set all accumulators to zero */ - acc0 = 0; - acc1 = 0; - acc2 = 0; - acc3 = 0; - - /* Initialize state pointer */ - px = pState; - - /* Initialize coefficient pointer */ - pb = pCoeffs; - - /* Read the first three samples from the state buffer: - * x[n-numTaps], x[n-numTaps-1], x[n-numTaps-2] */ - x0 = *(px++); - x1 = *(px++); - x2 = *(px++); - - /* Loop unrolling. Process 4 taps at a time. */ - tapCnt = numTaps >> 2; - i = tapCnt; - - while(i > 0u) - { - /* Read the b[numTaps] coefficient */ - c0 = *pb; - - /* Read x[n-numTaps-3] sample */ - x3 = *px; - - /* acc0 += b[numTaps] * x[n-numTaps] */ - acc0 += ((q15_t) x0 * c0); - - /* acc1 += b[numTaps] * x[n-numTaps-1] */ - acc1 += ((q15_t) x1 * c0); - - /* acc2 += b[numTaps] * x[n-numTaps-2] */ - acc2 += ((q15_t) x2 * c0); - - /* acc3 += b[numTaps] * x[n-numTaps-3] */ - acc3 += ((q15_t) x3 * c0); - - /* Read the b[numTaps-1] coefficient */ - c0 = *(pb + 1u); - - /* Read x[n-numTaps-4] sample */ - x0 = *(px + 1u); - - /* Perform the multiply-accumulates */ - acc0 += ((q15_t) x1 * c0); - acc1 += ((q15_t) x2 * c0); - acc2 += ((q15_t) x3 * c0); - acc3 += ((q15_t) x0 * c0); - - /* Read the b[numTaps-2] coefficient */ - c0 = *(pb + 2u); - - /* Read x[n-numTaps-5] sample */ - x1 = *(px + 2u); - - /* Perform the multiply-accumulates */ - acc0 += ((q15_t) x2 * c0); - acc1 += ((q15_t) x3 * c0); - acc2 += ((q15_t) x0 * c0); - acc3 += ((q15_t) x1 * c0); - - /* Read the b[numTaps-3] coefficients */ - c0 = *(pb + 3u); - - /* Read x[n-numTaps-6] sample */ - x2 = *(px + 3u); - - /* Perform the multiply-accumulates */ - acc0 += ((q15_t) x3 * c0); - acc1 += ((q15_t) x0 * c0); - acc2 += ((q15_t) x1 * c0); - acc3 += ((q15_t) x2 * c0); - - /* update coefficient pointer */ - pb += 4u; - px += 4u; - - /* Decrement the loop counter */ - i--; - } - - /* If the filter length is not a multiple of 4, compute the remaining filter taps */ - - i = numTaps - (tapCnt * 4u); - while(i > 0u) - { - /* Read coefficients */ - c0 = *(pb++); - - /* Fetch 1 state variable */ - x3 = *(px++); - - /* Perform the multiply-accumulates */ - acc0 += ((q15_t) x0 * c0); - acc1 += ((q15_t) x1 * c0); - acc2 += ((q15_t) x2 * c0); - acc3 += ((q15_t) x3 * c0); - - /* Reuse the present sample states for next sample */ - x0 = x1; - x1 = x2; - x2 = x3; - - /* Decrement the loop counter */ - i--; - } - - /* Advance the state pointer by 4 to process the next group of 4 samples */ - pState = pState + 4; - - /* The results in the 4 accumulators are in 2.62 format. Convert to 1.31 - ** Then store the 4 outputs in the destination buffer. */ - acc0 = __SSAT((acc0 >> 7u), 8); - *pDst++ = acc0; - acc1 = __SSAT((acc1 >> 7u), 8); - *pDst++ = acc1; - acc2 = __SSAT((acc2 >> 7u), 8); - *pDst++ = acc2; - acc3 = __SSAT((acc3 >> 7u), 8); - *pDst++ = acc3; - - /* Decrement the samples loop counter */ - blkCnt--; - } - - - /* If the blockSize is not a multiple of 4, compute any remaining output samples here. - ** No loop unrolling is used. */ - blkCnt = blockSize % 4u; - - while(blkCnt > 0u) - { - /* Copy one sample at a time into state buffer */ - *pStateCurnt++ = *pSrc++; - - /* Set the accumulator to zero */ - acc0 = 0; - - /* Initialize state pointer */ - px = pState; - - /* Initialize Coefficient pointer */ - pb = (pCoeffs); - - i = numTaps; - - /* Perform the multiply-accumulates */ - do - { - acc0 += (q15_t) * (px++) * (*(pb++)); - i--; - } while(i > 0u); - - /* The result is in 2.14 format. Convert to 1.7 - ** Then store the output in the destination buffer. */ - *pDst++ = __SSAT((acc0 >> 7u), 8); - - /* Advance state pointer by 1 for the next sample */ - pState = pState + 1; - - /* Decrement the samples loop counter */ - blkCnt--; - } - - /* Processing is complete. - ** Now copy the last numTaps - 1 samples to the satrt of the state buffer. - ** This prepares the state buffer for the next function call. */ - - /* Points to the start of the state buffer */ - pStateCurnt = S->pState; - - tapCnt = (numTaps - 1u) >> 2u; - - /* copy data */ - while(tapCnt > 0u) - { - *pStateCurnt++ = *pState++; - *pStateCurnt++ = *pState++; - *pStateCurnt++ = *pState++; - *pStateCurnt++ = *pState++; - - /* Decrement the loop counter */ - tapCnt--; - } - - /* Calculate remaining number of copies */ - tapCnt = (numTaps - 1u) % 0x4u; - - /* Copy the remaining q31_t data */ - while(tapCnt > 0u) - { - *pStateCurnt++ = *pState++; - - /* Decrement the loop counter */ - tapCnt--; - } - -#else - -/* Run the below code for Cortex-M0 */ - - uint32_t numTaps = S->numTaps; /* Number of taps in the filter */ - uint32_t i, blkCnt; /* Loop counters */ - q7_t *pState = S->pState; /* State pointer */ - q7_t *pCoeffs = S->pCoeffs; /* Coefficient pointer */ - q7_t *px, *pb; /* Temporary pointers to state and coeff */ - q31_t acc = 0; /* Accumlator */ - q7_t *pStateCurnt; /* Points to the current sample of the state */ - - - /* S->pState points to state array which contains previous frame (numTaps - 1) samples */ - /* pStateCurnt points to the location where the new input data should be written */ - pStateCurnt = S->pState + (numTaps - 1u); - - /* Initialize blkCnt with blockSize */ - blkCnt = blockSize; - - /* Perform filtering upto BlockSize - BlockSize%4 */ - while(blkCnt > 0u) - { - /* Copy one sample at a time into state buffer */ - *pStateCurnt++ = *pSrc++; - - /* Set accumulator to zero */ - acc = 0; - - /* Initialize state pointer of type q7 */ - px = pState; - - /* Initialize coeff pointer of type q7 */ - pb = pCoeffs; - - - i = numTaps; - - while(i > 0u) - { - /* acc = b[numTaps-1] * x[n-numTaps-1] + b[numTaps-2] * x[n-numTaps-2] + b[numTaps-3] * x[n-numTaps-3] +...+ b[0] * x[0] */ - acc += (q15_t) * px++ * *pb++; - i--; - } - - /* Store the 1.7 format filter output in destination buffer */ - *pDst++ = (q7_t) __SSAT((acc >> 7), 8); - - /* Advance the state pointer by 1 to process the next sample */ - pState = pState + 1; - - /* Decrement the loop counter */ - blkCnt--; - } - - /* Processing is complete. - ** Now copy the last numTaps - 1 samples to the satrt of the state buffer. - ** This prepares the state buffer for the next function call. */ - - - /* Points to the start of the state buffer */ - pStateCurnt = S->pState; - - - /* Copy numTaps number of values */ - i = (numTaps - 1u); - - /* Copy q7_t data */ - while(i > 0u) - { - *pStateCurnt++ = *pState++; - i--; - } - -#endif /* #ifndef ARM_MATH_CM0_FAMILY */ - -} - -/** - * @} end of FIR group - */ diff --git a/gui/demos/1_fir_twotone.cpp b/gui/demos/1_fir_twotone.cpp deleted file mode 100644 index 2f33b45..0000000 --- a/gui/demos/1_fir_twotone.cpp +++ /dev/null @@ -1,474 +0,0 @@ -// Digilent Waveforms -// Custom signal: -// 4096 samples, X from 0 to 4095 -// sin(PI/8000*X*770)+sin(PI/8000*X*1336) - -#include -using float32_t = float; - -typedef struct -{ - uint16_t numTaps; /**< number of filter coefficients in the filter. */ - float32_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ - float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ -} arm_fir_instance_f32; - -static void arm_fir_f32(const arm_fir_instance_f32 * S, float32_t * pSrc, float32_t * pDst, uint32_t blockSize); - -adcsample_t *process_data(adcsample_t *samples, unsigned int size) -{ - // 1. Define our array sizes (Be sure to set Run > Set buffer size... to below value!) - constexpr unsigned int buffer_size = 500; - constexpr unsigned int filter_size = 100; - - // 2. Define our filter and the working arrays - static float filter[filter_size] = { -0.0004387887025183802,0.000832200098857514,0.0015307184662295217,0.0025082006379108486,0.0037734534845577567,0.005298545881839843,0.007011536790726042,0.008794237700486741,0.0104866537299476,0.011898670086639574,0.01282927474471195,0.013091387203266143,0.012539923791204348,0.011099382508792464,0.008786721087738127,0.005724922305741446,0.002144437816471804,-0.0016305355316754216,-0.005210998401135279,-0.00818522521443848,-0.0101701012867913,-0.010865871085906236,-0.01010594970823667,-0.007895785082463622,-0.00443176063435828,-0.00009684904191641966,0.004570418146137933,0.008932018058761999,0.012326603606274784,0.014157852725048914,0.013983789156387687,0.011595484863822138,0.007073052408314296,0.0008096544104778903,-0.006503129471685042,-0.013929880283520692,-0.020382390416343286,-0.024738365522063946,-0.02597487538349127,-0.02330063345756659,-0.016270714607748243,-0.004868040016583383,0.010460249064783475,0.028818398768187533,0.04893049916926163,0.06925561893929223,0.0881379889511425,0.10397551230005074,0.11538733811709222,0.12136089030896859,0.12136089030896859,0.11538733811709222,0.10397551230005074,0.0881379889511425,0.06925561893929223,0.04893049916926163,0.028818398768187533,0.010460249064783475,-0.004868040016583383,-0.016270714607748243,-0.02330063345756659,-0.02597487538349127,-0.024738365522063946,-0.020382390416343286,-0.013929880283520692,-0.006503129471685042,0.0008096544104778903,0.007073052408314296,0.011595484863822138,0.013983789156387687,0.014157852725048914,0.012326603606274784,0.008932018058761999,0.004570418146137933,-0.00009684904191641966,-0.00443176063435828,-0.007895785082463622,-0.01010594970823667,-0.010865871085906236,-0.0101701012867913,-0.00818522521443848,-0.005210998401135279,-0.0016305355316754216,0.002144437816471804,0.005724922305741446,0.008786721087738127,0.011099382508792464,0.012539923791204348,0.013091387203266143,0.01282927474471195,0.011898670086639574,0.0104866537299476,0.008794237700486741,0.007011536790726042,0.005298545881839843,0.0037734534845577567,0.0025082006379108486,0.0015307184662295217,0.000832200098857514,0.0004387887025183802 - }; - static float input[buffer_size]; - static float output[buffer_size]; - static float working[buffer_size + filter_size]; - - // 3. Scale 0-4095 interger sample values to +/- 1.0 floats - for (unsigned int i = 0; i < size; i++) - input[i] = (samples[i] - 2048) / 2048.f; - - // 4. Compute the FIR - arm_fir_instance_f32 fir { filter_size, working, filter }; - arm_fir_f32(&fir, input, output, size); - - // 5. Convert float results back to 0-4095 range for output - for (unsigned int i = 0; i < size; i++) - samples[i] = output[i] * 2048.f + 2048; - - return samples; -} - -// Below taken from the CMSIS DSP Library (find it on GitHub) -void arm_fir_f32( - const arm_fir_instance_f32 * S, - float32_t * pSrc, - float32_t * pDst, - uint32_t blockSize) -{ - float32_t *pState = S->pState; /* State pointer */ - float32_t *pCoeffs = S->pCoeffs; /* Coefficient pointer */ - float32_t *pStateCurnt; /* Points to the current sample of the state */ - float32_t *px, *pb; /* Temporary pointers for state and coefficient buffers */ - float32_t acc0, acc1, acc2, acc3, acc4, acc5, acc6, acc7; /* Accumulators */ - float32_t x0, x1, x2, x3, x4, x5, x6, x7, c0; /* Temporary variables to hold state and coefficient values */ - uint32_t numTaps = S->numTaps; /* Number of filter coefficients in the filter */ - uint32_t i, tapCnt, blkCnt; /* Loop counters */ - float32_t p0,p1,p2,p3,p4,p5,p6,p7; /* Temporary product values */ - - /* S->pState points to state array which contains previous frame (numTaps - 1) samples */ - /* pStateCurnt points to the location where the new input data should be written */ - pStateCurnt = &(S->pState[(numTaps - 1u)]); - - /* Apply loop unrolling and compute 8 output values simultaneously. - * The variables acc0 ... acc7 hold output values that are being computed: - * - * acc0 = b[numTaps-1] * x[n-numTaps-1] + b[numTaps-2] * x[n-numTaps-2] + b[numTaps-3] * x[n-numTaps-3] +...+ b[0] * x[0] - * acc1 = b[numTaps-1] * x[n-numTaps] + b[numTaps-2] * x[n-numTaps-1] + b[numTaps-3] * x[n-numTaps-2] +...+ b[0] * x[1] - * acc2 = b[numTaps-1] * x[n-numTaps+1] + b[numTaps-2] * x[n-numTaps] + b[numTaps-3] * x[n-numTaps-1] +...+ b[0] * x[2] - * acc3 = b[numTaps-1] * x[n-numTaps+2] + b[numTaps-2] * x[n-numTaps+1] + b[numTaps-3] * x[n-numTaps] +...+ b[0] * x[3] - */ - blkCnt = blockSize >> 3; - - /* First part of the processing with loop unrolling. Compute 8 outputs at a time. - ** a second loop below computes the remaining 1 to 7 samples. */ - while(blkCnt > 0u) - { - /* Copy four new input samples into the state buffer */ - *pStateCurnt++ = *pSrc++; - *pStateCurnt++ = *pSrc++; - *pStateCurnt++ = *pSrc++; - *pStateCurnt++ = *pSrc++; - - /* Set all accumulators to zero */ - acc0 = 0.0f; - acc1 = 0.0f; - acc2 = 0.0f; - acc3 = 0.0f; - acc4 = 0.0f; - acc5 = 0.0f; - acc6 = 0.0f; - acc7 = 0.0f; - - /* Initialize state pointer */ - px = pState; - - /* Initialize coeff pointer */ - pb = (pCoeffs); - - /* This is separated from the others to avoid - * a call to __aeabi_memmove which would be slower - */ - *pStateCurnt++ = *pSrc++; - *pStateCurnt++ = *pSrc++; - *pStateCurnt++ = *pSrc++; - *pStateCurnt++ = *pSrc++; - - /* Read the first seven samples from the state buffer: x[n-numTaps], x[n-numTaps-1], x[n-numTaps-2] */ - x0 = *px++; - x1 = *px++; - x2 = *px++; - x3 = *px++; - x4 = *px++; - x5 = *px++; - x6 = *px++; - - /* Loop unrolling. Process 8 taps at a time. */ - tapCnt = numTaps >> 3u; - - /* Loop over the number of taps. Unroll by a factor of 8. - ** Repeat until we've computed numTaps-8 coefficients. */ - while(tapCnt > 0u) - { - /* Read the b[numTaps-1] coefficient */ - c0 = *(pb++); - - /* Read x[n-numTaps-3] sample */ - x7 = *(px++); - - /* acc0 += b[numTaps-1] * x[n-numTaps] */ - p0 = x0 * c0; - - /* acc1 += b[numTaps-1] * x[n-numTaps-1] */ - p1 = x1 * c0; - - /* acc2 += b[numTaps-1] * x[n-numTaps-2] */ - p2 = x2 * c0; - - /* acc3 += b[numTaps-1] * x[n-numTaps-3] */ - p3 = x3 * c0; - - /* acc4 += b[numTaps-1] * x[n-numTaps-4] */ - p4 = x4 * c0; - - /* acc1 += b[numTaps-1] * x[n-numTaps-5] */ - p5 = x5 * c0; - - /* acc2 += b[numTaps-1] * x[n-numTaps-6] */ - p6 = x6 * c0; - - /* acc3 += b[numTaps-1] * x[n-numTaps-7] */ - p7 = x7 * c0; - - /* Read the b[numTaps-2] coefficient */ - c0 = *(pb++); - - /* Read x[n-numTaps-4] sample */ - x0 = *(px++); - - acc0 += p0; - acc1 += p1; - acc2 += p2; - acc3 += p3; - acc4 += p4; - acc5 += p5; - acc6 += p6; - acc7 += p7; - - - /* Perform the multiply-accumulate */ - p0 = x1 * c0; - p1 = x2 * c0; - p2 = x3 * c0; - p3 = x4 * c0; - p4 = x5 * c0; - p5 = x6 * c0; - p6 = x7 * c0; - p7 = x0 * c0; - - /* Read the b[numTaps-3] coefficient */ - c0 = *(pb++); - - /* Read x[n-numTaps-5] sample */ - x1 = *(px++); - - acc0 += p0; - acc1 += p1; - acc2 += p2; - acc3 += p3; - acc4 += p4; - acc5 += p5; - acc6 += p6; - acc7 += p7; - - /* Perform the multiply-accumulates */ - p0 = x2 * c0; - p1 = x3 * c0; - p2 = x4 * c0; - p3 = x5 * c0; - p4 = x6 * c0; - p5 = x7 * c0; - p6 = x0 * c0; - p7 = x1 * c0; - - /* Read the b[numTaps-4] coefficient */ - c0 = *(pb++); - - /* Read x[n-numTaps-6] sample */ - x2 = *(px++); - - acc0 += p0; - acc1 += p1; - acc2 += p2; - acc3 += p3; - acc4 += p4; - acc5 += p5; - acc6 += p6; - acc7 += p7; - - /* Perform the multiply-accumulates */ - p0 = x3 * c0; - p1 = x4 * c0; - p2 = x5 * c0; - p3 = x6 * c0; - p4 = x7 * c0; - p5 = x0 * c0; - p6 = x1 * c0; - p7 = x2 * c0; - - /* Read the b[numTaps-4] coefficient */ - c0 = *(pb++); - - /* Read x[n-numTaps-6] sample */ - x3 = *(px++); - - acc0 += p0; - acc1 += p1; - acc2 += p2; - acc3 += p3; - acc4 += p4; - acc5 += p5; - acc6 += p6; - acc7 += p7; - - /* Perform the multiply-accumulates */ - p0 = x4 * c0; - p1 = x5 * c0; - p2 = x6 * c0; - p3 = x7 * c0; - p4 = x0 * c0; - p5 = x1 * c0; - p6 = x2 * c0; - p7 = x3 * c0; - - /* Read the b[numTaps-4] coefficient */ - c0 = *(pb++); - - /* Read x[n-numTaps-6] sample */ - x4 = *(px++); - - acc0 += p0; - acc1 += p1; - acc2 += p2; - acc3 += p3; - acc4 += p4; - acc5 += p5; - acc6 += p6; - acc7 += p7; - - /* Perform the multiply-accumulates */ - p0 = x5 * c0; - p1 = x6 * c0; - p2 = x7 * c0; - p3 = x0 * c0; - p4 = x1 * c0; - p5 = x2 * c0; - p6 = x3 * c0; - p7 = x4 * c0; - - /* Read the b[numTaps-4] coefficient */ - c0 = *(pb++); - - /* Read x[n-numTaps-6] sample */ - x5 = *(px++); - - acc0 += p0; - acc1 += p1; - acc2 += p2; - acc3 += p3; - acc4 += p4; - acc5 += p5; - acc6 += p6; - acc7 += p7; - - /* Perform the multiply-accumulates */ - p0 = x6 * c0; - p1 = x7 * c0; - p2 = x0 * c0; - p3 = x1 * c0; - p4 = x2 * c0; - p5 = x3 * c0; - p6 = x4 * c0; - p7 = x5 * c0; - - /* Read the b[numTaps-4] coefficient */ - c0 = *(pb++); - - /* Read x[n-numTaps-6] sample */ - x6 = *(px++); - - acc0 += p0; - acc1 += p1; - acc2 += p2; - acc3 += p3; - acc4 += p4; - acc5 += p5; - acc6 += p6; - acc7 += p7; - - /* Perform the multiply-accumulates */ - p0 = x7 * c0; - p1 = x0 * c0; - p2 = x1 * c0; - p3 = x2 * c0; - p4 = x3 * c0; - p5 = x4 * c0; - p6 = x5 * c0; - p7 = x6 * c0; - - tapCnt--; - - acc0 += p0; - acc1 += p1; - acc2 += p2; - acc3 += p3; - acc4 += p4; - acc5 += p5; - acc6 += p6; - acc7 += p7; - } - - /* If the filter length is not a multiple of 8, compute the remaining filter taps */ - tapCnt = numTaps % 0x8u; - - while(tapCnt > 0u) - { - /* Read coefficients */ - c0 = *(pb++); - - /* Fetch 1 state variable */ - x7 = *(px++); - - /* Perform the multiply-accumulates */ - p0 = x0 * c0; - p1 = x1 * c0; - p2 = x2 * c0; - p3 = x3 * c0; - p4 = x4 * c0; - p5 = x5 * c0; - p6 = x6 * c0; - p7 = x7 * c0; - - /* Reuse the present sample states for next sample */ - x0 = x1; - x1 = x2; - x2 = x3; - x3 = x4; - x4 = x5; - x5 = x6; - x6 = x7; - - acc0 += p0; - acc1 += p1; - acc2 += p2; - acc3 += p3; - acc4 += p4; - acc5 += p5; - acc6 += p6; - acc7 += p7; - - /* Decrement the loop counter */ - tapCnt--; - } - - /* Advance the state pointer by 8 to process the next group of 8 samples */ - pState = pState + 8; - - /* The results in the 8 accumulators, store in the destination buffer. */ - *pDst++ = acc0; - *pDst++ = acc1; - *pDst++ = acc2; - *pDst++ = acc3; - *pDst++ = acc4; - *pDst++ = acc5; - *pDst++ = acc6; - *pDst++ = acc7; - - blkCnt--; - } - - /* If the blockSize is not a multiple of 8, compute any remaining output samples here. - ** No loop unrolling is used. */ - blkCnt = blockSize % 0x8u; - - while(blkCnt > 0u) - { - /* Copy one sample at a time into state buffer */ - *pStateCurnt++ = *pSrc++; - - /* Set the accumulator to zero */ - acc0 = 0.0f; - - /* Initialize state pointer */ - px = pState; - - /* Initialize Coefficient pointer */ - pb = (pCoeffs); - - i = numTaps; - - /* Perform the multiply-accumulates */ - do - { - acc0 += *px++ * *pb++; - i--; - - } while(i > 0u); - - /* The result is store in the destination buffer. */ - *pDst++ = acc0; - - /* Advance state pointer by 1 for the next sample */ - pState = pState + 1; - - blkCnt--; - } - - /* Processing is complete. - ** Now copy the last numTaps - 1 samples to the start of the state buffer. - ** This prepares the state buffer for the next function call. */ - - /* Points to the start of the state buffer */ - pStateCurnt = S->pState; - - tapCnt = (numTaps - 1u) >> 2u; - - /* copy data */ - while(tapCnt > 0u) - { - *pStateCurnt++ = *pState++; - *pStateCurnt++ = *pState++; - *pStateCurnt++ = *pState++; - *pStateCurnt++ = *pState++; - - /* Decrement the loop counter */ - tapCnt--; - } - - /* Calculate remaining number of copies */ - tapCnt = (numTaps - 1u) % 0x4u; - - /* Copy the remaining q31_t data */ - while(tapCnt > 0u) - { - *pStateCurnt++ = *pState++; - - /* Decrement the loop counter */ - tapCnt--; - } -} diff --git a/gui/demos/2_iir_echo.cpp b/gui/demos/2_iir_echo.cpp deleted file mode 100644 index acb5c5d..0000000 --- a/gui/demos/2_iir_echo.cpp +++ /dev/null @@ -1,24 +0,0 @@ -Sample *process_data(Samples samples) -{ - constexpr unsigned int size = samples.size(); - constexpr unsigned int D = 2000; - - float alpha = readalt() / 4095.; - - static Sample output[size]; - static Sample prev[D]; // prev[0] = output[0 - D] - - // Do calculations with previous output - for (unsigned int i = 0; i < D; i++) - output[i] = samples[i] + alpha * (prev[i] - 2048); - - // Do calculations with current samples - for (unsigned int i = D; i < size; i++) - output[i] = samples[i] + alpha * (output[i - D] - 2048); - - // Save outputs for next computation - for (unsigned int i = 0; i < D; i++) - prev[i] = output[size - (D - i)]; - - return output; -} diff --git a/gui/exprtk.hpp b/gui/exprtk.hpp deleted file mode 100644 index bb108c2..0000000 --- a/gui/exprtk.hpp +++ /dev/null @@ -1,40121 +0,0 @@ -/* - ****************************************************************** - * C++ Mathematical Expression Toolkit Library * - * * - * Author: Arash Partow (1999-2021) * - * URL: http://www.partow.net/programming/exprtk/index.html * - * * - * Copyright notice: * - * Free use of the C++ Mathematical Expression Toolkit Library is * - * permitted under the guidelines and in accordance with the most * - * current version of the MIT License. * - * http://www.opensource.org/licenses/MIT * - * * - * Example expressions: * - * (00) (y + x / y) * (x - y / x) * - * (01) (x^2 / sin(2 * pi / y)) - x / 2 * - * (02) sqrt(1 - (x^2)) * - * (03) 1 - sin(2 * x) + cos(pi / y) * - * (04) a * exp(2 * t) + c * - * (05) if(((x + 2) == 3) and ((y + 5) <= 9),1 + w, 2 / z) * - * (06) (avg(x,y) <= x + y ? x - y : x * y) + 2 * pi / x * - * (07) z := x + sin(2 * pi / y) * - * (08) u := 2 * (pi * z) / (w := x + cos(y / pi)) * - * (09) clamp(-1,sin(2 * pi * x) + cos(y / 2 * pi),+1) * - * (10) inrange(-2,m,+2) == if(({-2 <= m} and [m <= +2]),1,0) * - * (11) (2sin(x)cos(2y)7 + 1) == (2 * sin(x) * cos(2*y) * 7 + 1) * - * (12) (x ilike 's*ri?g') and [y < (3 z^7 + w)] * - * * - ****************************************************************** -*/ - - -#ifndef INCLUDE_EXPRTK_HPP -#define INCLUDE_EXPRTK_HPP - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -namespace exprtk -{ - #ifdef exprtk_enable_debugging - #define exprtk_debug(params) printf params - #else - #define exprtk_debug(params) (void)0 - #endif - - #define exprtk_error_location \ - "exprtk.hpp:" + details::to_str(__LINE__) \ - - #if defined(__GNUC__) && (__GNUC__ >= 7) - - #define exprtk_disable_fallthrough_begin \ - _Pragma ("GCC diagnostic push") \ - _Pragma ("GCC diagnostic ignored \"-Wimplicit-fallthrough\"") \ - - #define exprtk_disable_fallthrough_end \ - _Pragma ("GCC diagnostic pop") \ - - #else - #define exprtk_disable_fallthrough_begin (void)0; - #define exprtk_disable_fallthrough_end (void)0; - #endif - - #if __cplusplus >= 201103L - #define exprtk_override override - #define exprtk_final final - #else - #define exprtk_override - #define exprtk_final - #endif - - namespace details - { - typedef unsigned char uchar_t; - typedef char char_t; - typedef uchar_t* uchar_ptr; - typedef char_t* char_ptr; - typedef uchar_t const* uchar_cptr; - typedef char_t const* char_cptr; - typedef unsigned long long int _uint64_t; - typedef long long int _int64_t; - - inline bool is_whitespace(const char_t c) - { - return (' ' == c) || ('\n' == c) || - ('\r' == c) || ('\t' == c) || - ('\b' == c) || ('\v' == c) || - ('\f' == c) ; - } - - inline bool is_operator_char(const char_t c) - { - return ('+' == c) || ('-' == c) || - ('*' == c) || ('/' == c) || - ('^' == c) || ('<' == c) || - ('>' == c) || ('=' == c) || - (',' == c) || ('!' == c) || - ('(' == c) || (')' == c) || - ('[' == c) || (']' == c) || - ('{' == c) || ('}' == c) || - ('%' == c) || (':' == c) || - ('?' == c) || ('&' == c) || - ('|' == c) || (';' == c) ; - } - - inline bool is_letter(const char_t c) - { - return (('a' <= c) && (c <= 'z')) || - (('A' <= c) && (c <= 'Z')) ; - } - - inline bool is_digit(const char_t c) - { - return ('0' <= c) && (c <= '9'); - } - - inline bool is_letter_or_digit(const char_t c) - { - return is_letter(c) || is_digit(c); - } - - inline bool is_left_bracket(const char_t c) - { - return ('(' == c) || ('[' == c) || ('{' == c); - } - - inline bool is_right_bracket(const char_t c) - { - return (')' == c) || (']' == c) || ('}' == c); - } - - inline bool is_bracket(const char_t c) - { - return is_left_bracket(c) || is_right_bracket(c); - } - - inline bool is_sign(const char_t c) - { - return ('+' == c) || ('-' == c); - } - - inline bool is_invalid(const char_t c) - { - return !is_whitespace (c) && - !is_operator_char(c) && - !is_letter (c) && - !is_digit (c) && - ('.' != c) && - ('_' != c) && - ('$' != c) && - ('~' != c) && - ('\'' != c); - } - - inline bool is_valid_string_char(const char_t c) - { - return std::isprint(static_cast(c)) || - is_whitespace(c); - } - - #ifndef exprtk_disable_caseinsensitivity - inline void case_normalise(std::string& s) - { - for (std::size_t i = 0; i < s.size(); ++i) - { - s[i] = static_cast(std::tolower(s[i])); - } - } - - inline bool imatch(const char_t c1, const char_t c2) - { - return std::tolower(c1) == std::tolower(c2); - } - - inline bool imatch(const std::string& s1, const std::string& s2) - { - if (s1.size() == s2.size()) - { - for (std::size_t i = 0; i < s1.size(); ++i) - { - if (std::tolower(s1[i]) != std::tolower(s2[i])) - { - return false; - } - } - - return true; - } - - return false; - } - - struct ilesscompare - { - inline bool operator() (const std::string& s1, const std::string& s2) const - { - const std::size_t length = std::min(s1.size(),s2.size()); - - for (std::size_t i = 0; i < length; ++i) - { - const char_t c1 = static_cast(std::tolower(s1[i])); - const char_t c2 = static_cast(std::tolower(s2[i])); - - if (c1 > c2) - return false; - else if (c1 < c2) - return true; - } - - return s1.size() < s2.size(); - } - }; - - #else - inline void case_normalise(std::string&) - {} - - inline bool imatch(const char_t c1, const char_t c2) - { - return c1 == c2; - } - - inline bool imatch(const std::string& s1, const std::string& s2) - { - return s1 == s2; - } - - struct ilesscompare - { - inline bool operator() (const std::string& s1, const std::string& s2) const - { - return s1 < s2; - } - }; - #endif - - inline bool is_valid_sf_symbol(const std::string& symbol) - { - // Special function: $f12 or $F34 - return (4 == symbol.size()) && - ('$' == symbol[0]) && - imatch('f',symbol[1]) && - is_digit(symbol[2]) && - is_digit(symbol[3]); - } - - inline const char_t& front(const std::string& s) - { - return s[0]; - } - - inline const char_t& back(const std::string& s) - { - return s[s.size() - 1]; - } - - inline std::string to_str(int i) - { - if (0 == i) - return std::string("0"); - - std::string result; - - if (i < 0) - { - for ( ; i; i /= 10) - { - result += '0' + static_cast(-(i % 10)); - } - - result += '-'; - } - else - { - for ( ; i; i /= 10) - { - result += '0' + static_cast(i % 10); - } - } - - std::reverse(result.begin(), result.end()); - - return result; - } - - inline std::string to_str(std::size_t i) - { - return to_str(static_cast(i)); - } - - inline bool is_hex_digit(const std::string::value_type digit) - { - return (('0' <= digit) && (digit <= '9')) || - (('A' <= digit) && (digit <= 'F')) || - (('a' <= digit) && (digit <= 'f')) ; - } - - inline uchar_t hex_to_bin(uchar_t h) - { - if (('0' <= h) && (h <= '9')) - return (h - '0'); - else - return static_cast(std::toupper(h) - 'A'); - } - - template - inline bool parse_hex(Iterator& itr, Iterator end, - std::string::value_type& result) - { - if ( - (end == (itr )) || - (end == (itr + 1)) || - (end == (itr + 2)) || - (end == (itr + 3)) || - ('0' != *(itr )) || - ('X' != std::toupper(*(itr + 1))) || - (!is_hex_digit(*(itr + 2))) || - (!is_hex_digit(*(itr + 3))) - ) - { - return false; - } - - result = hex_to_bin(static_cast(*(itr + 2))) << 4 | - hex_to_bin(static_cast(*(itr + 3))) ; - - return true; - } - - inline bool cleanup_escapes(std::string& s) - { - typedef std::string::iterator str_itr_t; - - str_itr_t itr1 = s.begin(); - str_itr_t itr2 = s.begin(); - str_itr_t end = s.end (); - - std::size_t removal_count = 0; - - while (end != itr1) - { - if ('\\' == (*itr1)) - { - if (end == ++itr1) - { - return false; - } - else if (parse_hex(itr1, end, *itr2)) - { - itr1+= 4; - itr2+= 1; - removal_count +=4; - } - else if ('a' == (*itr1)) { (*itr2++) = '\a'; ++itr1; ++removal_count; } - else if ('b' == (*itr1)) { (*itr2++) = '\b'; ++itr1; ++removal_count; } - else if ('f' == (*itr1)) { (*itr2++) = '\f'; ++itr1; ++removal_count; } - else if ('n' == (*itr1)) { (*itr2++) = '\n'; ++itr1; ++removal_count; } - else if ('r' == (*itr1)) { (*itr2++) = '\r'; ++itr1; ++removal_count; } - else if ('t' == (*itr1)) { (*itr2++) = '\t'; ++itr1; ++removal_count; } - else if ('v' == (*itr1)) { (*itr2++) = '\v'; ++itr1; ++removal_count; } - else if ('0' == (*itr1)) { (*itr2++) = '\0'; ++itr1; ++removal_count; } - else - { - (*itr2++) = (*itr1++); - ++removal_count; - } - continue; - } - else - (*itr2++) = (*itr1++); - } - - if ((removal_count > s.size()) || (0 == removal_count)) - return false; - - s.resize(s.size() - removal_count); - - return true; - } - - class build_string - { - public: - - build_string(const std::size_t& initial_size = 64) - { - data_.reserve(initial_size); - } - - inline build_string& operator << (const std::string& s) - { - data_ += s; - return (*this); - } - - inline build_string& operator << (char_cptr s) - { - data_ += std::string(s); - return (*this); - } - - inline operator std::string () const - { - return data_; - } - - inline std::string as_string() const - { - return data_; - } - - private: - - std::string data_; - }; - - static const std::string reserved_words[] = - { - "break", "case", "continue", "default", "false", "for", - "if", "else", "ilike", "in", "like", "and", "nand", "nor", - "not", "null", "or", "repeat", "return", "shl", "shr", - "swap", "switch", "true", "until", "var", "while", "xnor", - "xor", "&", "|" - }; - - static const std::size_t reserved_words_size = sizeof(reserved_words) / sizeof(std::string); - - static const std::string reserved_symbols[] = - { - "abs", "acos", "acosh", "and", "asin", "asinh", "atan", - "atanh", "atan2", "avg", "break", "case", "ceil", "clamp", - "continue", "cos", "cosh", "cot", "csc", "default", - "deg2grad", "deg2rad", "equal", "erf", "erfc", "exp", - "expm1", "false", "floor", "for", "frac", "grad2deg", - "hypot", "iclamp", "if", "else", "ilike", "in", "inrange", - "like", "log", "log10", "log2", "logn", "log1p", "mand", - "max", "min", "mod", "mor", "mul", "ncdf", "nand", "nor", - "not", "not_equal", "null", "or", "pow", "rad2deg", - "repeat", "return", "root", "round", "roundn", "sec", "sgn", - "shl", "shr", "sin", "sinc", "sinh", "sqrt", "sum", "swap", - "switch", "tan", "tanh", "true", "trunc", "until", "var", - "while", "xnor", "xor", "&", "|" - }; - - static const std::size_t reserved_symbols_size = sizeof(reserved_symbols) / sizeof(std::string); - - static const std::string base_function_list[] = - { - "abs", "acos", "acosh", "asin", "asinh", "atan", "atanh", - "atan2", "avg", "ceil", "clamp", "cos", "cosh", "cot", - "csc", "equal", "erf", "erfc", "exp", "expm1", "floor", - "frac", "hypot", "iclamp", "like", "log", "log10", "log2", - "logn", "log1p", "mand", "max", "min", "mod", "mor", "mul", - "ncdf", "pow", "root", "round", "roundn", "sec", "sgn", - "sin", "sinc", "sinh", "sqrt", "sum", "swap", "tan", "tanh", - "trunc", "not_equal", "inrange", "deg2grad", "deg2rad", - "rad2deg", "grad2deg" - }; - - static const std::size_t base_function_list_size = sizeof(base_function_list) / sizeof(std::string); - - static const std::string logic_ops_list[] = - { - "and", "nand", "nor", "not", "or", "xnor", "xor", "&", "|" - }; - - static const std::size_t logic_ops_list_size = sizeof(logic_ops_list) / sizeof(std::string); - - static const std::string cntrl_struct_list[] = - { - "if", "switch", "for", "while", "repeat", "return" - }; - - static const std::size_t cntrl_struct_list_size = sizeof(cntrl_struct_list) / sizeof(std::string); - - static const std::string arithmetic_ops_list[] = - { - "+", "-", "*", "/", "%", "^" - }; - - static const std::size_t arithmetic_ops_list_size = sizeof(arithmetic_ops_list) / sizeof(std::string); - - static const std::string assignment_ops_list[] = - { - ":=", "+=", "-=", - "*=", "/=", "%=" - }; - - static const std::size_t assignment_ops_list_size = sizeof(assignment_ops_list) / sizeof(std::string); - - static const std::string inequality_ops_list[] = - { - "<", "<=", "==", - "=", "!=", "<>", - ">=", ">" - }; - - static const std::size_t inequality_ops_list_size = sizeof(inequality_ops_list) / sizeof(std::string); - - inline bool is_reserved_word(const std::string& symbol) - { - for (std::size_t i = 0; i < reserved_words_size; ++i) - { - if (imatch(symbol, reserved_words[i])) - { - return true; - } - } - - return false; - } - - inline bool is_reserved_symbol(const std::string& symbol) - { - for (std::size_t i = 0; i < reserved_symbols_size; ++i) - { - if (imatch(symbol, reserved_symbols[i])) - { - return true; - } - } - - return false; - } - - inline bool is_base_function(const std::string& function_name) - { - for (std::size_t i = 0; i < base_function_list_size; ++i) - { - if (imatch(function_name, base_function_list[i])) - { - return true; - } - } - - return false; - } - - inline bool is_control_struct(const std::string& cntrl_strct) - { - for (std::size_t i = 0; i < cntrl_struct_list_size; ++i) - { - if (imatch(cntrl_strct, cntrl_struct_list[i])) - { - return true; - } - } - - return false; - } - - inline bool is_logic_opr(const std::string& lgc_opr) - { - for (std::size_t i = 0; i < logic_ops_list_size; ++i) - { - if (imatch(lgc_opr, logic_ops_list[i])) - { - return true; - } - } - - return false; - } - - struct cs_match - { - static inline bool cmp(const char_t c0, const char_t c1) - { - return (c0 == c1); - } - }; - - struct cis_match - { - static inline bool cmp(const char_t c0, const char_t c1) - { - return (std::tolower(c0) == std::tolower(c1)); - } - }; - - template - inline bool match_impl(const Iterator pattern_begin, - const Iterator pattern_end , - const Iterator data_begin , - const Iterator data_end , - const typename std::iterator_traits::value_type& zero_or_more, - const typename std::iterator_traits::value_type& zero_or_one ) - { - const Iterator null_itr(0); - - Iterator d_itr = data_begin; - Iterator p_itr = pattern_begin; - Iterator tb_p_itr = null_itr; - Iterator tb_d_itr = null_itr; - - while (d_itr != data_end) - { - if (zero_or_more == *p_itr) - { - while ((pattern_end != p_itr) && ((zero_or_more == *p_itr) || (zero_or_one == *p_itr))) - { - ++p_itr; - } - - if (pattern_end == p_itr) - return true; - - const typename std::iterator_traits::value_type c = *(p_itr); - - while ((data_end != d_itr) && !Compare::cmp(c,*d_itr)) - { - ++d_itr; - } - - tb_p_itr = p_itr; - tb_d_itr = d_itr; - - continue; - } - else if (!Compare::cmp(*p_itr, *d_itr) && (zero_or_one != *p_itr)) - { - if (null_itr == tb_d_itr) - return false; - - d_itr = tb_d_itr++; - p_itr = tb_p_itr; - - continue; - } - - ++p_itr; - ++d_itr; - } - - while ((pattern_end != p_itr) && ((zero_or_more == *p_itr) || (zero_or_one == *p_itr))) - { - ++p_itr; - } - - return (pattern_end == p_itr); - } - - inline bool wc_match(const std::string& wild_card, - const std::string& str) - { - return match_impl( - wild_card.data(), wild_card.data() + wild_card.size(), - str.data(), str.data() + str.size(), - '*', '?'); - } - - inline bool wc_imatch(const std::string& wild_card, - const std::string& str) - { - return match_impl( - wild_card.data(), wild_card.data() + wild_card.size(), - str.data(), str.data() + str.size(), - '*', '?'); - } - - inline bool sequence_match(const std::string& pattern, - const std::string& str, - std::size_t& diff_index, - char_t& diff_value) - { - if (str.empty()) - { - return ("Z" == pattern); - } - else if ('*' == pattern[0]) - return false; - - typedef std::string::const_iterator itr_t; - - itr_t p_itr = pattern.begin(); - itr_t s_itr = str .begin(); - - itr_t p_end = pattern.end(); - itr_t s_end = str .end(); - - while ((s_end != s_itr) && (p_end != p_itr)) - { - if ('*' == (*p_itr)) - { - const char_t target = static_cast(std::toupper(*(p_itr - 1))); - - if ('*' == target) - { - diff_index = static_cast(std::distance(str.begin(),s_itr)); - diff_value = static_cast(std::toupper(*p_itr)); - - return false; - } - else - ++p_itr; - - while (s_itr != s_end) - { - if (target != std::toupper(*s_itr)) - break; - else - ++s_itr; - } - - continue; - } - else if ( - ('?' != *p_itr) && - std::toupper(*p_itr) != std::toupper(*s_itr) - ) - { - diff_index = static_cast(std::distance(str.begin(),s_itr)); - diff_value = static_cast(std::toupper(*p_itr)); - - return false; - } - - ++p_itr; - ++s_itr; - } - - return ( - (s_end == s_itr) && - ( - (p_end == p_itr) || - ('*' == *p_itr) - ) - ); - } - - static const double pow10[] = { - 1.0, - 1.0E+001, 1.0E+002, 1.0E+003, 1.0E+004, - 1.0E+005, 1.0E+006, 1.0E+007, 1.0E+008, - 1.0E+009, 1.0E+010, 1.0E+011, 1.0E+012, - 1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016 - }; - - static const std::size_t pow10_size = sizeof(pow10) / sizeof(double); - - namespace numeric - { - namespace constant - { - static const double e = 2.71828182845904523536028747135266249775724709369996; - static const double pi = 3.14159265358979323846264338327950288419716939937510; - static const double pi_2 = 1.57079632679489661923132169163975144209858469968755; - static const double pi_4 = 0.78539816339744830961566084581987572104929234984378; - static const double pi_180 = 0.01745329251994329576923690768488612713442871888542; - static const double _1_pi = 0.31830988618379067153776752674502872406891929148091; - static const double _2_pi = 0.63661977236758134307553505349005744813783858296183; - static const double _180_pi = 57.29577951308232087679815481410517033240547246656443; - static const double log2 = 0.69314718055994530941723212145817656807550013436026; - static const double sqrt2 = 1.41421356237309504880168872420969807856967187537695; - } - - namespace details - { - struct unknown_type_tag { unknown_type_tag() {} }; - struct real_type_tag { real_type_tag () {} }; - struct complex_type_tag { complex_type_tag() {} }; - struct int_type_tag { int_type_tag () {} }; - - template - struct number_type - { - typedef unknown_type_tag type; - number_type() {} - }; - - #define exprtk_register_real_type_tag(T) \ - template <> struct number_type \ - { typedef real_type_tag type; number_type() {} }; \ - - #define exprtk_register_complex_type_tag(T) \ - template <> struct number_type > \ - { typedef complex_type_tag type; number_type() {} }; \ - - #define exprtk_register_int_type_tag(T) \ - template <> struct number_type \ - { typedef int_type_tag type; number_type() {} }; \ - - exprtk_register_real_type_tag(double ) - exprtk_register_real_type_tag(long double) - exprtk_register_real_type_tag(float ) - - exprtk_register_complex_type_tag(double ) - exprtk_register_complex_type_tag(long double) - exprtk_register_complex_type_tag(float ) - - exprtk_register_int_type_tag(short ) - exprtk_register_int_type_tag(int ) - exprtk_register_int_type_tag(_int64_t ) - exprtk_register_int_type_tag(unsigned short) - exprtk_register_int_type_tag(unsigned int ) - exprtk_register_int_type_tag(_uint64_t ) - - #undef exprtk_register_real_type_tag - #undef exprtk_register_int_type_tag - - template - struct epsilon_type {}; - - #define exprtk_define_epsilon_type(Type, Epsilon) \ - template <> struct epsilon_type \ - { \ - static inline Type value() \ - { \ - const Type epsilon = static_cast(Epsilon); \ - return epsilon; \ - } \ - }; \ - - exprtk_define_epsilon_type(float , 0.000001f) - exprtk_define_epsilon_type(double , 0.0000000001) - exprtk_define_epsilon_type(long double, 0.000000000001) - - #undef exprtk_define_epsilon_type - - template - inline bool is_nan_impl(const T v, real_type_tag) - { - return std::not_equal_to()(v,v); - } - - template - inline int to_int32_impl(const T v, real_type_tag) - { - return static_cast(v); - } - - template - inline _int64_t to_int64_impl(const T v, real_type_tag) - { - return static_cast<_int64_t>(v); - } - - template - inline bool is_true_impl(const T v) - { - return std::not_equal_to()(T(0),v); - } - - template - inline bool is_false_impl(const T v) - { - return std::equal_to()(T(0),v); - } - - template - inline T abs_impl(const T v, real_type_tag) - { - return ((v < T(0)) ? -v : v); - } - - template - inline T min_impl(const T v0, const T v1, real_type_tag) - { - return std::min(v0,v1); - } - - template - inline T max_impl(const T v0, const T v1, real_type_tag) - { - return std::max(v0,v1); - } - - template - inline T equal_impl(const T v0, const T v1, real_type_tag) - { - const T epsilon = epsilon_type::value(); - return (abs_impl(v0 - v1,real_type_tag()) <= (std::max(T(1),std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? T(1) : T(0); - } - - inline float equal_impl(const float v0, const float v1, real_type_tag) - { - const float epsilon = epsilon_type::value(); - return (abs_impl(v0 - v1,real_type_tag()) <= (std::max(1.0f,std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? 1.0f : 0.0f; - } - - template - inline T equal_impl(const T v0, const T v1, int_type_tag) - { - return (v0 == v1) ? 1 : 0; - } - - template - inline T expm1_impl(const T v, real_type_tag) - { - // return std::expm1(v); - if (abs_impl(v,real_type_tag()) < T(0.00001)) - return v + (T(0.5) * v * v); - else - return std::exp(v) - T(1); - } - - template - inline T expm1_impl(const T v, int_type_tag) - { - return T(std::exp(v)) - T(1); - } - - template - inline T nequal_impl(const T v0, const T v1, real_type_tag) - { - typedef real_type_tag rtg; - const T epsilon = epsilon_type::value(); - return (abs_impl(v0 - v1,rtg()) > (std::max(T(1),std::max(abs_impl(v0,rtg()),abs_impl(v1,rtg()))) * epsilon)) ? T(1) : T(0); - } - - inline float nequal_impl(const float v0, const float v1, real_type_tag) - { - typedef real_type_tag rtg; - const float epsilon = epsilon_type::value(); - return (abs_impl(v0 - v1,rtg()) > (std::max(1.0f,std::max(abs_impl(v0,rtg()),abs_impl(v1,rtg()))) * epsilon)) ? 1.0f : 0.0f; - } - - template - inline T nequal_impl(const T v0, const T v1, int_type_tag) - { - return (v0 != v1) ? 1 : 0; - } - - template - inline T modulus_impl(const T v0, const T v1, real_type_tag) - { - return std::fmod(v0,v1); - } - - template - inline T modulus_impl(const T v0, const T v1, int_type_tag) - { - return v0 % v1; - } - - template - inline T pow_impl(const T v0, const T v1, real_type_tag) - { - return std::pow(v0,v1); - } - - template - inline T pow_impl(const T v0, const T v1, int_type_tag) - { - return std::pow(static_cast(v0),static_cast(v1)); - } - - template - inline T logn_impl(const T v0, const T v1, real_type_tag) - { - return std::log(v0) / std::log(v1); - } - - template - inline T logn_impl(const T v0, const T v1, int_type_tag) - { - return static_cast(logn_impl(static_cast(v0),static_cast(v1),real_type_tag())); - } - - template - inline T log1p_impl(const T v, real_type_tag) - { - if (v > T(-1)) - { - if (abs_impl(v,real_type_tag()) > T(0.0001)) - { - return std::log(T(1) + v); - } - else - return (T(-0.5) * v + T(1)) * v; - } - else - return std::numeric_limits::quiet_NaN(); - } - - template - inline T log1p_impl(const T v, int_type_tag) - { - if (v > T(-1)) - { - return std::log(T(1) + v); - } - else - return std::numeric_limits::quiet_NaN(); - } - - template - inline T root_impl(const T v0, const T v1, real_type_tag) - { - if (v1 < T(0)) - return std::numeric_limits::quiet_NaN(); - - const std::size_t n = static_cast(v1); - - if ((v0 < T(0)) && (0 == (n % 2))) - return std::numeric_limits::quiet_NaN(); - - return std::pow(v0, T(1) / n); - } - - template - inline T root_impl(const T v0, const T v1, int_type_tag) - { - return root_impl(static_cast(v0),static_cast(v1),real_type_tag()); - } - - template - inline T round_impl(const T v, real_type_tag) - { - return ((v < T(0)) ? std::ceil(v - T(0.5)) : std::floor(v + T(0.5))); - } - - template - inline T roundn_impl(const T v0, const T v1, real_type_tag) - { - const int index = std::max(0, std::min(pow10_size - 1, static_cast(std::floor(v1)))); - const T p10 = T(pow10[index]); - - if (v0 < T(0)) - return T(std::ceil ((v0 * p10) - T(0.5)) / p10); - else - return T(std::floor((v0 * p10) + T(0.5)) / p10); - } - - template - inline T roundn_impl(const T v0, const T, int_type_tag) - { - return v0; - } - - template - inline T hypot_impl(const T v0, const T v1, real_type_tag) - { - return std::sqrt((v0 * v0) + (v1 * v1)); - } - - template - inline T hypot_impl(const T v0, const T v1, int_type_tag) - { - return static_cast(std::sqrt(static_cast((v0 * v0) + (v1 * v1)))); - } - - template - inline T atan2_impl(const T v0, const T v1, real_type_tag) - { - return std::atan2(v0,v1); - } - - template - inline T atan2_impl(const T, const T, int_type_tag) - { - return 0; - } - - template - inline T shr_impl(const T v0, const T v1, real_type_tag) - { - return v0 * (T(1) / std::pow(T(2),static_cast(static_cast(v1)))); - } - - template - inline T shr_impl(const T v0, const T v1, int_type_tag) - { - return v0 >> v1; - } - - template - inline T shl_impl(const T v0, const T v1, real_type_tag) - { - return v0 * std::pow(T(2),static_cast(static_cast(v1))); - } - - template - inline T shl_impl(const T v0, const T v1, int_type_tag) - { - return v0 << v1; - } - - template - inline T sgn_impl(const T v, real_type_tag) - { - if (v > T(0)) return T(+1); - else if (v < T(0)) return T(-1); - else return T( 0); - } - - template - inline T sgn_impl(const T v, int_type_tag) - { - if (v > T(0)) return T(+1); - else if (v < T(0)) return T(-1); - else return T( 0); - } - - template - inline T and_impl(const T v0, const T v1, real_type_tag) - { - return (is_true_impl(v0) && is_true_impl(v1)) ? T(1) : T(0); - } - - template - inline T and_impl(const T v0, const T v1, int_type_tag) - { - return v0 && v1; - } - - template - inline T nand_impl(const T v0, const T v1, real_type_tag) - { - return (is_false_impl(v0) || is_false_impl(v1)) ? T(1) : T(0); - } - - template - inline T nand_impl(const T v0, const T v1, int_type_tag) - { - return !(v0 && v1); - } - - template - inline T or_impl(const T v0, const T v1, real_type_tag) - { - return (is_true_impl(v0) || is_true_impl(v1)) ? T(1) : T(0); - } - - template - inline T or_impl(const T v0, const T v1, int_type_tag) - { - return (v0 || v1); - } - - template - inline T nor_impl(const T v0, const T v1, real_type_tag) - { - return (is_false_impl(v0) && is_false_impl(v1)) ? T(1) : T(0); - } - - template - inline T nor_impl(const T v0, const T v1, int_type_tag) - { - return !(v0 || v1); - } - - template - inline T xor_impl(const T v0, const T v1, real_type_tag) - { - return (is_false_impl(v0) != is_false_impl(v1)) ? T(1) : T(0); - } - - template - inline T xor_impl(const T v0, const T v1, int_type_tag) - { - return v0 ^ v1; - } - - template - inline T xnor_impl(const T v0, const T v1, real_type_tag) - { - const bool v0_true = is_true_impl(v0); - const bool v1_true = is_true_impl(v1); - - if ((v0_true && v1_true) || (!v0_true && !v1_true)) - return T(1); - else - return T(0); - } - - template - inline T xnor_impl(const T v0, const T v1, int_type_tag) - { - const bool v0_true = is_true_impl(v0); - const bool v1_true = is_true_impl(v1); - - if ((v0_true && v1_true) || (!v0_true && !v1_true)) - return T(1); - else - return T(0); - } - - #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || !defined(_MSC_VER) - #define exprtk_define_erf(TT,impl) \ - inline TT erf_impl(TT v) { return impl(v); } \ - - exprtk_define_erf( float,::erff) - exprtk_define_erf( double,::erf ) - exprtk_define_erf(long double,::erfl) - #undef exprtk_define_erf - #endif - - template - inline T erf_impl(T v, real_type_tag) - { - #if defined(_MSC_VER) && (_MSC_VER < 1900) - // Credits: Abramowitz & Stegun Equations 7.1.25-28 - static const T c[] = { - T( 1.26551223), T(1.00002368), - T( 0.37409196), T(0.09678418), - T(-0.18628806), T(0.27886807), - T(-1.13520398), T(1.48851587), - T(-0.82215223), T(0.17087277) - }; - - const T t = T(1) / (T(1) + T(0.5) * abs_impl(v,real_type_tag())); - - T result = T(1) - t * std::exp((-v * v) - - c[0] + t * (c[1] + t * - (c[2] + t * (c[3] + t * - (c[4] + t * (c[5] + t * - (c[6] + t * (c[7] + t * - (c[8] + t * (c[9])))))))))); - - return (v >= T(0)) ? result : -result; - #else - return erf_impl(v); - #endif - } - - template - inline T erf_impl(T v, int_type_tag) - { - return erf_impl(static_cast(v),real_type_tag()); - } - - #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || !defined(_MSC_VER) - #define exprtk_define_erfc(TT,impl) \ - inline TT erfc_impl(TT v) { return impl(v); } \ - - exprtk_define_erfc( float,::erfcf) - exprtk_define_erfc( double,::erfc ) - exprtk_define_erfc(long double,::erfcl) - #undef exprtk_define_erfc - #endif - - template - inline T erfc_impl(T v, real_type_tag) - { - #if defined(_MSC_VER) && (_MSC_VER < 1900) - return T(1) - erf_impl(v,real_type_tag()); - #else - return erfc_impl(v); - #endif - } - - template - inline T erfc_impl(T v, int_type_tag) - { - return erfc_impl(static_cast(v),real_type_tag()); - } - - template - inline T ncdf_impl(T v, real_type_tag) - { - T cnd = T(0.5) * (T(1) + erf_impl( - abs_impl(v,real_type_tag()) / - T(numeric::constant::sqrt2),real_type_tag())); - return (v < T(0)) ? (T(1) - cnd) : cnd; - } - - template - inline T ncdf_impl(T v, int_type_tag) - { - return ncdf_impl(static_cast(v),real_type_tag()); - } - - template - inline T sinc_impl(T v, real_type_tag) - { - if (std::abs(v) >= std::numeric_limits::epsilon()) - return(std::sin(v) / v); - else - return T(1); - } - - template - inline T sinc_impl(T v, int_type_tag) - { - return sinc_impl(static_cast(v),real_type_tag()); - } - - template inline T acos_impl(const T v, real_type_tag) { return std::acos (v); } - template inline T acosh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) - T(1))); } - template inline T asin_impl(const T v, real_type_tag) { return std::asin (v); } - template inline T asinh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) + T(1))); } - template inline T atan_impl(const T v, real_type_tag) { return std::atan (v); } - template inline T atanh_impl(const T v, real_type_tag) { return (std::log(T(1) + v) - std::log(T(1) - v)) / T(2); } - template inline T ceil_impl(const T v, real_type_tag) { return std::ceil (v); } - template inline T cos_impl(const T v, real_type_tag) { return std::cos (v); } - template inline T cosh_impl(const T v, real_type_tag) { return std::cosh (v); } - template inline T exp_impl(const T v, real_type_tag) { return std::exp (v); } - template inline T floor_impl(const T v, real_type_tag) { return std::floor(v); } - template inline T log_impl(const T v, real_type_tag) { return std::log (v); } - template inline T log10_impl(const T v, real_type_tag) { return std::log10(v); } - template inline T log2_impl(const T v, real_type_tag) { return std::log(v)/T(numeric::constant::log2); } - template inline T neg_impl(const T v, real_type_tag) { return -v; } - template inline T pos_impl(const T v, real_type_tag) { return +v; } - template inline T sin_impl(const T v, real_type_tag) { return std::sin (v); } - template inline T sinh_impl(const T v, real_type_tag) { return std::sinh (v); } - template inline T sqrt_impl(const T v, real_type_tag) { return std::sqrt (v); } - template inline T tan_impl(const T v, real_type_tag) { return std::tan (v); } - template inline T tanh_impl(const T v, real_type_tag) { return std::tanh (v); } - template inline T cot_impl(const T v, real_type_tag) { return T(1) / std::tan(v); } - template inline T sec_impl(const T v, real_type_tag) { return T(1) / std::cos(v); } - template inline T csc_impl(const T v, real_type_tag) { return T(1) / std::sin(v); } - template inline T r2d_impl(const T v, real_type_tag) { return (v * T(numeric::constant::_180_pi)); } - template inline T d2r_impl(const T v, real_type_tag) { return (v * T(numeric::constant::pi_180)); } - template inline T d2g_impl(const T v, real_type_tag) { return (v * T(20.0/9.0)); } - template inline T g2d_impl(const T v, real_type_tag) { return (v * T(9.0/20.0)); } - template inline T notl_impl(const T v, real_type_tag) { return (std::not_equal_to()(T(0),v) ? T(0) : T(1)); } - template inline T frac_impl(const T v, real_type_tag) { return (v - static_cast(v)); } - template inline T trunc_impl(const T v, real_type_tag) { return T(static_cast(v)); } - - template inline T const_pi_impl(real_type_tag) { return T(numeric::constant::pi); } - template inline T const_e_impl (real_type_tag) { return T(numeric::constant::e); } - - template inline T abs_impl(const T v, int_type_tag) { return ((v >= T(0)) ? v : -v); } - template inline T exp_impl(const T v, int_type_tag) { return std::exp (v); } - template inline T log_impl(const T v, int_type_tag) { return std::log (v); } - template inline T log10_impl(const T v, int_type_tag) { return std::log10(v); } - template inline T log2_impl(const T v, int_type_tag) { return std::log(v)/T(numeric::constant::log2); } - template inline T neg_impl(const T v, int_type_tag) { return -v; } - template inline T pos_impl(const T v, int_type_tag) { return +v; } - template inline T ceil_impl(const T v, int_type_tag) { return v; } - template inline T floor_impl(const T v, int_type_tag) { return v; } - template inline T round_impl(const T v, int_type_tag) { return v; } - template inline T notl_impl(const T v, int_type_tag) { return !v; } - template inline T sqrt_impl(const T v, int_type_tag) { return std::sqrt (v); } - template inline T frac_impl(const T , int_type_tag) { return T(0); } - template inline T trunc_impl(const T v, int_type_tag) { return v; } - template inline T acos_impl(const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } - template inline T acosh_impl(const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } - template inline T asin_impl(const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } - template inline T asinh_impl(const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } - template inline T atan_impl(const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } - template inline T atanh_impl(const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } - template inline T cos_impl(const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } - template inline T cosh_impl(const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } - template inline T sin_impl(const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } - template inline T sinh_impl(const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } - template inline T tan_impl(const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } - template inline T tanh_impl(const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } - template inline T cot_impl(const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } - template inline T sec_impl(const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } - template inline T csc_impl(const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } - - template - inline bool is_integer_impl(const T& v, real_type_tag) - { - return std::equal_to()(T(0),std::fmod(v,T(1))); - } - - template - inline bool is_integer_impl(const T&, int_type_tag) - { - return true; - } - } - - template - struct numeric_info { enum { length = 0, size = 32, bound_length = 0, min_exp = 0, max_exp = 0 }; }; - - template <> struct numeric_info { enum { length = 10, size = 16, bound_length = 9}; }; - template <> struct numeric_info { enum { min_exp = -38, max_exp = +38}; }; - template <> struct numeric_info { enum { min_exp = -308, max_exp = +308}; }; - template <> struct numeric_info { enum { min_exp = -308, max_exp = +308}; }; - - template - inline int to_int32(const T v) - { - const typename details::number_type::type num_type; - return to_int32_impl(v, num_type); - } - - template - inline _int64_t to_int64(const T v) - { - const typename details::number_type::type num_type; - return to_int64_impl(v, num_type); - } - - template - inline bool is_nan(const T v) - { - const typename details::number_type::type num_type; - return is_nan_impl(v, num_type); - } - - template - inline T min(const T v0, const T v1) - { - const typename details::number_type::type num_type; - return min_impl(v0, v1, num_type); - } - - template - inline T max(const T v0, const T v1) - { - const typename details::number_type::type num_type; - return max_impl(v0, v1, num_type); - } - - template - inline T equal(const T v0, const T v1) - { - const typename details::number_type::type num_type; - return equal_impl(v0, v1, num_type); - } - - template - inline T nequal(const T v0, const T v1) - { - const typename details::number_type::type num_type; - return nequal_impl(v0, v1, num_type); - } - - template - inline T modulus(const T v0, const T v1) - { - const typename details::number_type::type num_type; - return modulus_impl(v0, v1, num_type); - } - - template - inline T pow(const T v0, const T v1) - { - const typename details::number_type::type num_type; - return pow_impl(v0, v1, num_type); - } - - template - inline T logn(const T v0, const T v1) - { - const typename details::number_type::type num_type; - return logn_impl(v0, v1, num_type); - } - - template - inline T root(const T v0, const T v1) - { - const typename details::number_type::type num_type; - return root_impl(v0, v1, num_type); - } - - template - inline T roundn(const T v0, const T v1) - { - const typename details::number_type::type num_type; - return roundn_impl(v0, v1, num_type); - } - - template - inline T hypot(const T v0, const T v1) - { - const typename details::number_type::type num_type; - return hypot_impl(v0, v1, num_type); - } - - template - inline T atan2(const T v0, const T v1) - { - const typename details::number_type::type num_type; - return atan2_impl(v0, v1, num_type); - } - - template - inline T shr(const T v0, const T v1) - { - const typename details::number_type::type num_type; - return shr_impl(v0, v1, num_type); - } - - template - inline T shl(const T v0, const T v1) - { - const typename details::number_type::type num_type; - return shl_impl(v0, v1, num_type); - } - - template - inline T and_opr(const T v0, const T v1) - { - const typename details::number_type::type num_type; - return and_impl(v0, v1, num_type); - } - - template - inline T nand_opr(const T v0, const T v1) - { - const typename details::number_type::type num_type; - return nand_impl(v0, v1, num_type); - } - - template - inline T or_opr(const T v0, const T v1) - { - const typename details::number_type::type num_type; - return or_impl(v0, v1, num_type); - } - - template - inline T nor_opr(const T v0, const T v1) - { - const typename details::number_type::type num_type; - return nor_impl(v0, v1, num_type); - } - - template - inline T xor_opr(const T v0, const T v1) - { - const typename details::number_type::type num_type; - return xor_impl(v0, v1, num_type); - } - - template - inline T xnor_opr(const T v0, const T v1) - { - const typename details::number_type::type num_type; - return xnor_impl(v0, v1, num_type); - } - - template - inline bool is_integer(const T v) - { - const typename details::number_type::type num_type; - return is_integer_impl(v, num_type); - } - - template - struct fast_exp - { - static inline T result(T v) - { - unsigned int k = N; - T l = T(1); - - while (k) - { - if (k & 1) - { - l *= v; - --k; - } - - v *= v; - k >>= 1; - } - - return l; - } - }; - - template struct fast_exp { static inline T result(const T v) { T v_5 = fast_exp::result(v); return v_5 * v_5; } }; - template struct fast_exp { static inline T result(const T v) { return fast_exp::result(v) * v; } }; - template struct fast_exp { static inline T result(const T v) { T v_4 = fast_exp::result(v); return v_4 * v_4; } }; - template struct fast_exp { static inline T result(const T v) { return fast_exp::result(v) * v; } }; - template struct fast_exp { static inline T result(const T v) { T v_3 = fast_exp::result(v); return v_3 * v_3; } }; - template struct fast_exp { static inline T result(const T v) { return fast_exp::result(v) * v; } }; - template struct fast_exp { static inline T result(const T v) { T v_2 = v * v; return v_2 * v_2; } }; - template struct fast_exp { static inline T result(const T v) { return v * v * v; } }; - template struct fast_exp { static inline T result(const T v) { return v * v; } }; - template struct fast_exp { static inline T result(const T v) { return v; } }; - template struct fast_exp { static inline T result(const T ) { return T(1); } }; - - #define exprtk_define_unary_function(FunctionName) \ - template \ - inline T FunctionName (const T v) \ - { \ - const typename details::number_type::type num_type; \ - return FunctionName##_impl(v,num_type); \ - } \ - - exprtk_define_unary_function(abs ) - exprtk_define_unary_function(acos ) - exprtk_define_unary_function(acosh) - exprtk_define_unary_function(asin ) - exprtk_define_unary_function(asinh) - exprtk_define_unary_function(atan ) - exprtk_define_unary_function(atanh) - exprtk_define_unary_function(ceil ) - exprtk_define_unary_function(cos ) - exprtk_define_unary_function(cosh ) - exprtk_define_unary_function(exp ) - exprtk_define_unary_function(expm1) - exprtk_define_unary_function(floor) - exprtk_define_unary_function(log ) - exprtk_define_unary_function(log10) - exprtk_define_unary_function(log2 ) - exprtk_define_unary_function(log1p) - exprtk_define_unary_function(neg ) - exprtk_define_unary_function(pos ) - exprtk_define_unary_function(round) - exprtk_define_unary_function(sin ) - exprtk_define_unary_function(sinc ) - exprtk_define_unary_function(sinh ) - exprtk_define_unary_function(sqrt ) - exprtk_define_unary_function(tan ) - exprtk_define_unary_function(tanh ) - exprtk_define_unary_function(cot ) - exprtk_define_unary_function(sec ) - exprtk_define_unary_function(csc ) - exprtk_define_unary_function(r2d ) - exprtk_define_unary_function(d2r ) - exprtk_define_unary_function(d2g ) - exprtk_define_unary_function(g2d ) - exprtk_define_unary_function(notl ) - exprtk_define_unary_function(sgn ) - exprtk_define_unary_function(erf ) - exprtk_define_unary_function(erfc ) - exprtk_define_unary_function(ncdf ) - exprtk_define_unary_function(frac ) - exprtk_define_unary_function(trunc) - #undef exprtk_define_unary_function - } - - template - inline T compute_pow10(T d, const int exponent) - { - static const double fract10[] = - { - 0.0, - 1.0E+001, 1.0E+002, 1.0E+003, 1.0E+004, 1.0E+005, 1.0E+006, 1.0E+007, 1.0E+008, 1.0E+009, 1.0E+010, - 1.0E+011, 1.0E+012, 1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016, 1.0E+017, 1.0E+018, 1.0E+019, 1.0E+020, - 1.0E+021, 1.0E+022, 1.0E+023, 1.0E+024, 1.0E+025, 1.0E+026, 1.0E+027, 1.0E+028, 1.0E+029, 1.0E+030, - 1.0E+031, 1.0E+032, 1.0E+033, 1.0E+034, 1.0E+035, 1.0E+036, 1.0E+037, 1.0E+038, 1.0E+039, 1.0E+040, - 1.0E+041, 1.0E+042, 1.0E+043, 1.0E+044, 1.0E+045, 1.0E+046, 1.0E+047, 1.0E+048, 1.0E+049, 1.0E+050, - 1.0E+051, 1.0E+052, 1.0E+053, 1.0E+054, 1.0E+055, 1.0E+056, 1.0E+057, 1.0E+058, 1.0E+059, 1.0E+060, - 1.0E+061, 1.0E+062, 1.0E+063, 1.0E+064, 1.0E+065, 1.0E+066, 1.0E+067, 1.0E+068, 1.0E+069, 1.0E+070, - 1.0E+071, 1.0E+072, 1.0E+073, 1.0E+074, 1.0E+075, 1.0E+076, 1.0E+077, 1.0E+078, 1.0E+079, 1.0E+080, - 1.0E+081, 1.0E+082, 1.0E+083, 1.0E+084, 1.0E+085, 1.0E+086, 1.0E+087, 1.0E+088, 1.0E+089, 1.0E+090, - 1.0E+091, 1.0E+092, 1.0E+093, 1.0E+094, 1.0E+095, 1.0E+096, 1.0E+097, 1.0E+098, 1.0E+099, 1.0E+100, - 1.0E+101, 1.0E+102, 1.0E+103, 1.0E+104, 1.0E+105, 1.0E+106, 1.0E+107, 1.0E+108, 1.0E+109, 1.0E+110, - 1.0E+111, 1.0E+112, 1.0E+113, 1.0E+114, 1.0E+115, 1.0E+116, 1.0E+117, 1.0E+118, 1.0E+119, 1.0E+120, - 1.0E+121, 1.0E+122, 1.0E+123, 1.0E+124, 1.0E+125, 1.0E+126, 1.0E+127, 1.0E+128, 1.0E+129, 1.0E+130, - 1.0E+131, 1.0E+132, 1.0E+133, 1.0E+134, 1.0E+135, 1.0E+136, 1.0E+137, 1.0E+138, 1.0E+139, 1.0E+140, - 1.0E+141, 1.0E+142, 1.0E+143, 1.0E+144, 1.0E+145, 1.0E+146, 1.0E+147, 1.0E+148, 1.0E+149, 1.0E+150, - 1.0E+151, 1.0E+152, 1.0E+153, 1.0E+154, 1.0E+155, 1.0E+156, 1.0E+157, 1.0E+158, 1.0E+159, 1.0E+160, - 1.0E+161, 1.0E+162, 1.0E+163, 1.0E+164, 1.0E+165, 1.0E+166, 1.0E+167, 1.0E+168, 1.0E+169, 1.0E+170, - 1.0E+171, 1.0E+172, 1.0E+173, 1.0E+174, 1.0E+175, 1.0E+176, 1.0E+177, 1.0E+178, 1.0E+179, 1.0E+180, - 1.0E+181, 1.0E+182, 1.0E+183, 1.0E+184, 1.0E+185, 1.0E+186, 1.0E+187, 1.0E+188, 1.0E+189, 1.0E+190, - 1.0E+191, 1.0E+192, 1.0E+193, 1.0E+194, 1.0E+195, 1.0E+196, 1.0E+197, 1.0E+198, 1.0E+199, 1.0E+200, - 1.0E+201, 1.0E+202, 1.0E+203, 1.0E+204, 1.0E+205, 1.0E+206, 1.0E+207, 1.0E+208, 1.0E+209, 1.0E+210, - 1.0E+211, 1.0E+212, 1.0E+213, 1.0E+214, 1.0E+215, 1.0E+216, 1.0E+217, 1.0E+218, 1.0E+219, 1.0E+220, - 1.0E+221, 1.0E+222, 1.0E+223, 1.0E+224, 1.0E+225, 1.0E+226, 1.0E+227, 1.0E+228, 1.0E+229, 1.0E+230, - 1.0E+231, 1.0E+232, 1.0E+233, 1.0E+234, 1.0E+235, 1.0E+236, 1.0E+237, 1.0E+238, 1.0E+239, 1.0E+240, - 1.0E+241, 1.0E+242, 1.0E+243, 1.0E+244, 1.0E+245, 1.0E+246, 1.0E+247, 1.0E+248, 1.0E+249, 1.0E+250, - 1.0E+251, 1.0E+252, 1.0E+253, 1.0E+254, 1.0E+255, 1.0E+256, 1.0E+257, 1.0E+258, 1.0E+259, 1.0E+260, - 1.0E+261, 1.0E+262, 1.0E+263, 1.0E+264, 1.0E+265, 1.0E+266, 1.0E+267, 1.0E+268, 1.0E+269, 1.0E+270, - 1.0E+271, 1.0E+272, 1.0E+273, 1.0E+274, 1.0E+275, 1.0E+276, 1.0E+277, 1.0E+278, 1.0E+279, 1.0E+280, - 1.0E+281, 1.0E+282, 1.0E+283, 1.0E+284, 1.0E+285, 1.0E+286, 1.0E+287, 1.0E+288, 1.0E+289, 1.0E+290, - 1.0E+291, 1.0E+292, 1.0E+293, 1.0E+294, 1.0E+295, 1.0E+296, 1.0E+297, 1.0E+298, 1.0E+299, 1.0E+300, - 1.0E+301, 1.0E+302, 1.0E+303, 1.0E+304, 1.0E+305, 1.0E+306, 1.0E+307, 1.0E+308 - }; - - static const int fract10_size = static_cast(sizeof(fract10) / sizeof(double)); - - const int e = std::abs(exponent); - - if (exponent >= std::numeric_limits::min_exponent10) - { - if (e < fract10_size) - { - if (exponent > 0) - return T(d * fract10[e]); - else - return T(d / fract10[e]); - } - else - return T(d * std::pow(10.0, 10.0 * exponent)); - } - else - { - d /= T(fract10[ -std::numeric_limits::min_exponent10]); - return T(d / fract10[-exponent + std::numeric_limits::min_exponent10]); - } - } - - template - inline bool string_to_type_converter_impl_ref(Iterator& itr, const Iterator end, T& result) - { - if (itr == end) - return false; - - const bool negative = ('-' == (*itr)); - - if (negative || ('+' == (*itr))) - { - if (end == ++itr) - return false; - } - - static const uchar_t zero = static_cast('0'); - - while ((end != itr) && (zero == (*itr))) ++itr; - - bool return_result = true; - unsigned int digit = 0; - const std::size_t length = static_cast(std::distance(itr,end)); - - if (length <= 4) - { - exprtk_disable_fallthrough_begin - switch (length) - { - #ifdef exprtk_use_lut - - #define exprtk_process_digit \ - if ((digit = details::digit_table[(int)*itr++]) < 10) \ - result = result * 10 + (digit); \ - else \ - { \ - return_result = false; \ - break; \ - } \ - - #else - - #define exprtk_process_digit \ - if ((digit = (*itr++ - zero)) < 10) \ - result = result * T(10) + digit; \ - else \ - { \ - return_result = false; \ - break; \ - } \ - - #endif - - case 4 : exprtk_process_digit - case 3 : exprtk_process_digit - case 2 : exprtk_process_digit - case 1 : if ((digit = (*itr - zero))>= 10) { digit = 0; return_result = false; } - - #undef exprtk_process_digit - } - exprtk_disable_fallthrough_end - } - else - return_result = false; - - if (length && return_result) - { - result = result * 10 + static_cast(digit); - ++itr; - } - - result = negative ? -result : result; - return return_result; - } - - template - static inline bool parse_nan(Iterator& itr, const Iterator end, T& t) - { - typedef typename std::iterator_traits::value_type type; - - static const std::size_t nan_length = 3; - - if (std::distance(itr,end) != static_cast(nan_length)) - return false; - - if (static_cast('n') == (*itr)) - { - if ( - (static_cast('a') != *(itr + 1)) || - (static_cast('n') != *(itr + 2)) - ) - { - return false; - } - } - else if ( - (static_cast('A') != *(itr + 1)) || - (static_cast('N') != *(itr + 2)) - ) - { - return false; - } - - t = std::numeric_limits::quiet_NaN(); - - return true; - } - - template - static inline bool parse_inf(Iterator& itr, const Iterator end, T& t, bool negative) - { - static const char_t inf_uc[] = "INFINITY"; - static const char_t inf_lc[] = "infinity"; - static const std::size_t inf_length = 8; - - const std::size_t length = static_cast(std::distance(itr,end)); - - if ((3 != length) && (inf_length != length)) - return false; - - char_cptr inf_itr = ('i' == (*itr)) ? inf_lc : inf_uc; - - while (end != itr) - { - if (*inf_itr == static_cast(*itr)) - { - ++itr; - ++inf_itr; - continue; - } - else - return false; - } - - if (negative) - t = -std::numeric_limits::infinity(); - else - t = std::numeric_limits::infinity(); - - return true; - } - - template - inline bool valid_exponent(const int exponent, numeric::details::real_type_tag) - { - using namespace details::numeric; - return (numeric_info::min_exp <= exponent) && (exponent <= numeric_info::max_exp); - } - - template - inline bool string_to_real(Iterator& itr_external, const Iterator end, T& t, numeric::details::real_type_tag) - { - if (end == itr_external) return false; - - Iterator itr = itr_external; - - T d = T(0); - - const bool negative = ('-' == (*itr)); - - if (negative || '+' == (*itr)) - { - if (end == ++itr) - return false; - } - - bool instate = false; - - static const char_t zero = static_cast('0'); - - #define parse_digit_1(d) \ - if ((digit = (*itr - zero)) < 10) \ - { d = d * T(10) + digit; } \ - else \ - { break; } \ - if (end == ++itr) break; \ - - #define parse_digit_2(d) \ - if ((digit = (*itr - zero)) < 10) \ - { d = d * T(10) + digit; } \ - else { break; } \ - ++itr; \ - - if ('.' != (*itr)) - { - const Iterator curr = itr; - - while ((end != itr) && (zero == (*itr))) ++itr; - - while (end != itr) - { - unsigned int digit; - parse_digit_1(d) - parse_digit_1(d) - parse_digit_2(d) - } - - if (curr != itr) instate = true; - } - - int exponent = 0; - - if (end != itr) - { - if ('.' == (*itr)) - { - const Iterator curr = ++itr; - T tmp_d = T(0); - - while (end != itr) - { - unsigned int digit; - parse_digit_1(tmp_d) - parse_digit_1(tmp_d) - parse_digit_2(tmp_d) - } - - if (curr != itr) - { - instate = true; - - const int frac_exponent = static_cast(-std::distance(curr, itr)); - - if (!valid_exponent(frac_exponent, numeric::details::real_type_tag())) - return false; - - d += compute_pow10(tmp_d, frac_exponent); - } - - #undef parse_digit_1 - #undef parse_digit_2 - } - - if (end != itr) - { - typename std::iterator_traits::value_type c = (*itr); - - if (('e' == c) || ('E' == c)) - { - int exp = 0; - - if (!details::string_to_type_converter_impl_ref(++itr, end, exp)) - { - if (end == itr) - return false; - else - c = (*itr); - } - - exponent += exp; - } - - if (end != itr) - { - if (('f' == c) || ('F' == c) || ('l' == c) || ('L' == c)) - ++itr; - else if ('#' == c) - { - if (end == ++itr) - return false; - else if (('I' <= (*itr)) && ((*itr) <= 'n')) - { - if (('i' == (*itr)) || ('I' == (*itr))) - { - return parse_inf(itr, end, t, negative); - } - else if (('n' == (*itr)) || ('N' == (*itr))) - { - return parse_nan(itr, end, t); - } - else - return false; - } - else - return false; - } - else if (('I' <= (*itr)) && ((*itr) <= 'n')) - { - if (('i' == (*itr)) || ('I' == (*itr))) - { - return parse_inf(itr, end, t, negative); - } - else if (('n' == (*itr)) || ('N' == (*itr))) - { - return parse_nan(itr, end, t); - } - else - return false; - } - else - return false; - } - } - } - - if ((end != itr) || (!instate)) - return false; - else if (!valid_exponent(exponent, numeric::details::real_type_tag())) - return false; - else if (exponent) - d = compute_pow10(d,exponent); - - t = static_cast((negative) ? -d : d); - return true; - } - - template - inline bool string_to_real(const std::string& s, T& t) - { - const typename numeric::details::number_type::type num_type; - - char_cptr begin = s.data(); - char_cptr end = s.data() + s.size(); - - return string_to_real(begin, end, t, num_type); - } - - template - struct functor_t - { - /* - Note: The following definitions for Type, may require tweaking - based on the compiler and target architecture. The benchmark - should provide enough information to make the right choice. - */ - //typedef T Type; - //typedef const T Type; - typedef const T& Type; - typedef T& RefType; - typedef T (*qfunc_t)(Type t0, Type t1, Type t2, Type t3); - typedef T (*tfunc_t)(Type t0, Type t1, Type t2); - typedef T (*bfunc_t)(Type t0, Type t1); - typedef T (*ufunc_t)(Type t0); - }; - - } // namespace details - - struct loop_runtime_check - { - enum loop_types - { - e_invalid = 0, - e_for_loop = 1, - e_while_loop = 2, - e_repeat_until_loop = 4, - e_all_loops = 7 - }; - - enum violation_type - { - e_unknown = 0, - e_iteration_count = 1, - e_timeout = 2 - }; - - loop_types loop_set; - - loop_runtime_check() - : loop_set(e_invalid), - max_loop_iterations(0) - {} - - details::_uint64_t max_loop_iterations; - - struct violation_context - { - loop_types loop; - violation_type violation; - details::_uint64_t iteration_count; - }; - - virtual void handle_runtime_violation(const violation_context&) - { - throw std::runtime_error("ExprTk Loop run-time violation."); - } - - virtual ~loop_runtime_check() {} - }; - - typedef loop_runtime_check* loop_runtime_check_ptr; - - namespace lexer - { - struct token - { - enum token_type - { - e_none = 0, e_error = 1, e_err_symbol = 2, - e_err_number = 3, e_err_string = 4, e_err_sfunc = 5, - e_eof = 6, e_number = 7, e_symbol = 8, - e_string = 9, e_assign = 10, e_addass = 11, - e_subass = 12, e_mulass = 13, e_divass = 14, - e_modass = 15, e_shr = 16, e_shl = 17, - e_lte = 18, e_ne = 19, e_gte = 20, - e_swap = 21, e_lt = '<', e_gt = '>', - e_eq = '=', e_rbracket = ')', e_lbracket = '(', - e_rsqrbracket = ']', e_lsqrbracket = '[', e_rcrlbracket = '}', - e_lcrlbracket = '{', e_comma = ',', e_add = '+', - e_sub = '-', e_div = '/', e_mul = '*', - e_mod = '%', e_pow = '^', e_colon = ':', - e_ternary = '?' - }; - - token() - : type(e_none), - value(""), - position(std::numeric_limits::max()) - {} - - void clear() - { - type = e_none; - value = ""; - position = std::numeric_limits::max(); - } - - template - inline token& set_operator(const token_type tt, - const Iterator begin, const Iterator end, - const Iterator base_begin = Iterator(0)) - { - type = tt; - value.assign(begin,end); - if (base_begin) - position = static_cast(std::distance(base_begin,begin)); - return (*this); - } - - template - inline token& set_symbol(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0)) - { - type = e_symbol; - value.assign(begin,end); - if (base_begin) - position = static_cast(std::distance(base_begin,begin)); - return (*this); - } - - template - inline token& set_numeric(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0)) - { - type = e_number; - value.assign(begin,end); - if (base_begin) - position = static_cast(std::distance(base_begin,begin)); - return (*this); - } - - template - inline token& set_string(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0)) - { - type = e_string; - value.assign(begin,end); - if (base_begin) - position = static_cast(std::distance(base_begin,begin)); - return (*this); - } - - inline token& set_string(const std::string& s, const std::size_t p) - { - type = e_string; - value = s; - position = p; - return (*this); - } - - template - inline token& set_error(const token_type et, - const Iterator begin, const Iterator end, - const Iterator base_begin = Iterator(0)) - { - if ( - (e_error == et) || - (e_err_symbol == et) || - (e_err_number == et) || - (e_err_string == et) || - (e_err_sfunc == et) - ) - { - type = et; - } - else - type = e_error; - - value.assign(begin,end); - - if (base_begin) - position = static_cast(std::distance(base_begin,begin)); - - return (*this); - } - - static inline std::string to_str(token_type t) - { - switch (t) - { - case e_none : return "NONE"; - case e_error : return "ERROR"; - case e_err_symbol : return "ERROR_SYMBOL"; - case e_err_number : return "ERROR_NUMBER"; - case e_err_string : return "ERROR_STRING"; - case e_eof : return "EOF"; - case e_number : return "NUMBER"; - case e_symbol : return "SYMBOL"; - case e_string : return "STRING"; - case e_assign : return ":="; - case e_addass : return "+="; - case e_subass : return "-="; - case e_mulass : return "*="; - case e_divass : return "/="; - case e_modass : return "%="; - case e_shr : return ">>"; - case e_shl : return "<<"; - case e_lte : return "<="; - case e_ne : return "!="; - case e_gte : return ">="; - case e_lt : return "<"; - case e_gt : return ">"; - case e_eq : return "="; - case e_rbracket : return ")"; - case e_lbracket : return "("; - case e_rsqrbracket : return "]"; - case e_lsqrbracket : return "["; - case e_rcrlbracket : return "}"; - case e_lcrlbracket : return "{"; - case e_comma : return ","; - case e_add : return "+"; - case e_sub : return "-"; - case e_div : return "/"; - case e_mul : return "*"; - case e_mod : return "%"; - case e_pow : return "^"; - case e_colon : return ":"; - case e_ternary : return "?"; - case e_swap : return "<=>"; - default : return "UNKNOWN"; - } - } - - inline bool is_error() const - { - return ( - (e_error == type) || - (e_err_symbol == type) || - (e_err_number == type) || - (e_err_string == type) || - (e_err_sfunc == type) - ); - } - - token_type type; - std::string value; - std::size_t position; - }; - - class generator - { - public: - - typedef token token_t; - typedef std::vector token_list_t; - typedef token_list_t::iterator token_list_itr_t; - typedef details::char_t char_t; - - generator() - : base_itr_(0), - s_itr_ (0), - s_end_ (0) - { - clear(); - } - - inline void clear() - { - base_itr_ = 0; - s_itr_ = 0; - s_end_ = 0; - token_list_.clear(); - token_itr_ = token_list_.end(); - store_token_itr_ = token_list_.end(); - } - - inline bool process(const std::string& str) - { - base_itr_ = str.data(); - s_itr_ = str.data(); - s_end_ = str.data() + str.size(); - - eof_token_.set_operator(token_t::e_eof,s_end_,s_end_,base_itr_); - token_list_.clear(); - - while (!is_end(s_itr_)) - { - scan_token(); - - if (!token_list_.empty() && token_list_.back().is_error()) - return false; - } - - return true; - } - - inline bool empty() const - { - return token_list_.empty(); - } - - inline std::size_t size() const - { - return token_list_.size(); - } - - inline void begin() - { - token_itr_ = token_list_.begin(); - store_token_itr_ = token_list_.begin(); - } - - inline void store() - { - store_token_itr_ = token_itr_; - } - - inline void restore() - { - token_itr_ = store_token_itr_; - } - - inline token_t& next_token() - { - if (token_list_.end() != token_itr_) - { - return *token_itr_++; - } - else - return eof_token_; - } - - inline token_t& peek_next_token() - { - if (token_list_.end() != token_itr_) - { - return *token_itr_; - } - else - return eof_token_; - } - - inline token_t& operator[](const std::size_t& index) - { - if (index < token_list_.size()) - return token_list_[index]; - else - return eof_token_; - } - - inline token_t operator[](const std::size_t& index) const - { - if (index < token_list_.size()) - return token_list_[index]; - else - return eof_token_; - } - - inline bool finished() const - { - return (token_list_.end() == token_itr_); - } - - inline void insert_front(token_t::token_type tk_type) - { - if ( - !token_list_.empty() && - (token_list_.end() != token_itr_) - ) - { - token_t t = *token_itr_; - - t.type = tk_type; - token_itr_ = token_list_.insert(token_itr_,t); - } - } - - inline std::string substr(const std::size_t& begin, const std::size_t& end) - { - const details::char_cptr begin_itr = ((base_itr_ + begin) < s_end_) ? (base_itr_ + begin) : s_end_; - const details::char_cptr end_itr = ((base_itr_ + end) < s_end_) ? (base_itr_ + end) : s_end_; - - return std::string(begin_itr,end_itr); - } - - inline std::string remaining() const - { - if (finished()) - return ""; - else if (token_list_.begin() != token_itr_) - return std::string(base_itr_ + (token_itr_ - 1)->position, s_end_); - else - return std::string(base_itr_ + token_itr_->position, s_end_); - } - - private: - - inline bool is_end(details::char_cptr itr) - { - return (s_end_ == itr); - } - - #ifndef exprtk_disable_comments - inline bool is_comment_start(details::char_cptr itr) - { - const char_t c0 = *(itr + 0); - const char_t c1 = *(itr + 1); - - if ('#' == c0) - return true; - else if (!is_end(itr + 1)) - { - if (('/' == c0) && ('/' == c1)) return true; - if (('/' == c0) && ('*' == c1)) return true; - } - return false; - } - #else - inline bool is_comment_start(details::char_cptr) - { - return false; - } - #endif - - inline void skip_whitespace() - { - while (!is_end(s_itr_) && details::is_whitespace(*s_itr_)) - { - ++s_itr_; - } - } - - inline void skip_comments() - { - #ifndef exprtk_disable_comments - // The following comment styles are supported: - // 1. // .... \n - // 2. # .... \n - // 3. /* .... */ - struct test - { - static inline bool comment_start(const char_t c0, const char_t c1, int& mode, int& incr) - { - mode = 0; - if ('#' == c0) { mode = 1; incr = 1; } - else if ('/' == c0) - { - if ('/' == c1) { mode = 1; incr = 2; } - else if ('*' == c1) { mode = 2; incr = 2; } - } - return (0 != mode); - } - - static inline bool comment_end(const char_t c0, const char_t c1, int& mode) - { - if ( - ((1 == mode) && ('\n' == c0)) || - ((2 == mode) && ( '*' == c0) && ('/' == c1)) - ) - { - mode = 0; - return true; - } - else - return false; - } - }; - - int mode = 0; - int increment = 0; - - if (is_end(s_itr_)) - return; - else if (!test::comment_start(*s_itr_, *(s_itr_ + 1), mode, increment)) - return; - - details::char_cptr cmt_start = s_itr_; - - s_itr_ += increment; - - while (!is_end(s_itr_)) - { - if ((1 == mode) && test::comment_end(*s_itr_, 0, mode)) - { - ++s_itr_; - return; - } - - if ((2 == mode)) - { - if (!is_end((s_itr_ + 1)) && test::comment_end(*s_itr_, *(s_itr_ + 1), mode)) - { - s_itr_ += 2; - return; - } - } - - ++s_itr_; - } - - if (2 == mode) - { - token_t t; - t.set_error(token::e_error, cmt_start, cmt_start + mode, base_itr_); - token_list_.push_back(t); - } - #endif - } - - inline void scan_token() - { - if (details::is_whitespace(*s_itr_)) - { - skip_whitespace(); - return; - } - else if (is_comment_start(s_itr_)) - { - skip_comments(); - return; - } - else if (details::is_operator_char(*s_itr_)) - { - scan_operator(); - return; - } - else if (details::is_letter(*s_itr_)) - { - scan_symbol(); - return; - } - else if (details::is_digit((*s_itr_)) || ('.' == (*s_itr_))) - { - scan_number(); - return; - } - else if ('$' == (*s_itr_)) - { - scan_special_function(); - return; - } - #ifndef exprtk_disable_string_capabilities - else if ('\'' == (*s_itr_)) - { - scan_string(); - return; - } - #endif - else if ('~' == (*s_itr_)) - { - token_t t; - t.set_symbol(s_itr_, s_itr_ + 1, base_itr_); - token_list_.push_back(t); - ++s_itr_; - return; - } - else - { - token_t t; - t.set_error(token::e_error, s_itr_, s_itr_ + 2, base_itr_); - token_list_.push_back(t); - ++s_itr_; - } - } - - inline void scan_operator() - { - token_t t; - - const char_t c0 = s_itr_[0]; - - if (!is_end(s_itr_ + 1)) - { - const char_t c1 = s_itr_[1]; - - if (!is_end(s_itr_ + 2)) - { - const char_t c2 = s_itr_[2]; - - if ((c0 == '<') && (c1 == '=') && (c2 == '>')) - { - t.set_operator(token_t::e_swap, s_itr_, s_itr_ + 3, base_itr_); - token_list_.push_back(t); - s_itr_ += 3; - return; - } - } - - token_t::token_type ttype = token_t::e_none; - - if ((c0 == '<') && (c1 == '=')) ttype = token_t::e_lte; - else if ((c0 == '>') && (c1 == '=')) ttype = token_t::e_gte; - else if ((c0 == '<') && (c1 == '>')) ttype = token_t::e_ne; - else if ((c0 == '!') && (c1 == '=')) ttype = token_t::e_ne; - else if ((c0 == '=') && (c1 == '=')) ttype = token_t::e_eq; - else if ((c0 == ':') && (c1 == '=')) ttype = token_t::e_assign; - else if ((c0 == '<') && (c1 == '<')) ttype = token_t::e_shl; - else if ((c0 == '>') && (c1 == '>')) ttype = token_t::e_shr; - else if ((c0 == '+') && (c1 == '=')) ttype = token_t::e_addass; - else if ((c0 == '-') && (c1 == '=')) ttype = token_t::e_subass; - else if ((c0 == '*') && (c1 == '=')) ttype = token_t::e_mulass; - else if ((c0 == '/') && (c1 == '=')) ttype = token_t::e_divass; - else if ((c0 == '%') && (c1 == '=')) ttype = token_t::e_modass; - - if (token_t::e_none != ttype) - { - t.set_operator(ttype, s_itr_, s_itr_ + 2, base_itr_); - token_list_.push_back(t); - s_itr_ += 2; - return; - } - } - - if ('<' == c0) - t.set_operator(token_t::e_lt , s_itr_, s_itr_ + 1, base_itr_); - else if ('>' == c0) - t.set_operator(token_t::e_gt , s_itr_, s_itr_ + 1, base_itr_); - else if (';' == c0) - t.set_operator(token_t::e_eof, s_itr_, s_itr_ + 1, base_itr_); - else if ('&' == c0) - t.set_symbol(s_itr_, s_itr_ + 1, base_itr_); - else if ('|' == c0) - t.set_symbol(s_itr_, s_itr_ + 1, base_itr_); - else - t.set_operator(token_t::token_type(c0), s_itr_, s_itr_ + 1, base_itr_); - - token_list_.push_back(t); - ++s_itr_; - } - - inline void scan_symbol() - { - details::char_cptr initial_itr = s_itr_; - - while (!is_end(s_itr_)) - { - if (!details::is_letter_or_digit(*s_itr_) && ('_' != (*s_itr_))) - { - if ('.' != (*s_itr_)) - break; - /* - Permit symbols that contain a 'dot' - Allowed : abc.xyz, a123.xyz, abc.123, abc_.xyz a123_.xyz abc._123 - Disallowed: .abc, abc., abc., abc. - */ - if ( - (s_itr_ != initial_itr) && - !is_end(s_itr_ + 1) && - !details::is_letter_or_digit(*(s_itr_ + 1)) && - ('_' != (*(s_itr_ + 1))) - ) - break; - } - - ++s_itr_; - } - - token_t t; - t.set_symbol(initial_itr,s_itr_,base_itr_); - token_list_.push_back(t); - } - - inline void scan_number() - { - /* - Attempt to match a valid numeric value in one of the following formats: - (01) 123456 - (02) 123456. - (03) 123.456 - (04) 123.456e3 - (05) 123.456E3 - (06) 123.456e+3 - (07) 123.456E+3 - (08) 123.456e-3 - (09) 123.456E-3 - (00) .1234 - (11) .1234e3 - (12) .1234E+3 - (13) .1234e+3 - (14) .1234E-3 - (15) .1234e-3 - */ - - details::char_cptr initial_itr = s_itr_; - bool dot_found = false; - bool e_found = false; - bool post_e_sign_found = false; - bool post_e_digit_found = false; - token_t t; - - while (!is_end(s_itr_)) - { - if ('.' == (*s_itr_)) - { - if (dot_found) - { - t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); - token_list_.push_back(t); - - return; - } - - dot_found = true; - ++s_itr_; - - continue; - } - else if ('e' == std::tolower(*s_itr_)) - { - const char_t& c = *(s_itr_ + 1); - - if (is_end(s_itr_ + 1)) - { - t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); - token_list_.push_back(t); - - return; - } - else if ( - ('+' != c) && - ('-' != c) && - !details::is_digit(c) - ) - { - t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); - token_list_.push_back(t); - - return; - } - - e_found = true; - ++s_itr_; - - continue; - } - else if (e_found && details::is_sign(*s_itr_) && !post_e_digit_found) - { - if (post_e_sign_found) - { - t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); - token_list_.push_back(t); - - return; - } - - post_e_sign_found = true; - ++s_itr_; - - continue; - } - else if (e_found && details::is_digit(*s_itr_)) - { - post_e_digit_found = true; - ++s_itr_; - - continue; - } - else if (('.' != (*s_itr_)) && !details::is_digit(*s_itr_)) - break; - else - ++s_itr_; - } - - t.set_numeric(initial_itr, s_itr_, base_itr_); - token_list_.push_back(t); - - return; - } - - inline void scan_special_function() - { - details::char_cptr initial_itr = s_itr_; - token_t t; - - // $fdd(x,x,x) = at least 11 chars - if (std::distance(s_itr_,s_end_) < 11) - { - t.set_error( - token::e_err_sfunc, - initial_itr, std::min(initial_itr + 11, s_end_), - base_itr_); - token_list_.push_back(t); - - return; - } - - if ( - !(('$' == *s_itr_) && - (details::imatch ('f',*(s_itr_ + 1))) && - (details::is_digit(*(s_itr_ + 2))) && - (details::is_digit(*(s_itr_ + 3)))) - ) - { - t.set_error( - token::e_err_sfunc, - initial_itr, std::min(initial_itr + 4, s_end_), - base_itr_); - token_list_.push_back(t); - - return; - } - - s_itr_ += 4; // $fdd = 4chars - - t.set_symbol(initial_itr, s_itr_, base_itr_); - token_list_.push_back(t); - - return; - } - - #ifndef exprtk_disable_string_capabilities - inline void scan_string() - { - details::char_cptr initial_itr = s_itr_ + 1; - token_t t; - - if (std::distance(s_itr_,s_end_) < 2) - { - t.set_error(token::e_err_string, s_itr_, s_end_, base_itr_); - token_list_.push_back(t); - - return; - } - - ++s_itr_; - - bool escaped_found = false; - bool escaped = false; - - while (!is_end(s_itr_)) - { - if (!details::is_valid_string_char(*s_itr_)) - { - t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); - token_list_.push_back(t); - - return; - } - else if (!escaped && ('\\' == *s_itr_)) - { - escaped_found = true; - escaped = true; - ++s_itr_; - - continue; - } - else if (!escaped) - { - if ('\'' == *s_itr_) - break; - } - else if (escaped) - { - if ( - !is_end(s_itr_) && ('0' == *(s_itr_)) && - ((s_itr_ + 4) <= s_end_) - ) - { - const bool x_seperator = ('X' == std::toupper(*(s_itr_ + 1))); - - const bool both_digits = details::is_hex_digit(*(s_itr_ + 2)) && - details::is_hex_digit(*(s_itr_ + 3)) ; - - if (!(x_seperator && both_digits)) - { - t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); - token_list_.push_back(t); - - return; - } - else - s_itr_ += 3; - } - - escaped = false; - } - - ++s_itr_; - } - - if (is_end(s_itr_)) - { - t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); - token_list_.push_back(t); - - return; - } - - if (!escaped_found) - t.set_string(initial_itr, s_itr_, base_itr_); - else - { - std::string parsed_string(initial_itr,s_itr_); - - if (!details::cleanup_escapes(parsed_string)) - { - t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); - token_list_.push_back(t); - - return; - } - - t.set_string( - parsed_string, - static_cast(std::distance(base_itr_,initial_itr))); - } - - token_list_.push_back(t); - ++s_itr_; - - return; - } - #endif - - private: - - token_list_t token_list_; - token_list_itr_t token_itr_; - token_list_itr_t store_token_itr_; - token_t eof_token_; - details::char_cptr base_itr_; - details::char_cptr s_itr_; - details::char_cptr s_end_; - - friend class token_scanner; - friend class token_modifier; - friend class token_inserter; - friend class token_joiner; - }; - - class helper_interface - { - public: - - virtual void init() { } - virtual void reset() { } - virtual bool result() { return true; } - virtual std::size_t process(generator&) { return 0; } - virtual ~helper_interface() { } - }; - - class token_scanner : public helper_interface - { - public: - - virtual ~token_scanner() - {} - - explicit token_scanner(const std::size_t& stride) - : stride_(stride) - { - if (stride > 4) - { - throw std::invalid_argument("token_scanner() - Invalid stride value"); - } - } - - inline std::size_t process(generator& g) exprtk_override - { - if (g.token_list_.size() >= stride_) - { - for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i) - { - token t; - - switch (stride_) - { - case 1 : - { - const token& t0 = g.token_list_[i]; - - if (!operator()(t0)) - { - return i; - } - } - break; - - case 2 : - { - const token& t0 = g.token_list_[i ]; - const token& t1 = g.token_list_[i + 1]; - - if (!operator()(t0, t1)) - { - return i; - } - } - break; - - case 3 : - { - const token& t0 = g.token_list_[i ]; - const token& t1 = g.token_list_[i + 1]; - const token& t2 = g.token_list_[i + 2]; - - if (!operator()(t0, t1, t2)) - { - return i; - } - } - break; - - case 4 : - { - const token& t0 = g.token_list_[i ]; - const token& t1 = g.token_list_[i + 1]; - const token& t2 = g.token_list_[i + 2]; - const token& t3 = g.token_list_[i + 3]; - - if (!operator()(t0, t1, t2, t3)) - { - return i; - } - } - break; - } - } - } - - return (g.token_list_.size() - stride_ + 1); - } - - virtual bool operator() (const token&) - { - return false; - } - - virtual bool operator() (const token&, const token&) - { - return false; - } - - virtual bool operator() (const token&, const token&, const token&) - { - return false; - } - - virtual bool operator() (const token&, const token&, const token&, const token&) - { - return false; - } - - private: - - const std::size_t stride_; - }; - - class token_modifier : public helper_interface - { - public: - - inline std::size_t process(generator& g) exprtk_override - { - std::size_t changes = 0; - - for (std::size_t i = 0; i < g.token_list_.size(); ++i) - { - if (modify(g.token_list_[i])) changes++; - } - - return changes; - } - - virtual bool modify(token& t) = 0; - }; - - class token_inserter : public helper_interface - { - public: - - explicit token_inserter(const std::size_t& stride) - : stride_(stride) - { - if (stride > 5) - { - throw std::invalid_argument("token_inserter() - Invalid stride value"); - } - } - - inline std::size_t process(generator& g) exprtk_override - { - if (g.token_list_.empty()) - return 0; - else if (g.token_list_.size() < stride_) - return 0; - - std::size_t changes = 0; - - typedef std::pair insert_t; - std::vector insert_list; - insert_list.reserve(10000); - - for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i) - { - int insert_index = -1; - token t; - - switch (stride_) - { - case 1 : insert_index = insert(g.token_list_[i],t); - break; - - case 2 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], t); - break; - - case 3 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], g.token_list_[i + 2], t); - break; - - case 4 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], g.token_list_[i + 2], g.token_list_[i + 3], t); - break; - - case 5 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], g.token_list_[i + 2], g.token_list_[i + 3], g.token_list_[i + 4], t); - break; - } - - if ((insert_index >= 0) && (insert_index <= (static_cast(stride_) + 1))) - { - insert_list.push_back(insert_t(i, t)); - changes++; - } - } - - if (!insert_list.empty()) - { - generator::token_list_t token_list; - - std::size_t insert_index = 0; - - for (std::size_t i = 0; i < g.token_list_.size(); ++i) - { - token_list.push_back(g.token_list_[i]); - - if ( - (insert_index < insert_list.size()) && - (insert_list[insert_index].first == i) - ) - { - token_list.push_back(insert_list[insert_index].second); - insert_index++; - } - } - - std::swap(g.token_list_,token_list); - } - - return changes; - } - - #define token_inserter_empty_body \ - { \ - return -1; \ - } \ - - inline virtual int insert(const token&, token&) - token_inserter_empty_body - - inline virtual int insert(const token&, const token&, token&) - token_inserter_empty_body - - inline virtual int insert(const token&, const token&, const token&, token&) - token_inserter_empty_body - - inline virtual int insert(const token&, const token&, const token&, const token&, token&) - token_inserter_empty_body - - inline virtual int insert(const token&, const token&, const token&, const token&, const token&, token&) - token_inserter_empty_body - - #undef token_inserter_empty_body - - private: - - const std::size_t stride_; - }; - - class token_joiner : public helper_interface - { - public: - - explicit token_joiner(const std::size_t& stride) - : stride_(stride) - {} - - inline std::size_t process(generator& g) exprtk_override - { - if (g.token_list_.empty()) - return 0; - - switch (stride_) - { - case 2 : return process_stride_2(g); - case 3 : return process_stride_3(g); - default : return 0; - } - } - - virtual bool join(const token&, const token&, token&) { return false; } - virtual bool join(const token&, const token&, const token&, token&) { return false; } - - private: - - inline std::size_t process_stride_2(generator& g) - { - if (g.token_list_.size() < 2) - return 0; - - std::size_t changes = 0; - - generator::token_list_t token_list; - token_list.reserve(10000); - - for (int i = 0; i < static_cast(g.token_list_.size() - 1); ++i) - { - token t; - - for ( ; ; ) - { - if (!join(g[i], g[i + 1], t)) - { - token_list.push_back(g[i]); - break; - } - - token_list.push_back(t); - - ++changes; - - i+=2; - - if (static_cast(i) >= g.token_list_.size() - 1) - break; - } - } - - token_list.push_back(g.token_list_.back()); - - assert(token_list.size() <= g.token_list_.size()); - - std::swap(token_list, g.token_list_); - - return changes; - } - - inline std::size_t process_stride_3(generator& g) - { - if (g.token_list_.size() < 3) - return 0; - - std::size_t changes = 0; - - generator::token_list_t token_list; - token_list.reserve(10000); - - for (int i = 0; i < static_cast(g.token_list_.size() - 2); ++i) - { - token t; - - for ( ; ; ) - { - if (!join(g[i], g[i + 1], g[i + 2], t)) - { - token_list.push_back(g[i]); - break; - } - - token_list.push_back(t); - - ++changes; - - i+=3; - - if (static_cast(i) >= g.token_list_.size() - 2) - break; - } - } - - token_list.push_back(*(g.token_list_.begin() + g.token_list_.size() - 2)); - token_list.push_back(*(g.token_list_.begin() + g.token_list_.size() - 1)); - - assert(token_list.size() <= g.token_list_.size()); - - std::swap(token_list, g.token_list_); - - return changes; - } - - const std::size_t stride_; - }; - - namespace helper - { - - inline void dump(const lexer::generator& generator) - { - for (std::size_t i = 0; i < generator.size(); ++i) - { - const lexer::token& t = generator[i]; - printf("Token[%02d] @ %03d %6s --> '%s'\n", - static_cast(i), - static_cast(t.position), - t.to_str(t.type).c_str(), - t.value.c_str()); - } - } - - class commutative_inserter : public lexer::token_inserter - { - public: - - using lexer::token_inserter::insert; - - commutative_inserter() - : lexer::token_inserter(2) - {} - - inline void ignore_symbol(const std::string& symbol) - { - ignore_set_.insert(symbol); - } - - inline int insert(const lexer::token& t0, const lexer::token& t1, lexer::token& new_token) - { - bool match = false; - new_token.type = lexer::token::e_mul; - new_token.value = "*"; - new_token.position = t1.position; - - if (t0.type == lexer::token::e_symbol) - { - if (ignore_set_.end() != ignore_set_.find(t0.value)) - { - return -1; - } - else if (!t0.value.empty() && ('$' == t0.value[0])) - { - return -1; - } - } - - if (t1.type == lexer::token::e_symbol) - { - if (ignore_set_.end() != ignore_set_.find(t1.value)) - { - return -1; - } - } - if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_symbol )) match = true; - else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lbracket )) match = true; - else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lcrlbracket)) match = true; - else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lsqrbracket)) match = true; - else if ((t0.type == lexer::token::e_symbol ) && (t1.type == lexer::token::e_number )) match = true; - else if ((t0.type == lexer::token::e_rbracket ) && (t1.type == lexer::token::e_number )) match = true; - else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_number )) match = true; - else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_number )) match = true; - else if ((t0.type == lexer::token::e_rbracket ) && (t1.type == lexer::token::e_symbol )) match = true; - else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_symbol )) match = true; - else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_symbol )) match = true; - else if ((t0.type == lexer::token::e_symbol ) && (t1.type == lexer::token::e_symbol )) match = true; - - return (match) ? 1 : -1; - } - - private: - - std::set ignore_set_; - }; - - class operator_joiner : public token_joiner - { - public: - - explicit operator_joiner(const std::size_t& stride) - : token_joiner(stride) - {} - - inline bool join(const lexer::token& t0, const lexer::token& t1, lexer::token& t) - { - // ': =' --> ':=' - if ((t0.type == lexer::token::e_colon) && (t1.type == lexer::token::e_eq)) - { - t.type = lexer::token::e_assign; - t.value = ":="; - t.position = t0.position; - - return true; - } - // '+ =' --> '+=' - else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_eq)) - { - t.type = lexer::token::e_addass; - t.value = "+="; - t.position = t0.position; - - return true; - } - // '- =' --> '-=' - else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_eq)) - { - t.type = lexer::token::e_subass; - t.value = "-="; - t.position = t0.position; - - return true; - } - // '* =' --> '*=' - else if ((t0.type == lexer::token::e_mul) && (t1.type == lexer::token::e_eq)) - { - t.type = lexer::token::e_mulass; - t.value = "*="; - t.position = t0.position; - - return true; - } - // '/ =' --> '/=' - else if ((t0.type == lexer::token::e_div) && (t1.type == lexer::token::e_eq)) - { - t.type = lexer::token::e_divass; - t.value = "/="; - t.position = t0.position; - - return true; - } - // '% =' --> '%=' - else if ((t0.type == lexer::token::e_mod) && (t1.type == lexer::token::e_eq)) - { - t.type = lexer::token::e_modass; - t.value = "%="; - t.position = t0.position; - - return true; - } - // '> =' --> '>=' - else if ((t0.type == lexer::token::e_gt) && (t1.type == lexer::token::e_eq)) - { - t.type = lexer::token::e_gte; - t.value = ">="; - t.position = t0.position; - - return true; - } - // '< =' --> '<=' - else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_eq)) - { - t.type = lexer::token::e_lte; - t.value = "<="; - t.position = t0.position; - - return true; - } - // '= =' --> '==' - else if ((t0.type == lexer::token::e_eq) && (t1.type == lexer::token::e_eq)) - { - t.type = lexer::token::e_eq; - t.value = "=="; - t.position = t0.position; - - return true; - } - // '! =' --> '!=' - else if ((static_cast(t0.type) == '!') && (t1.type == lexer::token::e_eq)) - { - t.type = lexer::token::e_ne; - t.value = "!="; - t.position = t0.position; - - return true; - } - // '< >' --> '<>' - else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_gt)) - { - t.type = lexer::token::e_ne; - t.value = "<>"; - t.position = t0.position; - - return true; - } - // '<= >' --> '<=>' - else if ((t0.type == lexer::token::e_lte) && (t1.type == lexer::token::e_gt)) - { - t.type = lexer::token::e_swap; - t.value = "<=>"; - t.position = t0.position; - - return true; - } - // '+ -' --> '-' - else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_sub)) - { - t.type = lexer::token::e_sub; - t.value = "-"; - t.position = t0.position; - - return true; - } - // '- +' --> '-' - else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_add)) - { - t.type = lexer::token::e_sub; - t.value = "-"; - t.position = t0.position; - - return true; - } - // '- -' --> '+' - else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_sub)) - { - /* - Note: May need to reconsider this when wanting to implement - pre/postfix decrement operator - */ - t.type = lexer::token::e_add; - t.value = "+"; - t.position = t0.position; - - return true; - } - else - return false; - } - - inline bool join(const lexer::token& t0, const lexer::token& t1, const lexer::token& t2, lexer::token& t) - { - // '[ * ]' --> '[*]' - if ( - (t0.type == lexer::token::e_lsqrbracket) && - (t1.type == lexer::token::e_mul ) && - (t2.type == lexer::token::e_rsqrbracket) - ) - { - t.type = lexer::token::e_symbol; - t.value = "[*]"; - t.position = t0.position; - - return true; - } - else - return false; - } - }; - - class bracket_checker : public lexer::token_scanner - { - public: - - using lexer::token_scanner::operator(); - - bracket_checker() - : token_scanner(1), - state_(true) - {} - - bool result() - { - if (!stack_.empty()) - { - lexer::token t; - t.value = stack_.top().first; - t.position = stack_.top().second; - error_token_ = t; - state_ = false; - - return false; - } - else - return state_; - } - - lexer::token error_token() - { - return error_token_; - } - - void reset() - { - // Why? because msvc doesn't support swap properly. - stack_ = std::stack >(); - state_ = true; - error_token_.clear(); - } - - bool operator() (const lexer::token& t) - { - if ( - !t.value.empty() && - (lexer::token::e_string != t.type) && - (lexer::token::e_symbol != t.type) && - exprtk::details::is_bracket(t.value[0]) - ) - { - details::char_t c = t.value[0]; - - if (t.type == lexer::token::e_lbracket ) stack_.push(std::make_pair(')',t.position)); - else if (t.type == lexer::token::e_lcrlbracket) stack_.push(std::make_pair('}',t.position)); - else if (t.type == lexer::token::e_lsqrbracket) stack_.push(std::make_pair(']',t.position)); - else if (exprtk::details::is_right_bracket(c)) - { - if (stack_.empty()) - { - state_ = false; - error_token_ = t; - - return false; - } - else if (c != stack_.top().first) - { - state_ = false; - error_token_ = t; - - return false; - } - else - stack_.pop(); - } - } - - return true; - } - - private: - - bool state_; - std::stack > stack_; - lexer::token error_token_; - }; - - class numeric_checker : public lexer::token_scanner - { - public: - - using lexer::token_scanner::operator(); - - numeric_checker() - : token_scanner (1), - current_index_(0) - {} - - bool result() - { - return error_list_.empty(); - } - - void reset() - { - error_list_.clear(); - current_index_ = 0; - } - - bool operator() (const lexer::token& t) - { - if (token::e_number == t.type) - { - double v; - - if (!exprtk::details::string_to_real(t.value,v)) - { - error_list_.push_back(current_index_); - } - } - - ++current_index_; - - return true; - } - - std::size_t error_count() const - { - return error_list_.size(); - } - - std::size_t error_index(const std::size_t& i) - { - if (i < error_list_.size()) - return error_list_[i]; - else - return std::numeric_limits::max(); - } - - void clear_errors() - { - error_list_.clear(); - } - - private: - - std::size_t current_index_; - std::vector error_list_; - }; - - class symbol_replacer : public lexer::token_modifier - { - private: - - typedef std::map,details::ilesscompare> replace_map_t; - - public: - - bool remove(const std::string& target_symbol) - { - const replace_map_t::iterator itr = replace_map_.find(target_symbol); - - if (replace_map_.end() == itr) - return false; - - replace_map_.erase(itr); - - return true; - } - - bool add_replace(const std::string& target_symbol, - const std::string& replace_symbol, - const lexer::token::token_type token_type = lexer::token::e_symbol) - { - const replace_map_t::iterator itr = replace_map_.find(target_symbol); - - if (replace_map_.end() != itr) - { - return false; - } - - replace_map_[target_symbol] = std::make_pair(replace_symbol,token_type); - - return true; - } - - void clear() - { - replace_map_.clear(); - } - - private: - - bool modify(lexer::token& t) - { - if (lexer::token::e_symbol == t.type) - { - if (replace_map_.empty()) - return false; - - const replace_map_t::iterator itr = replace_map_.find(t.value); - - if (replace_map_.end() != itr) - { - t.value = itr->second.first; - t.type = itr->second.second; - - return true; - } - } - - return false; - } - - replace_map_t replace_map_; - }; - - class sequence_validator : public lexer::token_scanner - { - private: - - typedef std::pair token_pair_t; - typedef std::set set_t; - - public: - - using lexer::token_scanner::operator(); - - sequence_validator() - : lexer::token_scanner(2) - { - add_invalid(lexer::token::e_number, lexer::token::e_number); - add_invalid(lexer::token::e_string, lexer::token::e_string); - add_invalid(lexer::token::e_number, lexer::token::e_string); - add_invalid(lexer::token::e_string, lexer::token::e_number); - - add_invalid_set1(lexer::token::e_assign ); - add_invalid_set1(lexer::token::e_shr ); - add_invalid_set1(lexer::token::e_shl ); - add_invalid_set1(lexer::token::e_lte ); - add_invalid_set1(lexer::token::e_ne ); - add_invalid_set1(lexer::token::e_gte ); - add_invalid_set1(lexer::token::e_lt ); - add_invalid_set1(lexer::token::e_gt ); - add_invalid_set1(lexer::token::e_eq ); - add_invalid_set1(lexer::token::e_comma ); - add_invalid_set1(lexer::token::e_add ); - add_invalid_set1(lexer::token::e_sub ); - add_invalid_set1(lexer::token::e_div ); - add_invalid_set1(lexer::token::e_mul ); - add_invalid_set1(lexer::token::e_mod ); - add_invalid_set1(lexer::token::e_pow ); - add_invalid_set1(lexer::token::e_colon ); - add_invalid_set1(lexer::token::e_ternary); - } - - bool result() - { - return error_list_.empty(); - } - - bool operator() (const lexer::token& t0, const lexer::token& t1) - { - const set_t::value_type p = std::make_pair(t0.type,t1.type); - - if (invalid_bracket_check(t0.type,t1.type)) - { - error_list_.push_back(std::make_pair(t0,t1)); - } - else if (invalid_comb_.find(p) != invalid_comb_.end()) - { - error_list_.push_back(std::make_pair(t0,t1)); - } - - return true; - } - - std::size_t error_count() const - { - return error_list_.size(); - } - - std::pair error(const std::size_t index) - { - if (index < error_list_.size()) - { - return error_list_[index]; - } - else - { - static const lexer::token error_token; - return std::make_pair(error_token,error_token); - } - } - - void clear_errors() - { - error_list_.clear(); - } - - private: - - void add_invalid(lexer::token::token_type base, lexer::token::token_type t) - { - invalid_comb_.insert(std::make_pair(base,t)); - } - - void add_invalid_set1(lexer::token::token_type t) - { - add_invalid(t, lexer::token::e_assign); - add_invalid(t, lexer::token::e_shr ); - add_invalid(t, lexer::token::e_shl ); - add_invalid(t, lexer::token::e_lte ); - add_invalid(t, lexer::token::e_ne ); - add_invalid(t, lexer::token::e_gte ); - add_invalid(t, lexer::token::e_lt ); - add_invalid(t, lexer::token::e_gt ); - add_invalid(t, lexer::token::e_eq ); - add_invalid(t, lexer::token::e_comma ); - add_invalid(t, lexer::token::e_div ); - add_invalid(t, lexer::token::e_mul ); - add_invalid(t, lexer::token::e_mod ); - add_invalid(t, lexer::token::e_pow ); - add_invalid(t, lexer::token::e_colon ); - } - - bool invalid_bracket_check(lexer::token::token_type base, lexer::token::token_type t) - { - if (details::is_right_bracket(static_cast(base))) - { - switch (t) - { - case lexer::token::e_assign : return (']' != base); - case lexer::token::e_string : return (')' != base); - default : return false; - } - } - else if (details::is_left_bracket(static_cast(base))) - { - if (details::is_right_bracket(static_cast(t))) - return false; - else if (details::is_left_bracket(static_cast(t))) - return false; - else - { - switch (t) - { - case lexer::token::e_number : return false; - case lexer::token::e_symbol : return false; - case lexer::token::e_string : return false; - case lexer::token::e_add : return false; - case lexer::token::e_sub : return false; - case lexer::token::e_colon : return false; - case lexer::token::e_ternary : return false; - default : return true ; - } - } - } - else if (details::is_right_bracket(static_cast(t))) - { - switch (base) - { - case lexer::token::e_number : return false; - case lexer::token::e_symbol : return false; - case lexer::token::e_string : return false; - case lexer::token::e_eof : return false; - case lexer::token::e_colon : return false; - case lexer::token::e_ternary : return false; - default : return true ; - } - } - else if (details::is_left_bracket(static_cast(t))) - { - switch (base) - { - case lexer::token::e_rbracket : return true; - case lexer::token::e_rsqrbracket : return true; - case lexer::token::e_rcrlbracket : return true; - default : return false; - } - } - - return false; - } - - set_t invalid_comb_; - std::vector > error_list_; - }; - - class sequence_validator_3tokens : public lexer::token_scanner - { - private: - - typedef lexer::token::token_type token_t; - typedef std::pair > token_triplet_t; - typedef std::set set_t; - - public: - - using lexer::token_scanner::operator(); - - sequence_validator_3tokens() - : lexer::token_scanner(3) - { - add_invalid(lexer::token::e_number , lexer::token::e_number , lexer::token::e_number); - add_invalid(lexer::token::e_string , lexer::token::e_string , lexer::token::e_string); - add_invalid(lexer::token::e_comma , lexer::token::e_comma , lexer::token::e_comma ); - - add_invalid(lexer::token::e_add , lexer::token::e_add , lexer::token::e_add ); - add_invalid(lexer::token::e_sub , lexer::token::e_sub , lexer::token::e_sub ); - add_invalid(lexer::token::e_div , lexer::token::e_div , lexer::token::e_div ); - add_invalid(lexer::token::e_mul , lexer::token::e_mul , lexer::token::e_mul ); - add_invalid(lexer::token::e_mod , lexer::token::e_mod , lexer::token::e_mod ); - add_invalid(lexer::token::e_pow , lexer::token::e_pow , lexer::token::e_pow ); - - add_invalid(lexer::token::e_add , lexer::token::e_sub , lexer::token::e_add ); - add_invalid(lexer::token::e_sub , lexer::token::e_add , lexer::token::e_sub ); - add_invalid(lexer::token::e_div , lexer::token::e_mul , lexer::token::e_div ); - add_invalid(lexer::token::e_mul , lexer::token::e_div , lexer::token::e_mul ); - add_invalid(lexer::token::e_mod , lexer::token::e_pow , lexer::token::e_mod ); - add_invalid(lexer::token::e_pow , lexer::token::e_mod , lexer::token::e_pow ); - } - - bool result() - { - return error_list_.empty(); - } - - bool operator() (const lexer::token& t0, const lexer::token& t1, const lexer::token& t2) - { - const set_t::value_type p = std::make_pair(t0.type,std::make_pair(t1.type,t2.type)); - - if (invalid_comb_.find(p) != invalid_comb_.end()) - { - error_list_.push_back(std::make_pair(t0,t1)); - } - - return true; - } - - std::size_t error_count() const - { - return error_list_.size(); - } - - std::pair error(const std::size_t index) - { - if (index < error_list_.size()) - { - return error_list_[index]; - } - else - { - static const lexer::token error_token; - return std::make_pair(error_token,error_token); - } - } - - void clear_errors() - { - error_list_.clear(); - } - - private: - - void add_invalid(token_t t0, token_t t1, token_t t2) - { - invalid_comb_.insert(std::make_pair(t0,std::make_pair(t1,t2))); - } - - set_t invalid_comb_; - std::vector > error_list_; - }; - - struct helper_assembly - { - inline bool register_scanner(lexer::token_scanner* scanner) - { - if (token_scanner_list.end() != std::find(token_scanner_list.begin(), - token_scanner_list.end (), - scanner)) - { - return false; - } - - token_scanner_list.push_back(scanner); - - return true; - } - - inline bool register_modifier(lexer::token_modifier* modifier) - { - if (token_modifier_list.end() != std::find(token_modifier_list.begin(), - token_modifier_list.end (), - modifier)) - { - return false; - } - - token_modifier_list.push_back(modifier); - - return true; - } - - inline bool register_joiner(lexer::token_joiner* joiner) - { - if (token_joiner_list.end() != std::find(token_joiner_list.begin(), - token_joiner_list.end (), - joiner)) - { - return false; - } - - token_joiner_list.push_back(joiner); - - return true; - } - - inline bool register_inserter(lexer::token_inserter* inserter) - { - if (token_inserter_list.end() != std::find(token_inserter_list.begin(), - token_inserter_list.end (), - inserter)) - { - return false; - } - - token_inserter_list.push_back(inserter); - - return true; - } - - inline bool run_modifiers(lexer::generator& g) - { - error_token_modifier = reinterpret_cast(0); - - for (std::size_t i = 0; i < token_modifier_list.size(); ++i) - { - lexer::token_modifier& modifier = (*token_modifier_list[i]); - - modifier.reset(); - modifier.process(g); - - if (!modifier.result()) - { - error_token_modifier = token_modifier_list[i]; - - return false; - } - } - - return true; - } - - inline bool run_joiners(lexer::generator& g) - { - error_token_joiner = reinterpret_cast(0); - - for (std::size_t i = 0; i < token_joiner_list.size(); ++i) - { - lexer::token_joiner& joiner = (*token_joiner_list[i]); - - joiner.reset(); - joiner.process(g); - - if (!joiner.result()) - { - error_token_joiner = token_joiner_list[i]; - - return false; - } - } - - return true; - } - - inline bool run_inserters(lexer::generator& g) - { - error_token_inserter = reinterpret_cast(0); - - for (std::size_t i = 0; i < token_inserter_list.size(); ++i) - { - lexer::token_inserter& inserter = (*token_inserter_list[i]); - - inserter.reset(); - inserter.process(g); - - if (!inserter.result()) - { - error_token_inserter = token_inserter_list[i]; - - return false; - } - } - - return true; - } - - inline bool run_scanners(lexer::generator& g) - { - error_token_scanner = reinterpret_cast(0); - - for (std::size_t i = 0; i < token_scanner_list.size(); ++i) - { - lexer::token_scanner& scanner = (*token_scanner_list[i]); - - scanner.reset(); - scanner.process(g); - - if (!scanner.result()) - { - error_token_scanner = token_scanner_list[i]; - - return false; - } - } - - return true; - } - - std::vector token_scanner_list; - std::vector token_modifier_list; - std::vector token_joiner_list; - std::vector token_inserter_list; - - lexer::token_scanner* error_token_scanner; - lexer::token_modifier* error_token_modifier; - lexer::token_joiner* error_token_joiner; - lexer::token_inserter* error_token_inserter; - }; - } - - class parser_helper - { - public: - - typedef token token_t; - typedef generator generator_t; - - inline bool init(const std::string& str) - { - if (!lexer_.process(str)) - { - return false; - } - - lexer_.begin(); - - next_token(); - - return true; - } - - inline generator_t& lexer() - { - return lexer_; - } - - inline const generator_t& lexer() const - { - return lexer_; - } - - inline void store_token() - { - lexer_.store(); - store_current_token_ = current_token_; - } - - inline void restore_token() - { - lexer_.restore(); - current_token_ = store_current_token_; - } - - inline void next_token() - { - current_token_ = lexer_.next_token(); - } - - inline const token_t& current_token() const - { - return current_token_; - } - - enum token_advance_mode - { - e_hold = 0, - e_advance = 1 - }; - - inline void advance_token(const token_advance_mode mode) - { - if (e_advance == mode) - { - next_token(); - } - } - - inline bool token_is(const token_t::token_type& ttype, const token_advance_mode mode = e_advance) - { - if (current_token().type != ttype) - { - return false; - } - - advance_token(mode); - - return true; - } - - inline bool token_is(const token_t::token_type& ttype, - const std::string& value, - const token_advance_mode mode = e_advance) - { - if ( - (current_token().type != ttype) || - !exprtk::details::imatch(value,current_token().value) - ) - { - return false; - } - - advance_token(mode); - - return true; - } - - inline bool peek_token_is(const token_t::token_type& ttype) - { - return (lexer_.peek_next_token().type == ttype); - } - - inline bool peek_token_is(const std::string& s) - { - return (exprtk::details::imatch(lexer_.peek_next_token().value,s)); - } - - private: - - generator_t lexer_; - token_t current_token_; - token_t store_current_token_; - }; - } - - template - class vector_view - { - public: - - typedef T* data_ptr_t; - - vector_view(data_ptr_t data, const std::size_t& size) - : size_(size), - data_(data), - data_ref_(0) - {} - - vector_view(const vector_view& vv) - : size_(vv.size_), - data_(vv.data_), - data_ref_(0) - {} - - inline void rebase(data_ptr_t data) - { - data_ = data; - - if (!data_ref_.empty()) - { - for (std::size_t i = 0; i < data_ref_.size(); ++i) - { - (*data_ref_[i]) = data; - } - } - } - - inline data_ptr_t data() const - { - return data_; - } - - inline std::size_t size() const - { - return size_; - } - - inline const T& operator[](const std::size_t index) const - { - return data_[index]; - } - - inline T& operator[](const std::size_t index) - { - return data_[index]; - } - - void set_ref(data_ptr_t* data_ref) - { - data_ref_.push_back(data_ref); - } - - private: - - const std::size_t size_; - data_ptr_t data_; - std::vector data_ref_; - }; - - template - inline vector_view make_vector_view(T* data, - const std::size_t size, const std::size_t offset = 0) - { - return vector_view(data + offset, size); - } - - template - inline vector_view make_vector_view(std::vector& v, - const std::size_t size, const std::size_t offset = 0) - { - return vector_view(v.data() + offset, size); - } - - template class results_context; - - template - struct type_store - { - enum store_type - { - e_unknown, - e_scalar , - e_vector , - e_string - }; - - type_store() - : data(0), - size(0), - type(e_unknown) - {} - - union - { - void* data; - T* vec_data; - }; - - std::size_t size; - store_type type; - - class parameter_list - { - public: - - explicit parameter_list(std::vector& pl) - : parameter_list_(pl) - {} - - inline bool empty() const - { - return parameter_list_.empty(); - } - - inline std::size_t size() const - { - return parameter_list_.size(); - } - - inline type_store& operator[](const std::size_t& index) - { - return parameter_list_[index]; - } - - inline const type_store& operator[](const std::size_t& index) const - { - return parameter_list_[index]; - } - - inline type_store& front() - { - return parameter_list_[0]; - } - - inline const type_store& front() const - { - return parameter_list_[0]; - } - - inline type_store& back() - { - return parameter_list_.back(); - } - - inline const type_store& back() const - { - return parameter_list_.back(); - } - - private: - - std::vector& parameter_list_; - - friend class results_context; - }; - - template - struct type_view - { - typedef type_store type_store_t; - typedef ViewType value_t; - - explicit type_view(type_store_t& ts) - : ts_(ts), - data_(reinterpret_cast(ts_.data)) - {} - - explicit type_view(const type_store_t& ts) - : ts_(const_cast(ts)), - data_(reinterpret_cast(ts_.data)) - {} - - inline std::size_t size() const - { - return ts_.size; - } - - inline value_t& operator[](const std::size_t& i) - { - return data_[i]; - } - - inline const value_t& operator[](const std::size_t& i) const - { - return data_[i]; - } - - inline const value_t* begin() const { return data_; } - inline value_t* begin() { return data_; } - - inline const value_t* end() const - { - return static_cast(data_ + ts_.size); - } - - inline value_t* end() - { - return static_cast(data_ + ts_.size); - } - - type_store_t& ts_; - value_t* data_; - }; - - typedef type_view vector_view; - typedef type_view string_view; - - struct scalar_view - { - typedef type_store type_store_t; - typedef T value_t; - - explicit scalar_view(type_store_t& ts) - : v_(*reinterpret_cast(ts.data)) - {} - - explicit scalar_view(const type_store_t& ts) - : v_(*reinterpret_cast(const_cast(ts).data)) - {} - - inline value_t& operator() () - { - return v_; - } - - inline const value_t& operator() () const - { - return v_; - } - - template - inline bool to_int(IntType& i) const - { - if (!exprtk::details::numeric::is_integer(v_)) - return false; - - i = static_cast(v_); - - return true; - } - - template - inline bool to_uint(UIntType& u) const - { - if (v_ < T(0)) - return false; - else if (!exprtk::details::numeric::is_integer(v_)) - return false; - - u = static_cast(v_); - - return true; - } - - T& v_; - }; - }; - - template - inline std::string to_str(const StringView& view) - { - return std::string(view.begin(),view.size()); - } - - #ifndef exprtk_disable_return_statement - namespace details - { - template class return_node; - template class return_envelope_node; - } - #endif - - template - class results_context - { - public: - - typedef type_store type_store_t; - - results_context() - : results_available_(false) - {} - - inline std::size_t count() const - { - if (results_available_) - return parameter_list_.size(); - else - return 0; - } - - inline type_store_t& operator[](const std::size_t& index) - { - return parameter_list_[index]; - } - - inline const type_store_t& operator[](const std::size_t& index) const - { - return parameter_list_[index]; - } - - private: - - inline void clear() - { - results_available_ = false; - } - - typedef std::vector ts_list_t; - typedef typename type_store_t::parameter_list parameter_list_t; - - inline void assign(const parameter_list_t& pl) - { - parameter_list_ = pl.parameter_list_; - results_available_ = true; - } - - bool results_available_; - ts_list_t parameter_list_; - - #ifndef exprtk_disable_return_statement - friend class details::return_node; - friend class details::return_envelope_node; - #endif - }; - - namespace details - { - enum operator_type - { - e_default , e_null , e_add , e_sub , - e_mul , e_div , e_mod , e_pow , - e_atan2 , e_min , e_max , e_avg , - e_sum , e_prod , e_lt , e_lte , - e_eq , e_equal , e_ne , e_nequal , - e_gte , e_gt , e_and , e_nand , - e_or , e_nor , e_xor , e_xnor , - e_mand , e_mor , e_scand , e_scor , - e_shr , e_shl , e_abs , e_acos , - e_acosh , e_asin , e_asinh , e_atan , - e_atanh , e_ceil , e_cos , e_cosh , - e_exp , e_expm1 , e_floor , e_log , - e_log10 , e_log2 , e_log1p , e_logn , - e_neg , e_pos , e_round , e_roundn , - e_root , e_sqrt , e_sin , e_sinc , - e_sinh , e_sec , e_csc , e_tan , - e_tanh , e_cot , e_clamp , e_iclamp , - e_inrange , e_sgn , e_r2d , e_d2r , - e_d2g , e_g2d , e_hypot , e_notl , - e_erf , e_erfc , e_ncdf , e_frac , - e_trunc , e_assign , e_addass , e_subass , - e_mulass , e_divass , e_modass , e_in , - e_like , e_ilike , e_multi , e_smulti , - e_swap , - - // Do not add new functions/operators after this point. - e_sf00 = 1000, e_sf01 = 1001, e_sf02 = 1002, e_sf03 = 1003, - e_sf04 = 1004, e_sf05 = 1005, e_sf06 = 1006, e_sf07 = 1007, - e_sf08 = 1008, e_sf09 = 1009, e_sf10 = 1010, e_sf11 = 1011, - e_sf12 = 1012, e_sf13 = 1013, e_sf14 = 1014, e_sf15 = 1015, - e_sf16 = 1016, e_sf17 = 1017, e_sf18 = 1018, e_sf19 = 1019, - e_sf20 = 1020, e_sf21 = 1021, e_sf22 = 1022, e_sf23 = 1023, - e_sf24 = 1024, e_sf25 = 1025, e_sf26 = 1026, e_sf27 = 1027, - e_sf28 = 1028, e_sf29 = 1029, e_sf30 = 1030, e_sf31 = 1031, - e_sf32 = 1032, e_sf33 = 1033, e_sf34 = 1034, e_sf35 = 1035, - e_sf36 = 1036, e_sf37 = 1037, e_sf38 = 1038, e_sf39 = 1039, - e_sf40 = 1040, e_sf41 = 1041, e_sf42 = 1042, e_sf43 = 1043, - e_sf44 = 1044, e_sf45 = 1045, e_sf46 = 1046, e_sf47 = 1047, - e_sf48 = 1048, e_sf49 = 1049, e_sf50 = 1050, e_sf51 = 1051, - e_sf52 = 1052, e_sf53 = 1053, e_sf54 = 1054, e_sf55 = 1055, - e_sf56 = 1056, e_sf57 = 1057, e_sf58 = 1058, e_sf59 = 1059, - e_sf60 = 1060, e_sf61 = 1061, e_sf62 = 1062, e_sf63 = 1063, - e_sf64 = 1064, e_sf65 = 1065, e_sf66 = 1066, e_sf67 = 1067, - e_sf68 = 1068, e_sf69 = 1069, e_sf70 = 1070, e_sf71 = 1071, - e_sf72 = 1072, e_sf73 = 1073, e_sf74 = 1074, e_sf75 = 1075, - e_sf76 = 1076, e_sf77 = 1077, e_sf78 = 1078, e_sf79 = 1079, - e_sf80 = 1080, e_sf81 = 1081, e_sf82 = 1082, e_sf83 = 1083, - e_sf84 = 1084, e_sf85 = 1085, e_sf86 = 1086, e_sf87 = 1087, - e_sf88 = 1088, e_sf89 = 1089, e_sf90 = 1090, e_sf91 = 1091, - e_sf92 = 1092, e_sf93 = 1093, e_sf94 = 1094, e_sf95 = 1095, - e_sf96 = 1096, e_sf97 = 1097, e_sf98 = 1098, e_sf99 = 1099, - e_sffinal = 1100, - e_sf4ext00 = 2000, e_sf4ext01 = 2001, e_sf4ext02 = 2002, e_sf4ext03 = 2003, - e_sf4ext04 = 2004, e_sf4ext05 = 2005, e_sf4ext06 = 2006, e_sf4ext07 = 2007, - e_sf4ext08 = 2008, e_sf4ext09 = 2009, e_sf4ext10 = 2010, e_sf4ext11 = 2011, - e_sf4ext12 = 2012, e_sf4ext13 = 2013, e_sf4ext14 = 2014, e_sf4ext15 = 2015, - e_sf4ext16 = 2016, e_sf4ext17 = 2017, e_sf4ext18 = 2018, e_sf4ext19 = 2019, - e_sf4ext20 = 2020, e_sf4ext21 = 2021, e_sf4ext22 = 2022, e_sf4ext23 = 2023, - e_sf4ext24 = 2024, e_sf4ext25 = 2025, e_sf4ext26 = 2026, e_sf4ext27 = 2027, - e_sf4ext28 = 2028, e_sf4ext29 = 2029, e_sf4ext30 = 2030, e_sf4ext31 = 2031, - e_sf4ext32 = 2032, e_sf4ext33 = 2033, e_sf4ext34 = 2034, e_sf4ext35 = 2035, - e_sf4ext36 = 2036, e_sf4ext37 = 2037, e_sf4ext38 = 2038, e_sf4ext39 = 2039, - e_sf4ext40 = 2040, e_sf4ext41 = 2041, e_sf4ext42 = 2042, e_sf4ext43 = 2043, - e_sf4ext44 = 2044, e_sf4ext45 = 2045, e_sf4ext46 = 2046, e_sf4ext47 = 2047, - e_sf4ext48 = 2048, e_sf4ext49 = 2049, e_sf4ext50 = 2050, e_sf4ext51 = 2051, - e_sf4ext52 = 2052, e_sf4ext53 = 2053, e_sf4ext54 = 2054, e_sf4ext55 = 2055, - e_sf4ext56 = 2056, e_sf4ext57 = 2057, e_sf4ext58 = 2058, e_sf4ext59 = 2059, - e_sf4ext60 = 2060, e_sf4ext61 = 2061 - }; - - inline std::string to_str(const operator_type opr) - { - switch (opr) - { - case e_add : return "+" ; - case e_sub : return "-" ; - case e_mul : return "*" ; - case e_div : return "/" ; - case e_mod : return "%" ; - case e_pow : return "^" ; - case e_assign : return ":=" ; - case e_addass : return "+=" ; - case e_subass : return "-=" ; - case e_mulass : return "*=" ; - case e_divass : return "/=" ; - case e_modass : return "%=" ; - case e_lt : return "<" ; - case e_lte : return "<=" ; - case e_eq : return "==" ; - case e_equal : return "=" ; - case e_ne : return "!=" ; - case e_nequal : return "<>" ; - case e_gte : return ">=" ; - case e_gt : return ">" ; - case e_and : return "and" ; - case e_or : return "or" ; - case e_xor : return "xor" ; - case e_nand : return "nand"; - case e_nor : return "nor" ; - case e_xnor : return "xnor"; - default : return "N/A" ; - } - } - - struct base_operation_t - { - base_operation_t(const operator_type t, const unsigned int& np) - : type(t), - num_params(np) - {} - - operator_type type; - unsigned int num_params; - }; - - namespace loop_unroll - { - #ifndef exprtk_disable_superscalar_unroll - const unsigned int global_loop_batch_size = 16; - #else - const unsigned int global_loop_batch_size = 4; - #endif - - struct details - { - explicit details(const std::size_t& vsize, - const unsigned int loop_batch_size = global_loop_batch_size) - : batch_size(loop_batch_size ), - remainder (vsize % batch_size), - upper_bound(static_cast(vsize - (remainder ? loop_batch_size : 0))) - {} - - unsigned int batch_size; - int remainder; - int upper_bound; - }; - } - - #ifdef exprtk_enable_debugging - inline void dump_ptr(const std::string& s, const void* ptr, const std::size_t size = 0) - { - if (size) - exprtk_debug(("%s - addr: %p\n",s.c_str(),ptr)); - else - exprtk_debug(("%s - addr: %p size: %d\n", - s.c_str(), - ptr, - static_cast(size))); - } - #else - inline void dump_ptr(const std::string&, const void*) {} - inline void dump_ptr(const std::string&, const void*, const std::size_t) {} - #endif - - template - class vec_data_store - { - public: - - typedef vec_data_store type; - typedef T* data_t; - - private: - - struct control_block - { - control_block() - : ref_count(1), - size (0), - data (0), - destruct (true) - {} - - explicit control_block(const std::size_t& dsize) - : ref_count(1 ), - size (dsize), - data (0 ), - destruct (true ) - { create_data(); } - - control_block(const std::size_t& dsize, data_t dptr, bool dstrct = false) - : ref_count(1 ), - size (dsize ), - data (dptr ), - destruct (dstrct) - {} - - ~control_block() - { - if (data && destruct && (0 == ref_count)) - { - dump_ptr("~control_block() data",data); - delete[] data; - data = reinterpret_cast(0); - } - } - - static inline control_block* create(const std::size_t& dsize, data_t data_ptr = data_t(0), bool dstrct = false) - { - if (dsize) - { - if (0 == data_ptr) - return (new control_block(dsize)); - else - return (new control_block(dsize, data_ptr, dstrct)); - } - else - return (new control_block); - } - - static inline void destroy(control_block*& cntrl_blck) - { - if (cntrl_blck) - { - if ( - (0 != cntrl_blck->ref_count) && - (0 == --cntrl_blck->ref_count) - ) - { - delete cntrl_blck; - } - - cntrl_blck = 0; - } - } - - std::size_t ref_count; - std::size_t size; - data_t data; - bool destruct; - - private: - - control_block(const control_block&); - control_block& operator=(const control_block&); - - inline void create_data() - { - destruct = true; - data = new T[size]; - std::fill_n(data, size, T(0)); - dump_ptr("control_block::create_data() - data",data,size); - } - }; - - public: - - vec_data_store() - : control_block_(control_block::create(0)) - {} - - explicit vec_data_store(const std::size_t& size) - : control_block_(control_block::create(size,reinterpret_cast(0),true)) - {} - - vec_data_store(const std::size_t& size, data_t data, bool dstrct = false) - : control_block_(control_block::create(size, data, dstrct)) - {} - - vec_data_store(const type& vds) - { - control_block_ = vds.control_block_; - control_block_->ref_count++; - } - - ~vec_data_store() - { - control_block::destroy(control_block_); - } - - type& operator=(const type& vds) - { - if (this != &vds) - { - std::size_t final_size = min_size(control_block_, vds.control_block_); - - vds.control_block_->size = final_size; - control_block_->size = final_size; - - if (control_block_->destruct || (0 == control_block_->data)) - { - control_block::destroy(control_block_); - - control_block_ = vds.control_block_; - control_block_->ref_count++; - } - } - - return (*this); - } - - inline data_t data() - { - return control_block_->data; - } - - inline data_t data() const - { - return control_block_->data; - } - - inline std::size_t size() - { - return control_block_->size; - } - - inline std::size_t size() const - { - return control_block_->size; - } - - inline data_t& ref() - { - return control_block_->data; - } - - inline void dump() const - { - #ifdef exprtk_enable_debugging - exprtk_debug(("size: %d\taddress:%p\tdestruct:%c\n", - size(), - data(), - (control_block_->destruct ? 'T' : 'F'))); - - for (std::size_t i = 0; i < size(); ++i) - { - if (5 == i) - exprtk_debug(("\n")); - - exprtk_debug(("%15.10f ",data()[i])); - } - exprtk_debug(("\n")); - #endif - } - - static inline void match_sizes(type& vds0, type& vds1) - { - const std::size_t size = min_size(vds0.control_block_,vds1.control_block_); - vds0.control_block_->size = size; - vds1.control_block_->size = size; - } - - private: - - static inline std::size_t min_size(control_block* cb0, control_block* cb1) - { - const std::size_t size0 = cb0->size; - const std::size_t size1 = cb1->size; - - if (size0 && size1) - return std::min(size0,size1); - else - return (size0) ? size0 : size1; - } - - control_block* control_block_; - }; - - namespace numeric - { - namespace details - { - template - inline T process_impl(const operator_type operation, const T arg) - { - switch (operation) - { - case e_abs : return numeric::abs (arg); - case e_acos : return numeric::acos (arg); - case e_acosh : return numeric::acosh(arg); - case e_asin : return numeric::asin (arg); - case e_asinh : return numeric::asinh(arg); - case e_atan : return numeric::atan (arg); - case e_atanh : return numeric::atanh(arg); - case e_ceil : return numeric::ceil (arg); - case e_cos : return numeric::cos (arg); - case e_cosh : return numeric::cosh (arg); - case e_exp : return numeric::exp (arg); - case e_expm1 : return numeric::expm1(arg); - case e_floor : return numeric::floor(arg); - case e_log : return numeric::log (arg); - case e_log10 : return numeric::log10(arg); - case e_log2 : return numeric::log2 (arg); - case e_log1p : return numeric::log1p(arg); - case e_neg : return numeric::neg (arg); - case e_pos : return numeric::pos (arg); - case e_round : return numeric::round(arg); - case e_sin : return numeric::sin (arg); - case e_sinc : return numeric::sinc (arg); - case e_sinh : return numeric::sinh (arg); - case e_sqrt : return numeric::sqrt (arg); - case e_tan : return numeric::tan (arg); - case e_tanh : return numeric::tanh (arg); - case e_cot : return numeric::cot (arg); - case e_sec : return numeric::sec (arg); - case e_csc : return numeric::csc (arg); - case e_r2d : return numeric::r2d (arg); - case e_d2r : return numeric::d2r (arg); - case e_d2g : return numeric::d2g (arg); - case e_g2d : return numeric::g2d (arg); - case e_notl : return numeric::notl (arg); - case e_sgn : return numeric::sgn (arg); - case e_erf : return numeric::erf (arg); - case e_erfc : return numeric::erfc (arg); - case e_ncdf : return numeric::ncdf (arg); - case e_frac : return numeric::frac (arg); - case e_trunc : return numeric::trunc(arg); - - default : exprtk_debug(("numeric::details::process_impl - Invalid unary operation.\n")); - return std::numeric_limits::quiet_NaN(); - } - } - - template - inline T process_impl(const operator_type operation, const T arg0, const T arg1) - { - switch (operation) - { - case e_add : return (arg0 + arg1); - case e_sub : return (arg0 - arg1); - case e_mul : return (arg0 * arg1); - case e_div : return (arg0 / arg1); - case e_mod : return modulus(arg0,arg1); - case e_pow : return pow(arg0,arg1); - case e_atan2 : return atan2(arg0,arg1); - case e_min : return std::min(arg0,arg1); - case e_max : return std::max(arg0,arg1); - case e_logn : return logn(arg0,arg1); - case e_lt : return (arg0 < arg1) ? T(1) : T(0); - case e_lte : return (arg0 <= arg1) ? T(1) : T(0); - case e_eq : return std::equal_to()(arg0,arg1) ? T(1) : T(0); - case e_ne : return std::not_equal_to()(arg0,arg1) ? T(1) : T(0); - case e_gte : return (arg0 >= arg1) ? T(1) : T(0); - case e_gt : return (arg0 > arg1) ? T(1) : T(0); - case e_and : return and_opr (arg0,arg1); - case e_nand : return nand_opr(arg0,arg1); - case e_or : return or_opr (arg0,arg1); - case e_nor : return nor_opr (arg0,arg1); - case e_xor : return xor_opr (arg0,arg1); - case e_xnor : return xnor_opr(arg0,arg1); - case e_root : return root (arg0,arg1); - case e_roundn : return roundn (arg0,arg1); - case e_equal : return equal (arg0,arg1); - case e_nequal : return nequal (arg0,arg1); - case e_hypot : return hypot (arg0,arg1); - case e_shr : return shr (arg0,arg1); - case e_shl : return shl (arg0,arg1); - - default : exprtk_debug(("numeric::details::process_impl - Invalid binary operation.\n")); - return std::numeric_limits::quiet_NaN(); - } - } - - template - inline T process_impl(const operator_type operation, const T arg0, const T arg1, int_type_tag) - { - switch (operation) - { - case e_add : return (arg0 + arg1); - case e_sub : return (arg0 - arg1); - case e_mul : return (arg0 * arg1); - case e_div : return (arg0 / arg1); - case e_mod : return arg0 % arg1; - case e_pow : return pow(arg0,arg1); - case e_min : return std::min(arg0,arg1); - case e_max : return std::max(arg0,arg1); - case e_logn : return logn(arg0,arg1); - case e_lt : return (arg0 < arg1) ? T(1) : T(0); - case e_lte : return (arg0 <= arg1) ? T(1) : T(0); - case e_eq : return (arg0 == arg1) ? T(1) : T(0); - case e_ne : return (arg0 != arg1) ? T(1) : T(0); - case e_gte : return (arg0 >= arg1) ? T(1) : T(0); - case e_gt : return (arg0 > arg1) ? T(1) : T(0); - case e_and : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(1) : T(0); - case e_nand : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(0) : T(1); - case e_or : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(1) : T(0); - case e_nor : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(0) : T(1); - case e_xor : return arg0 ^ arg1; - case e_xnor : return !(arg0 ^ arg1); - case e_root : return root(arg0,arg1); - case e_equal : return arg0 == arg1; - case e_nequal : return arg0 != arg1; - case e_hypot : return hypot(arg0,arg1); - case e_shr : return arg0 >> arg1; - case e_shl : return arg0 << arg1; - - default : exprtk_debug(("numeric::details::process_impl - Invalid binary operation.\n")); - return std::numeric_limits::quiet_NaN(); - } - } - } - - template - inline T process(const operator_type operation, const T arg) - { - return exprtk::details::numeric::details::process_impl(operation,arg); - } - - template - inline T process(const operator_type operation, const T arg0, const T arg1) - { - return exprtk::details::numeric::details::process_impl(operation, arg0, arg1); - } - } - - template - struct node_collector_interface - { - typedef Node* node_ptr_t; - typedef Node** node_pp_t; - typedef std::vector noderef_list_t; - - virtual ~node_collector_interface() {} - - virtual void collect_nodes(noderef_list_t&) {} - }; - - template - struct node_depth_base; - - template - class expression_node : public node_collector_interface >, - public node_depth_base > - { - public: - - enum node_type - { - e_none , e_null , e_constant , e_unary , - e_binary , e_binary_ext , e_trinary , e_quaternary , - e_vararg , e_conditional , e_while , e_repeat , - e_for , e_switch , e_mswitch , e_return , - e_retenv , e_variable , e_stringvar , e_stringconst , - e_stringvarrng , e_cstringvarrng , e_strgenrange , e_strconcat , - e_stringvarsize , e_strswap , e_stringsize , e_stringvararg , - e_function , e_vafunction , e_genfunction , e_strfunction , - e_strcondition , e_strccondition , e_add , e_sub , - e_mul , e_div , e_mod , e_pow , - e_lt , e_lte , e_gt , e_gte , - e_eq , e_ne , e_and , e_nand , - e_or , e_nor , e_xor , e_xnor , - e_in , e_like , e_ilike , e_inranges , - e_ipow , e_ipowinv , e_abs , e_acos , - e_acosh , e_asin , e_asinh , e_atan , - e_atanh , e_ceil , e_cos , e_cosh , - e_exp , e_expm1 , e_floor , e_log , - e_log10 , e_log2 , e_log1p , e_neg , - e_pos , e_round , e_sin , e_sinc , - e_sinh , e_sqrt , e_tan , e_tanh , - e_cot , e_sec , e_csc , e_r2d , - e_d2r , e_d2g , e_g2d , e_notl , - e_sgn , e_erf , e_erfc , e_ncdf , - e_frac , e_trunc , e_uvouv , e_vov , - e_cov , e_voc , e_vob , e_bov , - e_cob , e_boc , e_vovov , e_vovoc , - e_vocov , e_covov , e_covoc , e_vovovov , - e_vovovoc , e_vovocov , e_vocovov , e_covovov , - e_covocov , e_vocovoc , e_covovoc , e_vococov , - e_sf3ext , e_sf4ext , e_nulleq , e_strass , - e_vector , e_vecelem , e_rbvecelem , e_rbveccelem , - e_vecdefass , e_vecvalass , e_vecvecass , e_vecopvalass , - e_vecopvecass , e_vecfunc , e_vecvecswap , e_vecvecineq , - e_vecvalineq , e_valvecineq , e_vecvecarith , e_vecvalarith , - e_valvecarith , e_vecunaryop , e_break , e_continue , - e_swap - }; - - typedef T value_type; - typedef expression_node* expression_ptr; - typedef node_collector_interface > nci_t; - typedef typename nci_t::noderef_list_t noderef_list_t; - typedef node_depth_base > ndb_t; - - virtual ~expression_node() - {} - - inline virtual T value() const - { - return std::numeric_limits::quiet_NaN(); - } - - inline virtual expression_node* branch(const std::size_t& index = 0) const - { - return reinterpret_cast(index * 0); - } - - inline virtual node_type type() const - { - return e_none; - } - }; - - template - inline bool is_generally_string_node(const expression_node* node); - - inline bool is_true(const double v) - { - return std::not_equal_to()(0.0,v); - } - - inline bool is_true(const long double v) - { - return std::not_equal_to()(0.0L,v); - } - - inline bool is_true(const float v) - { - return std::not_equal_to()(0.0f,v); - } - - template - inline bool is_true(const std::complex& v) - { - return std::not_equal_to >()(std::complex(0),v); - } - - template - inline bool is_true(const expression_node* node) - { - return std::not_equal_to()(T(0),node->value()); - } - - template - inline bool is_true(const std::pair*,bool>& node) - { - return std::not_equal_to()(T(0),node.first->value()); - } - - template - inline bool is_false(const expression_node* node) - { - return std::equal_to()(T(0),node->value()); - } - - template - inline bool is_false(const std::pair*,bool>& node) - { - return std::equal_to()(T(0),node.first->value()); - } - - template - inline bool is_unary_node(const expression_node* node) - { - return node && (details::expression_node::e_unary == node->type()); - } - - template - inline bool is_neg_unary_node(const expression_node* node) - { - return node && (details::expression_node::e_neg == node->type()); - } - - template - inline bool is_binary_node(const expression_node* node) - { - return node && (details::expression_node::e_binary == node->type()); - } - - template - inline bool is_variable_node(const expression_node* node) - { - return node && (details::expression_node::e_variable == node->type()); - } - - template - inline bool is_ivariable_node(const expression_node* node) - { - return node && - ( - details::expression_node::e_variable == node->type() || - details::expression_node::e_vecelem == node->type() || - details::expression_node::e_rbvecelem == node->type() || - details::expression_node::e_rbveccelem == node->type() - ); - } - - template - inline bool is_vector_elem_node(const expression_node* node) - { - return node && (details::expression_node::e_vecelem == node->type()); - } - - template - inline bool is_rebasevector_elem_node(const expression_node* node) - { - return node && (details::expression_node::e_rbvecelem == node->type()); - } - - template - inline bool is_rebasevector_celem_node(const expression_node* node) - { - return node && (details::expression_node::e_rbveccelem == node->type()); - } - - template - inline bool is_vector_node(const expression_node* node) - { - return node && (details::expression_node::e_vector == node->type()); - } - - template - inline bool is_ivector_node(const expression_node* node) - { - if (node) - { - switch (node->type()) - { - case details::expression_node::e_vector : - case details::expression_node::e_vecvalass : - case details::expression_node::e_vecvecass : - case details::expression_node::e_vecopvalass : - case details::expression_node::e_vecopvecass : - case details::expression_node::e_vecvecswap : - case details::expression_node::e_vecvecarith : - case details::expression_node::e_vecvalarith : - case details::expression_node::e_valvecarith : - case details::expression_node::e_vecunaryop : return true; - default : return false; - } - } - else - return false; - } - - template - inline bool is_constant_node(const expression_node* node) - { - return node && (details::expression_node::e_constant == node->type()); - } - - template - inline bool is_null_node(const expression_node* node) - { - return node && (details::expression_node::e_null == node->type()); - } - - template - inline bool is_break_node(const expression_node* node) - { - return node && (details::expression_node::e_break == node->type()); - } - - template - inline bool is_continue_node(const expression_node* node) - { - return node && (details::expression_node::e_continue == node->type()); - } - - template - inline bool is_swap_node(const expression_node* node) - { - return node && (details::expression_node::e_swap == node->type()); - } - - template - inline bool is_function(const expression_node* node) - { - return node && (details::expression_node::e_function == node->type()); - } - - template - inline bool is_return_node(const expression_node* node) - { - return node && (details::expression_node::e_return == node->type()); - } - - template class unary_node; - - template - inline bool is_negate_node(const expression_node* node) - { - if (node && is_unary_node(node)) - { - return (details::e_neg == static_cast*>(node)->operation()); - } - else - return false; - } - - template - inline bool branch_deletable(expression_node* node) - { - return (0 != node) && - !is_variable_node(node) && - !is_string_node (node) ; - } - - template - inline bool all_nodes_valid(expression_node* (&b)[N]) - { - for (std::size_t i = 0; i < N; ++i) - { - if (0 == b[i]) return false; - } - - return true; - } - - template class Sequence> - inline bool all_nodes_valid(const Sequence*,Allocator>& b) - { - for (std::size_t i = 0; i < b.size(); ++i) - { - if (0 == b[i]) return false; - } - - return true; - } - - template - inline bool all_nodes_variables(expression_node* (&b)[N]) - { - for (std::size_t i = 0; i < N; ++i) - { - if (0 == b[i]) - return false; - else if (!is_variable_node(b[i])) - return false; - } - - return true; - } - - template class Sequence> - inline bool all_nodes_variables(Sequence*,Allocator>& b) - { - for (std::size_t i = 0; i < b.size(); ++i) - { - if (0 == b[i]) - return false; - else if (!is_variable_node(b[i])) - return false; - } - - return true; - } - - template - class node_collection_destructor - { - public: - - typedef node_collector_interface nci_t; - - typedef typename nci_t::node_ptr_t node_ptr_t; - typedef typename nci_t::node_pp_t node_pp_t; - typedef typename nci_t::noderef_list_t noderef_list_t; - - static void delete_nodes(node_ptr_t& root) - { - std::vector node_delete_list; - node_delete_list.reserve(1000); - - collect_nodes(root, node_delete_list); - - for (std::size_t i = 0; i < node_delete_list.size(); ++i) - { - node_ptr_t& node = *node_delete_list[i]; - exprtk_debug(("ncd::delete_nodes() - deleting: %p\n", static_cast(node))); - delete node; - node = reinterpret_cast(0); - } - } - - private: - - static void collect_nodes(node_ptr_t& root, noderef_list_t& node_delete_list) - { - std::deque node_list; - node_list.push_back(root); - node_delete_list.push_back(&root); - - noderef_list_t child_node_delete_list; - child_node_delete_list.reserve(1000); - - while (!node_list.empty()) - { - node_list.front()->collect_nodes(child_node_delete_list); - - if (!child_node_delete_list.empty()) - { - for (std::size_t i = 0; i < child_node_delete_list.size(); ++i) - { - node_pp_t& node = child_node_delete_list[i]; - - if (0 == (*node)) - { - exprtk_debug(("ncd::collect_nodes() - null node encountered.\n")); - } - - node_list.push_back(*node); - } - - node_delete_list.insert( - node_delete_list.end(), - child_node_delete_list.begin(), child_node_delete_list.end()); - - child_node_delete_list.clear(); - } - - node_list.pop_front(); - } - - std::reverse(node_delete_list.begin(), node_delete_list.end()); - } - }; - - template - inline void free_all_nodes(NodeAllocator& node_allocator, expression_node* (&b)[N]) - { - for (std::size_t i = 0; i < N; ++i) - { - free_node(node_allocator,b[i]); - } - } - - template class Sequence> - inline void free_all_nodes(NodeAllocator& node_allocator, Sequence*,Allocator>& b) - { - for (std::size_t i = 0; i < b.size(); ++i) - { - free_node(node_allocator,b[i]); - } - - b.clear(); - } - - template - inline void free_node(NodeAllocator&, expression_node*& node) - { - if ((0 == node) || is_variable_node(node) || is_string_node(node)) - { - return; - } - - node_collection_destructor > - ::delete_nodes(node); - } - - template - inline void destroy_node(expression_node*& node) - { - if (0 != node) - { - node_collection_destructor > - ::delete_nodes(node); - } - } - - template - struct node_depth_base - { - typedef Node* node_ptr_t; - typedef std::pair nb_pair_t; - - node_depth_base() - : depth_set(false), - depth(0) - {} - - virtual ~node_depth_base() {} - - virtual std::size_t node_depth() const { return 1; } - - std::size_t compute_node_depth(const Node* const& node) const - { - if (!depth_set) - { - depth = 1 + (node ? node->node_depth() : 0); - depth_set = true; - } - - return depth; - } - - std::size_t compute_node_depth(const nb_pair_t& branch) const - { - if (!depth_set) - { - depth = 1 + (branch.first ? branch.first->node_depth() : 0); - depth_set = true; - } - - return depth; - } - - template - std::size_t compute_node_depth(const nb_pair_t (&branch)[N]) const - { - if (!depth_set) - { - depth = 0; - for (std::size_t i = 0; i < N; ++i) - { - if (branch[i].first) - { - depth = std::max(depth,branch[i].first->node_depth()); - } - } - depth += 1; - depth_set = true; - } - - return depth; - } - - template - std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1) const - { - if (!depth_set) - { - depth = 1 + std::max(compute_node_depth(n0), compute_node_depth(n1)); - depth_set = true; - } - - return depth; - } - - template - std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1, - const BranchType& n2) const - { - if (!depth_set) - { - depth = 1 + std::max( - std::max(compute_node_depth(n0), compute_node_depth(n1)), - compute_node_depth(n2)); - depth_set = true; - } - - return depth; - } - - template - std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1, - const BranchType& n2, const BranchType& n3) const - { - if (!depth_set) - { - depth = 1 + std::max( - std::max(compute_node_depth(n0), compute_node_depth(n1)), - std::max(compute_node_depth(n2), compute_node_depth(n3))); - depth_set = true; - } - - return depth; - } - - template class Sequence> - std::size_t compute_node_depth(const Sequence& branch_list) const - { - if (!depth_set) - { - for (std::size_t i = 0; i < branch_list.size(); ++i) - { - if (branch_list[i]) - { - depth = std::max(depth, compute_node_depth(branch_list[i])); - } - } - depth_set = true; - } - - return depth; - } - - template class Sequence> - std::size_t compute_node_depth(const Sequence& branch_list) const - { - if (!depth_set) - { - for (std::size_t i = 0; i < branch_list.size(); ++i) - { - if (branch_list[i].first) - { - depth = std::max(depth, compute_node_depth(branch_list[i].first)); - } - } - depth_set = true; - } - - return depth; - } - - mutable bool depth_set; - mutable std::size_t depth; - - template - void collect(node_ptr_t const& node, - const bool deletable, - NodeSequence& delete_node_list) const - { - if ((0 != node) && deletable) - { - delete_node_list.push_back(const_cast(&node)); - } - } - - template - void collect(const nb_pair_t& branch, - NodeSequence& delete_node_list) const - { - collect(branch.first, branch.second, delete_node_list); - } - - template - void collect(Node*& node, - NodeSequence& delete_node_list) const - { - collect(node, branch_deletable(node), delete_node_list); - } - - template - void collect(const nb_pair_t(&branch)[N], - NodeSequence& delete_node_list) const - { - for (std::size_t i = 0; i < N; ++i) - { - collect(branch[i].first, branch[i].second, delete_node_list); - } - } - - template class Sequence, - typename NodeSequence> - void collect(const Sequence& branch, - NodeSequence& delete_node_list) const - { - for (std::size_t i = 0; i < branch.size(); ++i) - { - collect(branch[i].first, branch[i].second, delete_node_list); - } - } - - template class Sequence, - typename NodeSequence> - void collect(const Sequence& branch_list, - NodeSequence& delete_node_list) const - { - for (std::size_t i = 0; i < branch_list.size(); ++i) - { - collect(branch_list[i], branch_deletable(branch_list[i]), delete_node_list); - } - } - - template class Sequence, - typename NodeSequence> - void collect(const Sequence& branch_list, - const Sequence& branch_deletable_list, - NodeSequence& delete_node_list) const - { - for (std::size_t i = 0; i < branch_list.size(); ++i) - { - collect(branch_list[i], branch_deletable_list[i], delete_node_list); - } - } - }; - - template - class vector_holder - { - private: - - typedef Type value_type; - typedef value_type* value_ptr; - typedef const value_ptr const_value_ptr; - - class vector_holder_base - { - public: - - virtual ~vector_holder_base() {} - - inline value_ptr operator[](const std::size_t& index) const - { - return value_at(index); - } - - inline std::size_t size() const - { - return vector_size(); - } - - inline value_ptr data() const - { - return value_at(0); - } - - virtual inline bool rebaseable() const - { - return false; - } - - virtual void set_ref(value_ptr*) {} - - protected: - - virtual value_ptr value_at(const std::size_t&) const = 0; - virtual std::size_t vector_size() const = 0; - }; - - class array_vector_impl : public vector_holder_base - { - public: - - array_vector_impl(const Type* vec, const std::size_t& vec_size) - : vec_(vec), - size_(vec_size) - {} - - protected: - - value_ptr value_at(const std::size_t& index) const - { - if (index < size_) - return const_cast(vec_ + index); - else - return const_value_ptr(0); - } - - std::size_t vector_size() const - { - return size_; - } - - private: - - array_vector_impl operator=(const array_vector_impl&); - - const Type* vec_; - const std::size_t size_; - }; - - template class Sequence> - class sequence_vector_impl : public vector_holder_base - { - public: - - typedef Sequence sequence_t; - - sequence_vector_impl(sequence_t& seq) - : sequence_(seq) - {} - - protected: - - value_ptr value_at(const std::size_t& index) const - { - return (index < sequence_.size()) ? (&sequence_[index]) : const_value_ptr(0); - } - - std::size_t vector_size() const - { - return sequence_.size(); - } - - private: - - sequence_vector_impl operator=(const sequence_vector_impl&); - - sequence_t& sequence_; - }; - - class vector_view_impl : public vector_holder_base - { - public: - - typedef exprtk::vector_view vector_view_t; - - vector_view_impl(vector_view_t& vec_view) - : vec_view_(vec_view) - {} - - void set_ref(value_ptr* ref) - { - vec_view_.set_ref(ref); - } - - virtual inline bool rebaseable() const - { - return true; - } - - protected: - - value_ptr value_at(const std::size_t& index) const - { - return (index < vec_view_.size()) ? (&vec_view_[index]) : const_value_ptr(0); - } - - std::size_t vector_size() const - { - return vec_view_.size(); - } - - private: - - vector_view_impl operator=(const vector_view_impl&); - - vector_view_t& vec_view_; - }; - - public: - - typedef typename details::vec_data_store vds_t; - - vector_holder(Type* vec, const std::size_t& vec_size) - : vector_holder_base_(new(buffer)array_vector_impl(vec,vec_size)) - {} - - vector_holder(const vds_t& vds) - : vector_holder_base_(new(buffer)array_vector_impl(vds.data(),vds.size())) - {} - - template - vector_holder(std::vector& vec) - : vector_holder_base_(new(buffer)sequence_vector_impl(vec)) - {} - - vector_holder(exprtk::vector_view& vec) - : vector_holder_base_(new(buffer)vector_view_impl(vec)) - {} - - inline value_ptr operator[](const std::size_t& index) const - { - return (*vector_holder_base_)[index]; - } - - inline std::size_t size() const - { - return vector_holder_base_->size(); - } - - inline value_ptr data() const - { - return vector_holder_base_->data(); - } - - void set_ref(value_ptr* ref) - { - vector_holder_base_->set_ref(ref); - } - - bool rebaseable() const - { - return vector_holder_base_->rebaseable(); - } - - private: - - mutable vector_holder_base* vector_holder_base_; - uchar_t buffer[64]; - }; - - template - class null_node exprtk_final : public expression_node - { - public: - - inline T value() const - { - return std::numeric_limits::quiet_NaN(); - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_null; - } - }; - - template - inline void construct_branch_pair(std::pair*,bool> (&branch)[N], - expression_node* b, - const std::size_t& index) - { - if (b && (index < N)) - { - branch[index] = std::make_pair(b,branch_deletable(b)); - } - } - - template - inline void construct_branch_pair(std::pair*,bool>& branch, expression_node* b) - { - if (b) - { - branch = std::make_pair(b,branch_deletable(b)); - } - } - - template - inline void init_branches(std::pair*,bool> (&branch)[N], - expression_node* b0, - expression_node* b1 = reinterpret_cast*>(0), - expression_node* b2 = reinterpret_cast*>(0), - expression_node* b3 = reinterpret_cast*>(0), - expression_node* b4 = reinterpret_cast*>(0), - expression_node* b5 = reinterpret_cast*>(0), - expression_node* b6 = reinterpret_cast*>(0), - expression_node* b7 = reinterpret_cast*>(0), - expression_node* b8 = reinterpret_cast*>(0), - expression_node* b9 = reinterpret_cast*>(0)) - { - construct_branch_pair(branch, b0, 0); - construct_branch_pair(branch, b1, 1); - construct_branch_pair(branch, b2, 2); - construct_branch_pair(branch, b3, 3); - construct_branch_pair(branch, b4, 4); - construct_branch_pair(branch, b5, 5); - construct_branch_pair(branch, b6, 6); - construct_branch_pair(branch, b7, 7); - construct_branch_pair(branch, b8, 8); - construct_branch_pair(branch, b9, 9); - } - - template - class null_eq_node exprtk_final : public expression_node - { - public: - - typedef expression_node* expression_ptr; - typedef std::pair branch_t; - - explicit null_eq_node(expression_ptr branch, const bool equality = true) - : equality_(equality) - { - construct_branch_pair(branch_, branch); - } - - inline T value() const - { - assert(branch_.first); - - const T v = branch_.first->value(); - const bool result = details::numeric::is_nan(v); - - if (result) - return (equality_) ? T(1) : T(0); - else - return (equality_) ? T(0) : T(1); - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_nulleq; - } - - inline operator_type operation() const - { - return details::e_eq; - } - - inline expression_node* branch(const std::size_t&) const - { - return branch_.first; - } - - void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) - { - expression_node::ndb_t::collect(branch_, node_delete_list); - } - - std::size_t node_depth() const - { - return expression_node::ndb_t::compute_node_depth(branch_); - } - - private: - - bool equality_; - branch_t branch_; - }; - - template - class literal_node exprtk_final : public expression_node - { - public: - - explicit literal_node(const T& v) - : value_(v) - {} - - inline T value() const - { - return value_; - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_constant; - } - - inline expression_node* branch(const std::size_t&) const - { - return reinterpret_cast*>(0); - } - - private: - - literal_node(literal_node&) {} - literal_node& operator=(literal_node&) { return (*this); } - - const T value_; - }; - - template - struct range_pack; - - template - struct range_data_type; - - template - class range_interface - { - public: - - typedef range_pack range_t; - - virtual ~range_interface() - {} - - virtual range_t& range_ref() = 0; - - virtual const range_t& range_ref() const = 0; - }; - - #ifndef exprtk_disable_string_capabilities - template - class string_base_node - { - public: - - typedef range_data_type range_data_type_t; - - virtual ~string_base_node() - {} - - virtual std::string str () const = 0; - - virtual char_cptr base() const = 0; - - virtual std::size_t size() const = 0; - }; - - template - class string_literal_node exprtk_final - : public expression_node , - public string_base_node, - public range_interface - { - public: - - typedef range_pack range_t; - - explicit string_literal_node(const std::string& v) - : value_(v) - { - rp_.n0_c = std::make_pair(true,0); - rp_.n1_c = std::make_pair(true,v.size() - 1); - rp_.cache.first = rp_.n0_c.second; - rp_.cache.second = rp_.n1_c.second; - } - - inline T value() const - { - return std::numeric_limits::quiet_NaN(); - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_stringconst; - } - - inline expression_node* branch(const std::size_t&) const - { - return reinterpret_cast*>(0); - } - - std::string str() const - { - return value_; - } - - char_cptr base() const - { - return value_.data(); - } - - std::size_t size() const - { - return value_.size(); - } - - range_t& range_ref() - { - return rp_; - } - - const range_t& range_ref() const - { - return rp_; - } - - private: - - string_literal_node(const string_literal_node&); - string_literal_node& operator=(const string_literal_node&); - - const std::string value_; - range_t rp_; - }; - #endif - - template - class unary_node : public expression_node - { - public: - - typedef expression_node* expression_ptr; - typedef std::pair branch_t; - - unary_node(const operator_type& opr, expression_ptr branch) - : operation_(opr) - { - construct_branch_pair(branch_,branch); - } - - inline T value() const - { - assert(branch_.first); - - const T arg = branch_.first->value(); - - return numeric::process(operation_,arg); - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_unary; - } - - inline operator_type operation() const - { - return operation_; - } - - inline expression_node* branch(const std::size_t&) const - { - return branch_.first; - } - - inline void release() - { - branch_.second = false; - } - - void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) - { - expression_node::ndb_t::collect(branch_, node_delete_list); - } - - std::size_t node_depth() const exprtk_final - { - return expression_node::ndb_t::compute_node_depth(branch_); - } - - protected: - - operator_type operation_; - branch_t branch_; - }; - - template - class binary_node : public expression_node - { - public: - - typedef expression_node* expression_ptr; - typedef std::pair branch_t; - - binary_node(const operator_type& opr, - expression_ptr branch0, - expression_ptr branch1) - : operation_(opr) - { - init_branches<2>(branch_, branch0, branch1); - } - - inline T value() const - { - assert(branch_[0].first); - assert(branch_[1].first); - - const T arg0 = branch_[0].first->value(); - const T arg1 = branch_[1].first->value(); - - return numeric::process(operation_,arg0,arg1); - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_binary; - } - - inline operator_type operation() - { - return operation_; - } - - inline expression_node* branch(const std::size_t& index = 0) const - { - if (0 == index) - return branch_[0].first; - else if (1 == index) - return branch_[1].first; - else - return reinterpret_cast(0); - } - - void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) - { - expression_node::ndb_t::template collect(branch_, node_delete_list); - } - - std::size_t node_depth() const exprtk_final - { - return expression_node::ndb_t::template compute_node_depth<2>(branch_); - } - - protected: - - operator_type operation_; - branch_t branch_[2]; - }; - - template - class binary_ext_node exprtk_final : public expression_node - { - public: - - typedef expression_node* expression_ptr; - typedef std::pair branch_t; - - binary_ext_node(expression_ptr branch0, expression_ptr branch1) - { - init_branches<2>(branch_, branch0, branch1); - } - - inline T value() const - { - assert(branch_[0].first); - assert(branch_[1].first); - - const T arg0 = branch_[0].first->value(); - const T arg1 = branch_[1].first->value(); - - return Operation::process(arg0,arg1); - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_binary_ext; - } - - inline operator_type operation() - { - return Operation::operation(); - } - - inline expression_node* branch(const std::size_t& index = 0) const - { - if (0 == index) - return branch_[0].first; - else if (1 == index) - return branch_[1].first; - else - return reinterpret_cast(0); - } - - void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) - { - expression_node::ndb_t::template collect(branch_, node_delete_list); - } - - std::size_t node_depth() const - { - return expression_node::ndb_t::template compute_node_depth<2>(branch_); - } - - protected: - - branch_t branch_[2]; - }; - - template - class trinary_node : public expression_node - { - public: - - typedef expression_node* expression_ptr; - typedef std::pair branch_t; - - trinary_node(const operator_type& opr, - expression_ptr branch0, - expression_ptr branch1, - expression_ptr branch2) - : operation_(opr) - { - init_branches<3>(branch_, branch0, branch1, branch2); - } - - inline T value() const - { - assert(branch_[0].first); - assert(branch_[1].first); - assert(branch_[2].first); - - const T arg0 = branch_[0].first->value(); - const T arg1 = branch_[1].first->value(); - const T arg2 = branch_[2].first->value(); - - switch (operation_) - { - case e_inrange : return (arg1 < arg0) ? T(0) : ((arg1 > arg2) ? T(0) : T(1)); - - case e_clamp : return (arg1 < arg0) ? arg0 : (arg1 > arg2 ? arg2 : arg1); - - case e_iclamp : if ((arg1 <= arg0) || (arg1 >= arg2)) - return arg1; - else - return ((T(2) * arg1 <= (arg2 + arg0)) ? arg0 : arg2); - - default : exprtk_debug(("trinary_node::value() - Error: Invalid operation\n")); - return std::numeric_limits::quiet_NaN(); - } - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_trinary; - } - - void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) - { - expression_node::ndb_t::template collect(branch_, node_delete_list); - } - - std::size_t node_depth() const exprtk_final - { - return expression_node::ndb_t::template compute_node_depth<3>(branch_); - } - - protected: - - operator_type operation_; - branch_t branch_[3]; - }; - - template - class quaternary_node : public expression_node - { - public: - - typedef expression_node* expression_ptr; - typedef std::pair branch_t; - - quaternary_node(const operator_type& opr, - expression_ptr branch0, - expression_ptr branch1, - expression_ptr branch2, - expression_ptr branch3) - : operation_(opr) - { - init_branches<4>(branch_, branch0, branch1, branch2, branch3); - } - - inline T value() const - { - return std::numeric_limits::quiet_NaN(); - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_quaternary; - } - - void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) - { - expression_node::ndb_t::template collect(branch_, node_delete_list); - } - - std::size_t node_depth() const exprtk_final - { - return expression_node::ndb_t::template compute_node_depth<4>(branch_); - } - - protected: - - operator_type operation_; - branch_t branch_[4]; - }; - - template - class conditional_node exprtk_final : public expression_node - { - public: - - typedef expression_node* expression_ptr; - typedef std::pair branch_t; - - conditional_node(expression_ptr condition, - expression_ptr consequent, - expression_ptr alternative) - { - construct_branch_pair(condition_ , condition ); - construct_branch_pair(consequent_ , consequent ); - construct_branch_pair(alternative_, alternative); - } - - inline T value() const - { - assert(condition_ .first); - assert(consequent_ .first); - assert(alternative_.first); - - if (is_true(condition_)) - return consequent_.first->value(); - else - return alternative_.first->value(); - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_conditional; - } - - void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) - { - expression_node::ndb_t::collect(condition_ , node_delete_list); - expression_node::ndb_t::collect(consequent_ , node_delete_list); - expression_node::ndb_t::collect(alternative_ , node_delete_list); - } - - std::size_t node_depth() const - { - return expression_node::ndb_t::compute_node_depth - (condition_, consequent_, alternative_); - } - - private: - - branch_t condition_; - branch_t consequent_; - branch_t alternative_; - }; - - template - class cons_conditional_node exprtk_final : public expression_node - { - public: - - // Consequent only conditional statement node - typedef expression_node* expression_ptr; - typedef std::pair branch_t; - - cons_conditional_node(expression_ptr condition, - expression_ptr consequent) - { - construct_branch_pair(condition_ , condition ); - construct_branch_pair(consequent_, consequent); - } - - inline T value() const - { - assert(condition_ .first); - assert(consequent_.first); - - if (is_true(condition_)) - return consequent_.first->value(); - else - return std::numeric_limits::quiet_NaN(); - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_conditional; - } - - void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) - { - expression_node::ndb_t::collect(condition_ , node_delete_list); - expression_node::ndb_t::collect(consequent_ , node_delete_list); - } - - std::size_t node_depth() const - { - return expression_node::ndb_t:: - compute_node_depth(condition_, consequent_); - } - - private: - - branch_t condition_; - branch_t consequent_; - }; - - #ifndef exprtk_disable_break_continue - template - class break_exception - { - public: - - explicit break_exception(const T& v) - : value(v) - {} - - T value; - }; - - class continue_exception - {}; - - template - class break_node exprtk_final : public expression_node - { - public: - - typedef expression_node* expression_ptr; - typedef std::pair branch_t; - - break_node(expression_ptr ret = expression_ptr(0)) - { - construct_branch_pair(return_, ret); - } - - inline T value() const - { - throw break_exception(return_.first ? return_.first->value() : std::numeric_limits::quiet_NaN()); - #ifndef _MSC_VER - return std::numeric_limits::quiet_NaN(); - #endif - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_break; - } - - void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) - { - expression_node::ndb_t::collect(return_, node_delete_list); - } - - std::size_t node_depth() const - { - return expression_node::ndb_t::compute_node_depth(return_); - } - - private: - - branch_t return_; - }; - - template - class continue_node exprtk_final : public expression_node - { - public: - - inline T value() const - { - throw continue_exception(); - #ifndef _MSC_VER - return std::numeric_limits::quiet_NaN(); - #endif - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_break; - } - }; - #endif - - #ifdef exprtk_enable_runtime_checks - struct loop_runtime_checker - { - loop_runtime_checker(loop_runtime_check_ptr loop_rt_chk = loop_runtime_check_ptr(0), - loop_runtime_check::loop_types lp_typ = loop_runtime_check::e_invalid) - : iteration_count_(0), - loop_runtime_check_(loop_rt_chk), - loop_type(lp_typ) - {} - - inline void reset(const _uint64_t initial_value = 0) const - { - iteration_count_ = initial_value; - } - - inline bool check() const - { - if ( - (0 == loop_runtime_check_) || - (++iteration_count_ <= loop_runtime_check_->max_loop_iterations) - ) - { - return true; - } - - loop_runtime_check::violation_context ctxt; - ctxt.loop = loop_type; - ctxt.violation = loop_runtime_check::e_iteration_count; - - loop_runtime_check_->handle_runtime_violation(ctxt); - - return false; - } - - mutable _uint64_t iteration_count_; - mutable loop_runtime_check_ptr loop_runtime_check_; - loop_runtime_check::loop_types loop_type; - }; - #else - struct loop_runtime_checker - { - loop_runtime_checker(loop_runtime_check_ptr, loop_runtime_check::loop_types) - {} - - inline void reset(const _uint64_t = 0) const - {} - - inline bool check() const - { - return true; - } - }; - #endif - - template - class while_loop_node exprtk_final - : public expression_node, - public loop_runtime_checker - { - public: - - typedef expression_node* expression_ptr; - typedef std::pair branch_t; - - while_loop_node(expression_ptr condition, - expression_ptr loop_body, - loop_runtime_check_ptr loop_rt_chk = loop_runtime_check_ptr(0)) - : loop_runtime_checker(loop_rt_chk,loop_runtime_check::e_while_loop) - { - construct_branch_pair(condition_, condition); - construct_branch_pair(loop_body_, loop_body); - } - - inline T value() const - { - assert(condition_.first); - assert(loop_body_.first); - - T result = T(0); - - loop_runtime_checker::reset(); - - while (is_true(condition_) && loop_runtime_checker::check()) - { - result = loop_body_.first->value(); - } - - return result; - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_while; - } - - void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) - { - expression_node::ndb_t::collect(condition_ , node_delete_list); - expression_node::ndb_t::collect(loop_body_ , node_delete_list); - } - - std::size_t node_depth() const - { - return expression_node::ndb_t::compute_node_depth(condition_, loop_body_); - } - - private: - - branch_t condition_; - branch_t loop_body_; - }; - - template - class repeat_until_loop_node exprtk_final - : public expression_node, - public loop_runtime_checker - { - public: - - typedef expression_node* expression_ptr; - typedef std::pair branch_t; - - repeat_until_loop_node(expression_ptr condition, - expression_ptr loop_body, - loop_runtime_check_ptr loop_rt_chk = loop_runtime_check_ptr(0)) - : loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_repeat_until_loop) - { - construct_branch_pair(condition_, condition); - construct_branch_pair(loop_body_, loop_body); - } - - inline T value() const - { - assert(condition_.first); - assert(loop_body_.first); - - T result = T(0); - - loop_runtime_checker::reset(1); - - do - { - result = loop_body_.first->value(); - } - while (is_false(condition_.first) && loop_runtime_checker::check()); - - return result; - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_repeat; - } - - void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) - { - expression_node::ndb_t::collect(condition_ , node_delete_list); - expression_node::ndb_t::collect(loop_body_ , node_delete_list); - } - - std::size_t node_depth() const - { - return expression_node::ndb_t::compute_node_depth(condition_, loop_body_); - } - - private: - - branch_t condition_; - branch_t loop_body_; - }; - - template - class for_loop_node exprtk_final - : public expression_node, - public loop_runtime_checker - { - public: - - typedef expression_node* expression_ptr; - typedef std::pair branch_t; - - for_loop_node(expression_ptr initialiser, - expression_ptr condition, - expression_ptr incrementor, - expression_ptr loop_body, - loop_runtime_check_ptr loop_rt_chk = loop_runtime_check_ptr(0)) - : loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_for_loop) - { - construct_branch_pair(initialiser_, initialiser); - construct_branch_pair(condition_ , condition ); - construct_branch_pair(incrementor_, incrementor); - construct_branch_pair(loop_body_ , loop_body ); - } - - inline T value() const - { - assert(condition_.first); - assert(loop_body_.first); - - T result = T(0); - - loop_runtime_checker::reset(); - - if (initialiser_.first) - initialiser_.first->value(); - - if (incrementor_.first) - { - while (is_true(condition_) && loop_runtime_checker::check()) - { - result = loop_body_.first->value(); - incrementor_.first->value(); - } - } - else - { - while (is_true(condition_) && loop_runtime_checker::check()) - { - result = loop_body_.first->value(); - } - } - - return result; - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_for; - } - - void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) - { - expression_node::ndb_t::collect(initialiser_ , node_delete_list); - expression_node::ndb_t::collect(condition_ , node_delete_list); - expression_node::ndb_t::collect(incrementor_ , node_delete_list); - expression_node::ndb_t::collect(loop_body_ , node_delete_list); - } - - std::size_t node_depth() const - { - return expression_node::ndb_t::compute_node_depth - (initialiser_, condition_, incrementor_, loop_body_); - } - - private: - - branch_t initialiser_; - branch_t condition_ ; - branch_t incrementor_; - branch_t loop_body_ ; - }; - - #ifndef exprtk_disable_break_continue - template - class while_loop_bc_node exprtk_final - : public expression_node, - public loop_runtime_checker - { - public: - - typedef expression_node* expression_ptr; - typedef std::pair branch_t; - - while_loop_bc_node(expression_ptr condition, - expression_ptr loop_body, - loop_runtime_check_ptr loop_rt_chk = loop_runtime_check_ptr(0)) - : loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_while_loop) - { - construct_branch_pair(condition_, condition); - construct_branch_pair(loop_body_, loop_body); - } - - inline T value() const - { - assert(condition_.first); - assert(loop_body_.first); - - T result = T(0); - - loop_runtime_checker::reset(); - - while (is_true(condition_) && loop_runtime_checker::check()) - { - try - { - result = loop_body_.first->value(); - } - catch(const break_exception& e) - { - return e.value; - } - catch(const continue_exception&) - {} - } - - return result; - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_while; - } - - void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) - { - expression_node::ndb_t::collect(condition_ , node_delete_list); - expression_node::ndb_t::collect(loop_body_ , node_delete_list); - } - - std::size_t node_depth() const - { - return expression_node::ndb_t::compute_node_depth(condition_, loop_body_); - } - - private: - - branch_t condition_; - branch_t loop_body_; - }; - - template - class repeat_until_loop_bc_node exprtk_final - : public expression_node, - public loop_runtime_checker - { - public: - - typedef expression_node* expression_ptr; - typedef std::pair branch_t; - - repeat_until_loop_bc_node(expression_ptr condition, - expression_ptr loop_body, - loop_runtime_check_ptr loop_rt_chk = loop_runtime_check_ptr(0)) - : loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_repeat_until_loop) - { - construct_branch_pair(condition_, condition); - construct_branch_pair(loop_body_, loop_body); - } - - inline T value() const - { - assert(condition_.first); - assert(loop_body_.first); - - T result = T(0); - - loop_runtime_checker::reset(); - - do - { - try - { - result = loop_body_.first->value(); - } - catch(const break_exception& e) - { - return e.value; - } - catch(const continue_exception&) - {} - } - while (is_false(condition_.first) && loop_runtime_checker::check()); - - return result; - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_repeat; - } - - void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) - { - expression_node::ndb_t::collect(condition_ , node_delete_list); - expression_node::ndb_t::collect(loop_body_ , node_delete_list); - } - - std::size_t node_depth() const - { - return expression_node::ndb_t::compute_node_depth(condition_, loop_body_); - } - - private: - - branch_t condition_; - branch_t loop_body_; - }; - - template - class for_loop_bc_node exprtk_final - : public expression_node, - public loop_runtime_checker - { - public: - - typedef expression_node* expression_ptr; - typedef std::pair branch_t; - - for_loop_bc_node(expression_ptr initialiser, - expression_ptr condition, - expression_ptr incrementor, - expression_ptr loop_body, - loop_runtime_check_ptr loop_rt_chk = loop_runtime_check_ptr(0)) - : loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_for_loop) - { - construct_branch_pair(initialiser_, initialiser); - construct_branch_pair(condition_ , condition ); - construct_branch_pair(incrementor_, incrementor); - construct_branch_pair(loop_body_ , loop_body ); - } - - inline T value() const - { - assert(condition_.first); - assert(loop_body_.first); - - T result = T(0); - - loop_runtime_checker::reset(); - - if (initialiser_.first) - initialiser_.first->value(); - - if (incrementor_.first) - { - while (is_true(condition_) && loop_runtime_checker::check()) - { - try - { - result = loop_body_.first->value(); - } - catch(const break_exception& e) - { - return e.value; - } - catch(const continue_exception&) - {} - - incrementor_.first->value(); - } - } - else - { - while (is_true(condition_) && loop_runtime_checker::check()) - { - try - { - result = loop_body_.first->value(); - } - catch(const break_exception& e) - { - return e.value; - } - catch(const continue_exception&) - {} - } - } - - return result; - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_for; - } - - void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) - { - expression_node::ndb_t::collect(initialiser_ , node_delete_list); - expression_node::ndb_t::collect(condition_ , node_delete_list); - expression_node::ndb_t::collect(incrementor_ , node_delete_list); - expression_node::ndb_t::collect(loop_body_ , node_delete_list); - } - - std::size_t node_depth() const - { - return expression_node::ndb_t::compute_node_depth - (initialiser_, condition_, incrementor_, loop_body_); - } - - private: - - branch_t initialiser_; - branch_t condition_ ; - branch_t incrementor_; - branch_t loop_body_ ; - }; - #endif - - template - class switch_node : public expression_node - { - public: - - typedef expression_node* expression_ptr; - typedef std::pair branch_t; - - template class Sequence> - explicit switch_node(const Sequence& arg_list) - { - if (1 != (arg_list.size() & 1)) - return; - - arg_list_.resize(arg_list.size()); - - for (std::size_t i = 0; i < arg_list.size(); ++i) - { - if (arg_list[i]) - { - construct_branch_pair(arg_list_[i], arg_list[i]); - } - else - { - arg_list_.clear(); - return; - } - } - } - - inline T value() const - { - if (!arg_list_.empty()) - { - const std::size_t upper_bound = (arg_list_.size() - 1); - - for (std::size_t i = 0; i < upper_bound; i += 2) - { - expression_ptr condition = arg_list_[i ].first; - expression_ptr consequent = arg_list_[i + 1].first; - - if (is_true(condition)) - { - return consequent->value(); - } - } - - return arg_list_[upper_bound].first->value(); - } - else - return std::numeric_limits::quiet_NaN(); - } - - inline typename expression_node::node_type type() const exprtk_final - { - return expression_node::e_switch; - } - - void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) - { - expression_node::ndb_t::collect(arg_list_, node_delete_list); - } - - std::size_t node_depth() const exprtk_final - { - return expression_node::ndb_t::compute_node_depth(arg_list_); - } - - protected: - - std::vector arg_list_; - }; - - template - class switch_n_node exprtk_final : public switch_node - { - public: - - typedef expression_node* expression_ptr; - - template class Sequence> - explicit switch_n_node(const Sequence& arg_list) - : switch_node(arg_list) - {} - - inline T value() const - { - return Switch_N::process(switch_node::arg_list_); - } - }; - - template - class multi_switch_node exprtk_final : public expression_node - { - public: - - typedef expression_node* expression_ptr; - typedef std::pair branch_t; - - template class Sequence> - explicit multi_switch_node(const Sequence& arg_list) - { - if (0 != (arg_list.size() & 1)) - return; - - arg_list_.resize(arg_list.size()); - - for (std::size_t i = 0; i < arg_list.size(); ++i) - { - if (arg_list[i]) - { - construct_branch_pair(arg_list_[i], arg_list[i]); - } - else - { - arg_list_.clear(); - return; - } - } - } - - inline T value() const - { - T result = T(0); - - if (arg_list_.empty()) - { - return std::numeric_limits::quiet_NaN(); - } - - const std::size_t upper_bound = (arg_list_.size() - 1); - - for (std::size_t i = 0; i < upper_bound; i += 2) - { - expression_ptr condition = arg_list_[i ].first; - expression_ptr consequent = arg_list_[i + 1].first; - - if (is_true(condition)) - { - result = consequent->value(); - } - } - - return result; - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_mswitch; - } - - void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) - { - expression_node::ndb_t::collect(arg_list_, node_delete_list); - } - - std::size_t node_depth() const exprtk_final - { - return expression_node::ndb_t::compute_node_depth(arg_list_); - } - - private: - - std::vector arg_list_; - }; - - template - class ivariable - { - public: - - virtual ~ivariable() - {} - - virtual T& ref() = 0; - virtual const T& ref() const = 0; - }; - - template - class variable_node exprtk_final - : public expression_node, - public ivariable - { - public: - - static T null_value; - - explicit variable_node() - : value_(&null_value) - {} - - explicit variable_node(T& v) - : value_(&v) - {} - - inline bool operator <(const variable_node& v) const - { - return this < (&v); - } - - inline T value() const - { - return (*value_); - } - - inline T& ref() - { - return (*value_); - } - - inline const T& ref() const - { - return (*value_); - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_variable; - } - - private: - - T* value_; - }; - - template - T variable_node::null_value = T(std::numeric_limits::quiet_NaN()); - - template - struct range_pack - { - typedef expression_node* expression_node_ptr; - typedef std::pair cached_range_t; - - range_pack() - : n0_e (std::make_pair(false,expression_node_ptr(0))), - n1_e (std::make_pair(false,expression_node_ptr(0))), - n0_c (std::make_pair(false,0)), - n1_c (std::make_pair(false,0)), - cache(std::make_pair(0,0)) - {} - - void clear() - { - n0_e = std::make_pair(false,expression_node_ptr(0)); - n1_e = std::make_pair(false,expression_node_ptr(0)); - n0_c = std::make_pair(false,0); - n1_c = std::make_pair(false,0); - cache = std::make_pair(0,0); - } - - void free() - { - if (n0_e.first && n0_e.second) - { - n0_e.first = false; - - if ( - !is_variable_node(n0_e.second) && - !is_string_node (n0_e.second) - ) - { - destroy_node(n0_e.second); - } - } - - if (n1_e.first && n1_e.second) - { - n1_e.first = false; - - if ( - !is_variable_node(n1_e.second) && - !is_string_node (n1_e.second) - ) - { - destroy_node(n1_e.second); - } - } - } - - bool const_range() const - { - return ( n0_c.first && n1_c.first) && - (!n0_e.first && !n1_e.first); - } - - bool var_range() const - { - return ( n0_e.first && n1_e.first) && - (!n0_c.first && !n1_c.first); - } - - bool operator() (std::size_t& r0, std::size_t& r1, - const std::size_t& size = std::numeric_limits::max()) const - { - if (n0_c.first) - r0 = n0_c.second; - else if (n0_e.first) - { - r0 = static_cast(details::numeric::to_int64(n0_e.second->value())); - } - else - return false; - - if (n1_c.first) - r1 = n1_c.second; - else if (n1_e.first) - { - r1 = static_cast(details::numeric::to_int64(n1_e.second->value())); - } - else - return false; - - if ( - (std::numeric_limits::max() != size) && - (std::numeric_limits::max() == r1 ) - ) - { - r1 = size - 1; - } - - cache.first = r0; - cache.second = r1; - - #ifndef exprtk_enable_runtime_checks - return (r0 <= r1); - #else - return range_runtime_check(r0, r1, size); - #endif - } - - inline std::size_t const_size() const - { - return (n1_c.second - n0_c.second + 1); - } - - inline std::size_t cache_size() const - { - return (cache.second - cache.first + 1); - } - - std::pair n0_e; - std::pair n1_e; - std::pair n0_c; - std::pair n1_c; - mutable cached_range_t cache; - - #ifdef exprtk_enable_runtime_checks - bool range_runtime_check(const std::size_t r0, - const std::size_t r1, - const std::size_t size) const - { - if (r0 >= size) - { - throw std::runtime_error("range error: (r0 < 0) || (r0 >= size)"); - return false; - } - - if (r1 >= size) - { - throw std::runtime_error("range error: (r1 < 0) || (r1 >= size)"); - return false; - } - - return (r0 <= r1); - } - #endif - }; - - template - class string_base_node; - - template - struct range_data_type - { - typedef range_pack range_t; - typedef string_base_node* strbase_ptr_t; - - range_data_type() - : range(0), - data (0), - size (0), - type_size(0), - str_node (0) - {} - - range_t* range; - void* data; - std::size_t size; - std::size_t type_size; - strbase_ptr_t str_node; - }; - - template class vector_node; - - template - class vector_interface - { - public: - - typedef vector_node* vector_node_ptr; - typedef vec_data_store vds_t; - - virtual ~vector_interface() - {} - - virtual std::size_t size () const = 0; - - virtual vector_node_ptr vec() const = 0; - - virtual vector_node_ptr vec() = 0; - - virtual vds_t& vds () = 0; - - virtual const vds_t& vds () const = 0; - - virtual bool side_effect () const { return false; } - }; - - template - class vector_node exprtk_final - : public expression_node , - public vector_interface - { - public: - - typedef expression_node* expression_ptr; - typedef vector_holder vector_holder_t; - typedef vector_node* vector_node_ptr; - typedef vec_data_store vds_t; - - explicit vector_node(vector_holder_t* vh) - : vector_holder_(vh), - vds_((*vector_holder_).size(),(*vector_holder_)[0]) - { - vector_holder_->set_ref(&vds_.ref()); - } - - vector_node(const vds_t& vds, vector_holder_t* vh) - : vector_holder_(vh), - vds_(vds) - {} - - inline T value() const - { - return vds().data()[0]; - } - - vector_node_ptr vec() const - { - return const_cast(this); - } - - vector_node_ptr vec() - { - return this; - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_vector; - } - - std::size_t size() const - { - return vds().size(); - } - - vds_t& vds() - { - return vds_; - } - - const vds_t& vds() const - { - return vds_; - } - - inline vector_holder_t& vec_holder() - { - return (*vector_holder_); - } - - private: - - vector_holder_t* vector_holder_; - vds_t vds_; - }; - - template - class vector_elem_node exprtk_final - : public expression_node, - public ivariable - { - public: - - typedef expression_node* expression_ptr; - typedef vector_holder vector_holder_t; - typedef vector_holder_t* vector_holder_ptr; - typedef std::pair branch_t; - - vector_elem_node(expression_ptr index, vector_holder_ptr vec_holder) - : vec_holder_(vec_holder), - vector_base_((*vec_holder)[0]) - { - construct_branch_pair(index_, index); - } - - inline T value() const - { - return *(vector_base_ + static_cast(details::numeric::to_int64(index_.first->value()))); - } - - inline T& ref() - { - return *(vector_base_ + static_cast(details::numeric::to_int64(index_.first->value()))); - } - - inline const T& ref() const - { - return *(vector_base_ + static_cast(details::numeric::to_int64(index_.first->value()))); - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_vecelem; - } - - inline vector_holder_t& vec_holder() - { - return (*vec_holder_); - } - - void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) - { - expression_node::ndb_t::collect(index_, node_delete_list); - } - - std::size_t node_depth() const - { - return expression_node::ndb_t::compute_node_depth(index_); - } - - private: - - vector_holder_ptr vec_holder_; - T* vector_base_; - branch_t index_; - }; - - template - class rebasevector_elem_node exprtk_final - : public expression_node, - public ivariable - { - public: - - typedef expression_node* expression_ptr; - typedef vector_holder vector_holder_t; - typedef vector_holder_t* vector_holder_ptr; - typedef vec_data_store vds_t; - typedef std::pair branch_t; - - rebasevector_elem_node(expression_ptr index, vector_holder_ptr vec_holder) - : vector_holder_(vec_holder), - vds_((*vector_holder_).size(),(*vector_holder_)[0]) - { - vector_holder_->set_ref(&vds_.ref()); - construct_branch_pair(index_, index); - } - - inline T value() const - { - return *(vds_.data() + static_cast(details::numeric::to_int64(index_.first->value()))); - } - - inline T& ref() - { - return *(vds_.data() + static_cast(details::numeric::to_int64(index_.first->value()))); - } - - inline const T& ref() const - { - return *(vds_.data() + static_cast(details::numeric::to_int64(index_.first->value()))); - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_rbvecelem; - } - - inline vector_holder_t& vec_holder() - { - return (*vector_holder_); - } - - void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) - { - expression_node::ndb_t::template collect(index_, node_delete_list); - } - - std::size_t node_depth() const - { - return expression_node::ndb_t::compute_node_depth(index_); - } - - private: - - vector_holder_ptr vector_holder_; - vds_t vds_; - branch_t index_; - }; - - template - class rebasevector_celem_node exprtk_final - : public expression_node, - public ivariable - { - public: - - typedef expression_node* expression_ptr; - typedef vector_holder vector_holder_t; - typedef vector_holder_t* vector_holder_ptr; - typedef vec_data_store vds_t; - - rebasevector_celem_node(const std::size_t index, vector_holder_ptr vec_holder) - : index_(index), - vector_holder_(vec_holder), - vds_((*vector_holder_).size(),(*vector_holder_)[0]) - { - vector_holder_->set_ref(&vds_.ref()); - } - - inline T value() const - { - return *(vds_.data() + index_); - } - - inline T& ref() - { - return *(vds_.data() + index_); - } - - inline const T& ref() const - { - return *(vds_.data() + index_); - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_rbveccelem; - } - - inline vector_holder_t& vec_holder() - { - return (*vector_holder_); - } - - private: - - const std::size_t index_; - vector_holder_ptr vector_holder_; - vds_t vds_; - }; - - template - class vector_assignment_node exprtk_final : public expression_node - { - public: - - typedef expression_node* expression_ptr; - - vector_assignment_node(T* vector_base, - const std::size_t& size, - const std::vector& initialiser_list, - const bool single_value_initialse) - : vector_base_(vector_base), - initialiser_list_(initialiser_list), - size_(size), - single_value_initialse_(single_value_initialse) - {} - - inline T value() const - { - if (single_value_initialse_) - { - for (std::size_t i = 0; i < size_; ++i) - { - *(vector_base_ + i) = initialiser_list_[0]->value(); - } - } - else - { - std::size_t il_size = initialiser_list_.size(); - - for (std::size_t i = 0; i < il_size; ++i) - { - *(vector_base_ + i) = initialiser_list_[i]->value(); - } - - if (il_size < size_) - { - for (std::size_t i = il_size; i < size_; ++i) - { - *(vector_base_ + i) = T(0); - } - } - } - - return *(vector_base_); - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_vecdefass; - } - - void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) - { - expression_node::ndb_t::collect(initialiser_list_, node_delete_list); - } - - std::size_t node_depth() const - { - return expression_node::ndb_t::compute_node_depth(initialiser_list_); - } - - private: - - vector_assignment_node& operator=(const vector_assignment_node&); - - mutable T* vector_base_; - std::vector initialiser_list_; - const std::size_t size_; - const bool single_value_initialse_; - }; - - template - class swap_node exprtk_final : public expression_node - { - public: - - typedef expression_node* expression_ptr; - typedef variable_node* variable_node_ptr; - - swap_node(variable_node_ptr var0, variable_node_ptr var1) - : var0_(var0), - var1_(var1) - {} - - inline T value() const - { - std::swap(var0_->ref(),var1_->ref()); - return var1_->ref(); - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_swap; - } - - private: - - variable_node_ptr var0_; - variable_node_ptr var1_; - }; - - template - class swap_generic_node exprtk_final : public binary_node - { - public: - - typedef expression_node* expression_ptr; - typedef ivariable* ivariable_ptr; - - swap_generic_node(expression_ptr var0, expression_ptr var1) - : binary_node(details::e_swap, var0, var1), - var0_(dynamic_cast(var0)), - var1_(dynamic_cast(var1)) - {} - - inline T value() const - { - std::swap(var0_->ref(),var1_->ref()); - return var1_->ref(); - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_swap; - } - - private: - - ivariable_ptr var0_; - ivariable_ptr var1_; - }; - - template - class swap_vecvec_node exprtk_final - : public binary_node , - public vector_interface - { - public: - - typedef expression_node* expression_ptr; - typedef vector_node* vector_node_ptr; - typedef vec_data_store vds_t; - - swap_vecvec_node(expression_ptr branch0, - expression_ptr branch1) - : binary_node(details::e_swap, branch0, branch1), - vec0_node_ptr_(0), - vec1_node_ptr_(0), - vec_size_ (0), - initialised_ (false) - { - if (is_ivector_node(binary_node::branch_[0].first)) - { - vector_interface* vi = reinterpret_cast*>(0); - - if (0 != (vi = dynamic_cast*>(binary_node::branch_[0].first))) - { - vec0_node_ptr_ = vi->vec(); - vds() = vi->vds(); - } - } - - if (is_ivector_node(binary_node::branch_[1].first)) - { - vector_interface* vi = reinterpret_cast*>(0); - - if (0 != (vi = dynamic_cast*>(binary_node::branch_[1].first))) - { - vec1_node_ptr_ = vi->vec(); - } - } - - if (vec0_node_ptr_ && vec1_node_ptr_) - { - vec_size_ = std::min(vec0_node_ptr_->vds().size(), - vec1_node_ptr_->vds().size()); - - initialised_ = true; - } - } - - inline T value() const - { - assert(binary_node::branch_[0].first); - assert(binary_node::branch_[1].first); - - if (initialised_) - { - binary_node::branch_[0].first->value(); - binary_node::branch_[1].first->value(); - - T* vec0 = vec0_node_ptr_->vds().data(); - T* vec1 = vec1_node_ptr_->vds().data(); - - for (std::size_t i = 0; i < vec_size_; ++i) - { - std::swap(vec0[i],vec1[i]); - } - - return vec1_node_ptr_->value(); - } - else - return std::numeric_limits::quiet_NaN(); - } - - vector_node_ptr vec() const - { - return vec0_node_ptr_; - } - - vector_node_ptr vec() - { - return vec0_node_ptr_; - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_vecvecswap; - } - - std::size_t size() const - { - return vec_size_; - } - - vds_t& vds() - { - return vds_; - } - - const vds_t& vds() const - { - return vds_; - } - - private: - - vector_node* vec0_node_ptr_; - vector_node* vec1_node_ptr_; - std::size_t vec_size_; - bool initialised_; - vds_t vds_; - }; - - #ifndef exprtk_disable_string_capabilities - template - class stringvar_node exprtk_final - : public expression_node , - public string_base_node, - public range_interface - { - public: - - typedef range_pack range_t; - - static std::string null_value; - - explicit stringvar_node() - : value_(&null_value) - {} - - explicit stringvar_node(std::string& v) - : value_(&v) - { - rp_.n0_c = std::make_pair(true,0); - rp_.n1_c = std::make_pair(true,v.size() - 1); - rp_.cache.first = rp_.n0_c.second; - rp_.cache.second = rp_.n1_c.second; - } - - inline bool operator <(const stringvar_node& v) const - { - return this < (&v); - } - - inline T value() const - { - rp_.n1_c.second = (*value_).size() - 1; - rp_.cache.second = rp_.n1_c.second; - - return std::numeric_limits::quiet_NaN(); - } - - std::string str() const - { - return ref(); - } - - char_cptr base() const - { - return &(*value_)[0]; - } - - std::size_t size() const - { - return ref().size(); - } - - std::string& ref() - { - return (*value_); - } - - const std::string& ref() const - { - return (*value_); - } - - range_t& range_ref() - { - return rp_; - } - - const range_t& range_ref() const - { - return rp_; - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_stringvar; - } - - private: - - std::string* value_; - mutable range_t rp_; - }; - - template - std::string stringvar_node::null_value = std::string(""); - - template - class string_range_node exprtk_final - : public expression_node , - public string_base_node, - public range_interface - { - public: - - typedef range_pack range_t; - - static std::string null_value; - - explicit string_range_node(std::string& v, const range_t& rp) - : value_(&v), - rp_(rp) - {} - - virtual ~string_range_node() - { - rp_.free(); - } - - inline bool operator <(const string_range_node& v) const - { - return this < (&v); - } - - inline T value() const - { - return std::numeric_limits::quiet_NaN(); - } - - inline std::string str() const - { - return (*value_); - } - - char_cptr base() const - { - return &(*value_)[0]; - } - - std::size_t size() const - { - return ref().size(); - } - - inline range_t range() const - { - return rp_; - } - - inline virtual std::string& ref() - { - return (*value_); - } - - inline virtual const std::string& ref() const - { - return (*value_); - } - - inline range_t& range_ref() - { - return rp_; - } - - inline const range_t& range_ref() const - { - return rp_; - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_stringvarrng; - } - - private: - - std::string* value_; - range_t rp_; - }; - - template - std::string string_range_node::null_value = std::string(""); - - template - class const_string_range_node exprtk_final - : public expression_node , - public string_base_node, - public range_interface - { - public: - - typedef range_pack range_t; - - explicit const_string_range_node(const std::string& v, const range_t& rp) - : value_(v), - rp_(rp) - {} - - ~const_string_range_node() - { - rp_.free(); - } - - inline T value() const - { - return std::numeric_limits::quiet_NaN(); - } - - std::string str() const - { - return value_; - } - - char_cptr base() const - { - return value_.data(); - } - - std::size_t size() const - { - return value_.size(); - } - - range_t range() const - { - return rp_; - } - - range_t& range_ref() - { - return rp_; - } - - const range_t& range_ref() const - { - return rp_; - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_cstringvarrng; - } - - private: - - const_string_range_node& operator=(const const_string_range_node&); - - const std::string value_; - range_t rp_; - }; - - template - class generic_string_range_node exprtk_final - : public expression_node , - public string_base_node, - public range_interface - { - public: - - typedef expression_node * expression_ptr; - typedef stringvar_node * strvar_node_ptr; - typedef string_base_node* str_base_ptr; - typedef range_pack range_t; - typedef range_t* range_ptr; - typedef range_interface irange_t; - typedef irange_t* irange_ptr; - typedef std::pair branch_t; - - - generic_string_range_node(expression_ptr str_branch, const range_t& brange) - : initialised_(false), - str_base_ptr_ (0), - str_range_ptr_(0), - base_range_(brange) - { - range_.n0_c = std::make_pair(true,0); - range_.n1_c = std::make_pair(true,0); - range_.cache.first = range_.n0_c.second; - range_.cache.second = range_.n1_c.second; - - construct_branch_pair(branch_, str_branch); - - if (is_generally_string_node(branch_.first)) - { - str_base_ptr_ = dynamic_cast(branch_.first); - - if (0 == str_base_ptr_) - return; - - str_range_ptr_ = dynamic_cast(branch_.first); - - if (0 == str_range_ptr_) - return; - } - - initialised_ = (str_base_ptr_ && str_range_ptr_); - } - - ~generic_string_range_node() - { - base_range_.free(); - } - - inline T value() const - { - if (initialised_) - { - assert(branch_.first); - - branch_.first->value(); - - std::size_t str_r0 = 0; - std::size_t str_r1 = 0; - - std::size_t r0 = 0; - std::size_t r1 = 0; - - const range_t& range = str_range_ptr_->range_ref(); - - const std::size_t base_str_size = str_base_ptr_->size(); - - if ( - range (str_r0, str_r1, base_str_size) && - base_range_( r0, r1, base_str_size - str_r0) - ) - { - const std::size_t size = (r1 - r0) + 1; - - range_.n1_c.second = size - 1; - range_.cache.second = range_.n1_c.second; - - value_.assign(str_base_ptr_->base() + str_r0 + r0, size); - } - } - - return std::numeric_limits::quiet_NaN(); - } - - std::string str() const - { - return value_; - } - - char_cptr base() const - { - return &value_[0]; - } - - std::size_t size() const - { - return value_.size(); - } - - range_t& range_ref() - { - return range_; - } - - const range_t& range_ref() const - { - return range_; - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_strgenrange; - } - - void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) - { - expression_node::ndb_t::collect(branch_, node_delete_list); - } - - std::size_t node_depth() const - { - return expression_node::ndb_t::compute_node_depth(branch_); - } - - private: - - bool initialised_; - branch_t branch_; - str_base_ptr str_base_ptr_; - irange_ptr str_range_ptr_; - mutable range_t base_range_; - mutable range_t range_; - mutable std::string value_; - }; - - template - class string_concat_node exprtk_final - : public binary_node , - public string_base_node, - public range_interface - { - public: - - typedef expression_node * expression_ptr; - typedef string_base_node* str_base_ptr; - typedef range_pack range_t; - typedef range_t* range_ptr; - typedef range_interface irange_t; - typedef irange_t* irange_ptr; - - string_concat_node(const operator_type& opr, - expression_ptr branch0, - expression_ptr branch1) - : binary_node(opr, branch0, branch1), - initialised_(false), - str0_base_ptr_ (0), - str1_base_ptr_ (0), - str0_range_ptr_(0), - str1_range_ptr_(0) - { - range_.n0_c = std::make_pair(true,0); - range_.n1_c = std::make_pair(true,0); - - range_.cache.first = range_.n0_c.second; - range_.cache.second = range_.n1_c.second; - - if (is_generally_string_node(binary_node::branch_[0].first)) - { - str0_base_ptr_ = dynamic_cast(binary_node::branch_[0].first); - - if (0 == str0_base_ptr_) - return; - - str0_range_ptr_ = dynamic_cast(binary_node::branch_[0].first); - - if (0 == str0_range_ptr_) - return; - } - - if (is_generally_string_node(binary_node::branch_[1].first)) - { - str1_base_ptr_ = dynamic_cast(binary_node::branch_[1].first); - - if (0 == str1_base_ptr_) - return; - - str1_range_ptr_ = dynamic_cast(binary_node::branch_[1].first); - - if (0 == str1_range_ptr_) - return; - } - - initialised_ = str0_base_ptr_ && - str1_base_ptr_ && - str0_range_ptr_ && - str1_range_ptr_ ; - } - - inline T value() const - { - if (initialised_) - { - assert(binary_node::branch_[0].first); - assert(binary_node::branch_[1].first); - - binary_node::branch_[0].first->value(); - binary_node::branch_[1].first->value(); - - std::size_t str0_r0 = 0; - std::size_t str0_r1 = 0; - - std::size_t str1_r0 = 0; - std::size_t str1_r1 = 0; - - const range_t& range0 = str0_range_ptr_->range_ref(); - const range_t& range1 = str1_range_ptr_->range_ref(); - - if ( - range0(str0_r0, str0_r1, str0_base_ptr_->size()) && - range1(str1_r0, str1_r1, str1_base_ptr_->size()) - ) - { - const std::size_t size0 = (str0_r1 - str0_r0) + 1; - const std::size_t size1 = (str1_r1 - str1_r0) + 1; - - value_.assign(str0_base_ptr_->base() + str0_r0, size0); - value_.append(str1_base_ptr_->base() + str1_r0, size1); - - range_.n1_c.second = value_.size() - 1; - range_.cache.second = range_.n1_c.second; - } - } - - return std::numeric_limits::quiet_NaN(); - } - - std::string str() const - { - return value_; - } - - char_cptr base() const - { - return &value_[0]; - } - - std::size_t size() const - { - return value_.size(); - } - - range_t& range_ref() - { - return range_; - } - - const range_t& range_ref() const - { - return range_; - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_strconcat; - } - - private: - - bool initialised_; - str_base_ptr str0_base_ptr_; - str_base_ptr str1_base_ptr_; - irange_ptr str0_range_ptr_; - irange_ptr str1_range_ptr_; - mutable range_t range_; - mutable std::string value_; - }; - - template - class swap_string_node exprtk_final - : public binary_node , - public string_base_node, - public range_interface - { - public: - - typedef expression_node * expression_ptr; - typedef stringvar_node * strvar_node_ptr; - typedef string_base_node* str_base_ptr; - typedef range_pack range_t; - typedef range_t* range_ptr; - typedef range_interface irange_t; - typedef irange_t* irange_ptr; - - swap_string_node(expression_ptr branch0, expression_ptr branch1) - : binary_node(details::e_swap, branch0, branch1), - initialised_(false), - str0_node_ptr_(0), - str1_node_ptr_(0) - { - if (is_string_node(binary_node::branch_[0].first)) - { - str0_node_ptr_ = static_cast(binary_node::branch_[0].first); - } - - if (is_string_node(binary_node::branch_[1].first)) - { - str1_node_ptr_ = static_cast(binary_node::branch_[1].first); - } - - initialised_ = (str0_node_ptr_ && str1_node_ptr_); - } - - inline T value() const - { - if (initialised_) - { - assert(binary_node::branch_[0].first); - assert(binary_node::branch_[1].first); - - binary_node::branch_[0].first->value(); - binary_node::branch_[1].first->value(); - - std::swap(str0_node_ptr_->ref(), str1_node_ptr_->ref()); - } - - return std::numeric_limits::quiet_NaN(); - } - - std::string str() const - { - return str0_node_ptr_->str(); - } - - char_cptr base() const - { - return str0_node_ptr_->base(); - } - - std::size_t size() const - { - return str0_node_ptr_->size(); - } - - range_t& range_ref() - { - return str0_node_ptr_->range_ref(); - } - - const range_t& range_ref() const - { - return str0_node_ptr_->range_ref(); - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_strswap; - } - - private: - - bool initialised_; - strvar_node_ptr str0_node_ptr_; - strvar_node_ptr str1_node_ptr_; - }; - - template - class swap_genstrings_node exprtk_final : public binary_node - { - public: - - typedef expression_node * expression_ptr; - typedef string_base_node* str_base_ptr; - typedef range_pack range_t; - typedef range_t* range_ptr; - typedef range_interface irange_t; - typedef irange_t* irange_ptr; - - swap_genstrings_node(expression_ptr branch0, - expression_ptr branch1) - : binary_node(details::e_default, branch0, branch1), - str0_base_ptr_ (0), - str1_base_ptr_ (0), - str0_range_ptr_(0), - str1_range_ptr_(0), - initialised_(false) - { - if (is_generally_string_node(binary_node::branch_[0].first)) - { - str0_base_ptr_ = dynamic_cast(binary_node::branch_[0].first); - - if (0 == str0_base_ptr_) - return; - - irange_ptr range = dynamic_cast(binary_node::branch_[0].first); - - if (0 == range) - return; - - str0_range_ptr_ = &(range->range_ref()); - } - - if (is_generally_string_node(binary_node::branch_[1].first)) - { - str1_base_ptr_ = dynamic_cast(binary_node::branch_[1].first); - - if (0 == str1_base_ptr_) - return; - - irange_ptr range = dynamic_cast(binary_node::branch_[1].first); - - if (0 == range) - return; - - str1_range_ptr_ = &(range->range_ref()); - } - - initialised_ = str0_base_ptr_ && - str1_base_ptr_ && - str0_range_ptr_ && - str1_range_ptr_ ; - } - - inline T value() const - { - if (initialised_) - { - assert(binary_node::branch_[0].first); - assert(binary_node::branch_[1].first); - - binary_node::branch_[0].first->value(); - binary_node::branch_[1].first->value(); - - std::size_t str0_r0 = 0; - std::size_t str0_r1 = 0; - - std::size_t str1_r0 = 0; - std::size_t str1_r1 = 0; - - const range_t& range0 = (*str0_range_ptr_); - const range_t& range1 = (*str1_range_ptr_); - - if ( - range0(str0_r0, str0_r1, str0_base_ptr_->size()) && - range1(str1_r0, str1_r1, str1_base_ptr_->size()) - ) - { - const std::size_t size0 = range0.cache_size(); - const std::size_t size1 = range1.cache_size(); - const std::size_t max_size = std::min(size0,size1); - - char_ptr s0 = const_cast(str0_base_ptr_->base() + str0_r0); - char_ptr s1 = const_cast(str1_base_ptr_->base() + str1_r0); - - loop_unroll::details lud(max_size); - char_cptr upper_bound = s0 + lud.upper_bound; - - while (s0 < upper_bound) - { - #define exprtk_loop(N) \ - std::swap(s0[N], s1[N]); \ - - exprtk_loop( 0) exprtk_loop( 1) - exprtk_loop( 2) exprtk_loop( 3) - #ifndef exprtk_disable_superscalar_unroll - exprtk_loop( 4) exprtk_loop( 5) - exprtk_loop( 6) exprtk_loop( 7) - exprtk_loop( 8) exprtk_loop( 9) - exprtk_loop(10) exprtk_loop(11) - exprtk_loop(12) exprtk_loop(13) - exprtk_loop(14) exprtk_loop(15) - #endif - - s0 += lud.batch_size; - s1 += lud.batch_size; - } - - int i = 0; - - exprtk_disable_fallthrough_begin - switch (lud.remainder) - { - #define case_stmt(N) \ - case N : { std::swap(s0[i], s1[i]); ++i; } \ - - #ifndef exprtk_disable_superscalar_unroll - case_stmt(15) case_stmt(14) - case_stmt(13) case_stmt(12) - case_stmt(11) case_stmt(10) - case_stmt( 9) case_stmt( 8) - case_stmt( 7) case_stmt( 6) - case_stmt( 5) case_stmt( 4) - #endif - case_stmt( 3) case_stmt( 2) - case_stmt( 1) - } - exprtk_disable_fallthrough_end - - #undef exprtk_loop - #undef case_stmt - } - } - - return std::numeric_limits::quiet_NaN(); - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_strswap; - } - - private: - - swap_genstrings_node(swap_genstrings_node&); - swap_genstrings_node& operator=(swap_genstrings_node&); - - str_base_ptr str0_base_ptr_; - str_base_ptr str1_base_ptr_; - range_ptr str0_range_ptr_; - range_ptr str1_range_ptr_; - bool initialised_; - }; - - template - class stringvar_size_node exprtk_final : public expression_node - { - public: - - static std::string null_value; - - explicit stringvar_size_node() - : value_(&null_value) - {} - - explicit stringvar_size_node(std::string& v) - : value_(&v) - {} - - inline T value() const - { - return T((*value_).size()); - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_stringvarsize; - } - - private: - - std::string* value_; - }; - - template - std::string stringvar_size_node::null_value = std::string(""); - - template - class string_size_node exprtk_final : public expression_node - { - public: - - typedef expression_node * expression_ptr; - typedef string_base_node* str_base_ptr; - typedef std::pair branch_t; - - - explicit string_size_node(expression_ptr branch) - : str_base_ptr_(0) - { - construct_branch_pair(branch_, branch); - - if (is_generally_string_node(branch_.first)) - { - str_base_ptr_ = dynamic_cast(branch_.first); - - if (0 == str_base_ptr_) - return; - } - } - - inline T value() const - { - T result = std::numeric_limits::quiet_NaN(); - - if (str_base_ptr_) - { - branch_.first->value(); - result = T(str_base_ptr_->size()); - } - - return result; - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_stringsize; - } - - void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) - { - expression_node::ndb_t::collect(branch_, node_delete_list); - } - - std::size_t node_depth() const - { - return expression_node::ndb_t::compute_node_depth(branch_); - } - - private: - - branch_t branch_; - str_base_ptr str_base_ptr_; - }; - - struct asn_assignment - { - static inline void execute(std::string& s, char_cptr data, const std::size_t size) - { s.assign(data,size); } - }; - - struct asn_addassignment - { - static inline void execute(std::string& s, char_cptr data, const std::size_t size) - { s.append(data,size); } - }; - - template - class assignment_string_node exprtk_final - : public binary_node , - public string_base_node, - public range_interface - { - public: - - typedef expression_node * expression_ptr; - typedef stringvar_node * strvar_node_ptr; - typedef string_base_node* str_base_ptr; - typedef range_pack range_t; - typedef range_t* range_ptr; - typedef range_interface irange_t; - typedef irange_t* irange_ptr; - - assignment_string_node(const operator_type& opr, - expression_ptr branch0, - expression_ptr branch1) - : binary_node(opr, branch0, branch1), - initialised_(false), - str0_base_ptr_ (0), - str1_base_ptr_ (0), - str0_node_ptr_ (0), - str1_range_ptr_(0) - { - if (is_string_node(binary_node::branch_[0].first)) - { - str0_node_ptr_ = static_cast(binary_node::branch_[0].first); - - str0_base_ptr_ = dynamic_cast(binary_node::branch_[0].first); - } - - if (is_generally_string_node(binary_node::branch_[1].first)) - { - str1_base_ptr_ = dynamic_cast(binary_node::branch_[1].first); - - if (0 == str1_base_ptr_) - return; - - irange_ptr range = dynamic_cast(binary_node::branch_[1].first); - - if (0 == range) - return; - - str1_range_ptr_ = &(range->range_ref()); - } - - initialised_ = str0_base_ptr_ && - str1_base_ptr_ && - str0_node_ptr_ && - str1_range_ptr_ ; - } - - inline T value() const - { - if (initialised_) - { - assert(binary_node::branch_[0].first); - assert(binary_node::branch_[1].first); - - binary_node::branch_[1].first->value(); - - std::size_t r0 = 0; - std::size_t r1 = 0; - - const range_t& range = (*str1_range_ptr_); - - if (range(r0, r1, str1_base_ptr_->size())) - { - AssignmentProcess::execute(str0_node_ptr_->ref(), - str1_base_ptr_->base() + r0, - (r1 - r0) + 1); - - binary_node::branch_[0].first->value(); - } - } - - return std::numeric_limits::quiet_NaN(); - } - - std::string str() const - { - return str0_node_ptr_->str(); - } - - char_cptr base() const - { - return str0_node_ptr_->base(); - } - - std::size_t size() const - { - return str0_node_ptr_->size(); - } - - range_t& range_ref() - { - return str0_node_ptr_->range_ref(); - } - - const range_t& range_ref() const - { - return str0_node_ptr_->range_ref(); - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_strass; - } - - private: - - bool initialised_; - str_base_ptr str0_base_ptr_; - str_base_ptr str1_base_ptr_; - strvar_node_ptr str0_node_ptr_; - range_ptr str1_range_ptr_; - }; - - template - class assignment_string_range_node exprtk_final - : public binary_node , - public string_base_node, - public range_interface - { - public: - - typedef expression_node * expression_ptr; - typedef stringvar_node * strvar_node_ptr; - typedef string_range_node* str_rng_node_ptr; - typedef string_base_node * str_base_ptr; - typedef range_pack range_t; - typedef range_t* range_ptr; - typedef range_interface irange_t; - typedef irange_t* irange_ptr; - - assignment_string_range_node(const operator_type& opr, - expression_ptr branch0, - expression_ptr branch1) - : binary_node(opr, branch0, branch1), - initialised_(false), - str0_base_ptr_ (0), - str1_base_ptr_ (0), - str0_rng_node_ptr_ (0), - str0_range_ptr_ (0), - str1_range_ptr_ (0) - { - if (is_string_range_node(binary_node::branch_[0].first)) - { - str0_rng_node_ptr_ = static_cast(binary_node::branch_[0].first); - - str0_base_ptr_ = dynamic_cast(binary_node::branch_[0].first); - - irange_ptr range = dynamic_cast(binary_node::branch_[0].first); - - if (0 == range) - return; - - str0_range_ptr_ = &(range->range_ref()); - } - - if (is_generally_string_node(binary_node::branch_[1].first)) - { - str1_base_ptr_ = dynamic_cast(binary_node::branch_[1].first); - - if (0 == str1_base_ptr_) - return; - - irange_ptr range = dynamic_cast(binary_node::branch_[1].first); - - if (0 == range) - return; - - str1_range_ptr_ = &(range->range_ref()); - } - - initialised_ = str0_base_ptr_ && - str1_base_ptr_ && - str0_rng_node_ptr_ && - str0_range_ptr_ && - str1_range_ptr_ ; - } - - inline T value() const - { - if (initialised_) - { - assert(binary_node::branch_[0].first); - assert(binary_node::branch_[1].first); - - binary_node::branch_[0].first->value(); - binary_node::branch_[1].first->value(); - - std::size_t s0_r0 = 0; - std::size_t s0_r1 = 0; - - std::size_t s1_r0 = 0; - std::size_t s1_r1 = 0; - - const range_t& range0 = (*str0_range_ptr_); - const range_t& range1 = (*str1_range_ptr_); - - if ( - range0(s0_r0, s0_r1, str0_base_ptr_->size()) && - range1(s1_r0, s1_r1, str1_base_ptr_->size()) - ) - { - const std::size_t size = std::min((s0_r1 - s0_r0), (s1_r1 - s1_r0)) + 1; - - std::copy(str1_base_ptr_->base() + s1_r0, - str1_base_ptr_->base() + s1_r0 + size, - const_cast(base() + s0_r0)); - } - } - - return std::numeric_limits::quiet_NaN(); - } - - std::string str() const - { - return str0_base_ptr_->str(); - } - - char_cptr base() const - { - return str0_base_ptr_->base(); - } - - std::size_t size() const - { - return str0_base_ptr_->size(); - } - - range_t& range_ref() - { - return str0_rng_node_ptr_->range_ref(); - } - - const range_t& range_ref() const - { - return str0_rng_node_ptr_->range_ref(); - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_strass; - } - - private: - - bool initialised_; - str_base_ptr str0_base_ptr_; - str_base_ptr str1_base_ptr_; - str_rng_node_ptr str0_rng_node_ptr_; - range_ptr str0_range_ptr_; - range_ptr str1_range_ptr_; - }; - - template - class conditional_string_node exprtk_final - : public trinary_node , - public string_base_node, - public range_interface - { - public: - - typedef expression_node * expression_ptr; - typedef string_base_node* str_base_ptr; - typedef range_pack range_t; - typedef range_t* range_ptr; - typedef range_interface irange_t; - typedef irange_t* irange_ptr; - - conditional_string_node(expression_ptr condition, - expression_ptr consequent, - expression_ptr alternative) - : trinary_node(details::e_default,consequent,alternative,condition), - initialised_(false), - str0_base_ptr_ (0), - str1_base_ptr_ (0), - str0_range_ptr_(0), - str1_range_ptr_(0), - condition_ (condition), - consequent_ (consequent), - alternative_(alternative) - { - range_.n0_c = std::make_pair(true,0); - range_.n1_c = std::make_pair(true,0); - - range_.cache.first = range_.n0_c.second; - range_.cache.second = range_.n1_c.second; - - if (is_generally_string_node(trinary_node::branch_[0].first)) - { - str0_base_ptr_ = dynamic_cast(trinary_node::branch_[0].first); - - if (0 == str0_base_ptr_) - return; - - str0_range_ptr_ = dynamic_cast(trinary_node::branch_[0].first); - - if (0 == str0_range_ptr_) - return; - } - - if (is_generally_string_node(trinary_node::branch_[1].first)) - { - str1_base_ptr_ = dynamic_cast(trinary_node::branch_[1].first); - - if (0 == str1_base_ptr_) - return; - - str1_range_ptr_ = dynamic_cast(trinary_node::branch_[1].first); - - if (0 == str1_range_ptr_) - return; - } - - initialised_ = str0_base_ptr_ && - str1_base_ptr_ && - str0_range_ptr_ && - str1_range_ptr_ ; - - } - - inline T value() const - { - if (initialised_) - { - assert(condition_ ); - assert(consequent_ ); - assert(alternative_); - - std::size_t r0 = 0; - std::size_t r1 = 0; - - if (is_true(condition_)) - { - consequent_->value(); - - const range_t& range = str0_range_ptr_->range_ref(); - - if (range(r0, r1, str0_base_ptr_->size())) - { - const std::size_t size = (r1 - r0) + 1; - - value_.assign(str0_base_ptr_->base() + r0, size); - - range_.n1_c.second = value_.size() - 1; - range_.cache.second = range_.n1_c.second; - - return T(1); - } - } - else - { - alternative_->value(); - - const range_t& range = str1_range_ptr_->range_ref(); - - if (range(r0, r1, str1_base_ptr_->size())) - { - const std::size_t size = (r1 - r0) + 1; - - value_.assign(str1_base_ptr_->base() + r0, size); - - range_.n1_c.second = value_.size() - 1; - range_.cache.second = range_.n1_c.second; - - return T(0); - } - } - } - - return std::numeric_limits::quiet_NaN(); - } - - std::string str() const - { - return value_; - } - - char_cptr base() const - { - return &value_[0]; - } - - std::size_t size() const - { - return value_.size(); - } - - range_t& range_ref() - { - return range_; - } - - const range_t& range_ref() const - { - return range_; - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_strcondition; - } - - private: - - bool initialised_; - str_base_ptr str0_base_ptr_; - str_base_ptr str1_base_ptr_; - irange_ptr str0_range_ptr_; - irange_ptr str1_range_ptr_; - mutable range_t range_; - mutable std::string value_; - - expression_ptr condition_; - expression_ptr consequent_; - expression_ptr alternative_; - }; - - template - class cons_conditional_str_node exprtk_final - : public binary_node , - public string_base_node, - public range_interface - { - public: - - typedef expression_node * expression_ptr; - typedef string_base_node* str_base_ptr; - typedef range_pack range_t; - typedef range_t* range_ptr; - typedef range_interface irange_t; - typedef irange_t* irange_ptr; - - cons_conditional_str_node(expression_ptr condition, - expression_ptr consequent) - : binary_node(details::e_default, consequent, condition), - initialised_(false), - str0_base_ptr_ (0), - str0_range_ptr_(0), - condition_ (condition), - consequent_(consequent) - { - range_.n0_c = std::make_pair(true,0); - range_.n1_c = std::make_pair(true,0); - - range_.cache.first = range_.n0_c.second; - range_.cache.second = range_.n1_c.second; - - if (is_generally_string_node(binary_node::branch_[0].first)) - { - str0_base_ptr_ = dynamic_cast(binary_node::branch_[0].first); - - if (0 == str0_base_ptr_) - return; - - str0_range_ptr_ = dynamic_cast(binary_node::branch_[0].first); - - if (0 == str0_range_ptr_) - return; - } - - initialised_ = str0_base_ptr_ && str0_range_ptr_ ; - } - - inline T value() const - { - if (initialised_) - { - assert(condition_ ); - assert(consequent_); - - if (is_true(condition_)) - { - consequent_->value(); - - const range_t& range = str0_range_ptr_->range_ref(); - - std::size_t r0 = 0; - std::size_t r1 = 0; - - if (range(r0, r1, str0_base_ptr_->size())) - { - const std::size_t size = (r1 - r0) + 1; - - value_.assign(str0_base_ptr_->base() + r0, size); - - range_.n1_c.second = value_.size() - 1; - range_.cache.second = range_.n1_c.second; - - return T(1); - } - } - } - - return std::numeric_limits::quiet_NaN(); - } - - std::string str() const - { - return value_; - } - - char_cptr base() const - { - return &value_[0]; - } - - std::size_t size() const - { - return value_.size(); - } - - range_t& range_ref() - { - return range_; - } - - const range_t& range_ref() const - { - return range_; - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_strccondition; - } - - private: - - bool initialised_; - str_base_ptr str0_base_ptr_; - irange_ptr str0_range_ptr_; - mutable range_t range_; - mutable std::string value_; - - expression_ptr condition_; - expression_ptr consequent_; - }; - - template - class str_vararg_node exprtk_final - : public expression_node , - public string_base_node, - public range_interface - { - public: - - typedef expression_node * expression_ptr; - typedef string_base_node* str_base_ptr; - typedef range_pack range_t; - typedef range_t* range_ptr; - typedef range_interface irange_t; - typedef irange_t* irange_ptr; - typedef std::pair branch_t; - - template class Sequence> - explicit str_vararg_node(const Sequence& arg_list) - : initialised_(false), - str_base_ptr_ (0), - str_range_ptr_(0) - { - construct_branch_pair(final_node_, const_cast(arg_list.back())); - - if (0 == final_node_.first) - return; - else if (!is_generally_string_node(final_node_.first)) - return; - - str_base_ptr_ = dynamic_cast(final_node_.first); - - if (0 == str_base_ptr_) - return; - - str_range_ptr_ = dynamic_cast(final_node_.first); - - if (0 == str_range_ptr_) - return; - - initialised_ = str_base_ptr_ && str_range_ptr_; - - if (arg_list.size() > 1) - { - const std::size_t arg_list_size = arg_list.size() - 1; - - arg_list_.resize(arg_list_size); - - for (std::size_t i = 0; i < arg_list_size; ++i) - { - if (arg_list[i]) - { - construct_branch_pair(arg_list_[i], arg_list[i]); - } - else - { - arg_list_.clear(); - return; - } - } - } - } - - inline T value() const - { - if (!arg_list_.empty()) - { - VarArgFunction::process(arg_list_); - } - - final_node_.first->value(); - - return std::numeric_limits::quiet_NaN(); - } - - std::string str() const - { - return str_base_ptr_->str(); - } - - char_cptr base() const - { - return str_base_ptr_->base(); - } - - std::size_t size() const - { - return str_base_ptr_->size(); - } - - range_t& range_ref() - { - return str_range_ptr_->range_ref(); - } - - const range_t& range_ref() const - { - return str_range_ptr_->range_ref(); - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_stringvararg; - } - - void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) - { - expression_node::ndb_t::collect(final_node_ , node_delete_list); - expression_node::ndb_t::collect(arg_list_ , node_delete_list); - } - - std::size_t node_depth() const - { - return std::max( - expression_node::ndb_t::compute_node_depth(final_node_), - expression_node::ndb_t::compute_node_depth(arg_list_ )); - } - - private: - - bool initialised_; - branch_t final_node_; - str_base_ptr str_base_ptr_; - irange_ptr str_range_ptr_; - std::vector arg_list_; - }; - #endif - - template - inline T axn(const T a, const T x) - { - // a*x^n - return a * exprtk::details::numeric::fast_exp::result(x); - } - - template - inline T axnb(const T a, const T x, const T b) - { - // a*x^n+b - return a * exprtk::details::numeric::fast_exp::result(x) + b; - } - - template - struct sf_base - { - typedef typename details::functor_t::Type Type; - typedef typename details::functor_t functor_t; - typedef typename functor_t::qfunc_t quaternary_functor_t; - typedef typename functor_t::tfunc_t trinary_functor_t; - typedef typename functor_t::bfunc_t binary_functor_t; - typedef typename functor_t::ufunc_t unary_functor_t; - }; - - #define define_sfop3(NN,OP0,OP1) \ - template \ - struct sf##NN##_op : public sf_base \ - { \ - typedef typename sf_base::Type const Type; \ - static inline T process(Type x, Type y, Type z) \ - { \ - return (OP0); \ - } \ - static inline std::string id() \ - { \ - return (OP1); \ - } \ - }; \ - - define_sfop3(00,(x + y) / z ,"(t+t)/t") - define_sfop3(01,(x + y) * z ,"(t+t)*t") - define_sfop3(02,(x + y) - z ,"(t+t)-t") - define_sfop3(03,(x + y) + z ,"(t+t)+t") - define_sfop3(04,(x - y) + z ,"(t-t)+t") - define_sfop3(05,(x - y) / z ,"(t-t)/t") - define_sfop3(06,(x - y) * z ,"(t-t)*t") - define_sfop3(07,(x * y) + z ,"(t*t)+t") - define_sfop3(08,(x * y) - z ,"(t*t)-t") - define_sfop3(09,(x * y) / z ,"(t*t)/t") - define_sfop3(10,(x * y) * z ,"(t*t)*t") - define_sfop3(11,(x / y) + z ,"(t/t)+t") - define_sfop3(12,(x / y) - z ,"(t/t)-t") - define_sfop3(13,(x / y) / z ,"(t/t)/t") - define_sfop3(14,(x / y) * z ,"(t/t)*t") - define_sfop3(15,x / (y + z) ,"t/(t+t)") - define_sfop3(16,x / (y - z) ,"t/(t-t)") - define_sfop3(17,x / (y * z) ,"t/(t*t)") - define_sfop3(18,x / (y / z) ,"t/(t/t)") - define_sfop3(19,x * (y + z) ,"t*(t+t)") - define_sfop3(20,x * (y - z) ,"t*(t-t)") - define_sfop3(21,x * (y * z) ,"t*(t*t)") - define_sfop3(22,x * (y / z) ,"t*(t/t)") - define_sfop3(23,x - (y + z) ,"t-(t+t)") - define_sfop3(24,x - (y - z) ,"t-(t-t)") - define_sfop3(25,x - (y / z) ,"t-(t/t)") - define_sfop3(26,x - (y * z) ,"t-(t*t)") - define_sfop3(27,x + (y * z) ,"t+(t*t)") - define_sfop3(28,x + (y / z) ,"t+(t/t)") - define_sfop3(29,x + (y + z) ,"t+(t+t)") - define_sfop3(30,x + (y - z) ,"t+(t-t)") - define_sfop3(31,(axnb(x,y,z))," ") - define_sfop3(32,(axnb(x,y,z))," ") - define_sfop3(33,(axnb(x,y,z))," ") - define_sfop3(34,(axnb(x,y,z))," ") - define_sfop3(35,(axnb(x,y,z))," ") - define_sfop3(36,(axnb(x,y,z))," ") - define_sfop3(37,(axnb(x,y,z))," ") - define_sfop3(38,(axnb(x,y,z))," ") - define_sfop3(39,x * numeric::log(y) + z,"") - define_sfop3(40,x * numeric::log(y) - z,"") - define_sfop3(41,x * numeric::log10(y) + z,"") - define_sfop3(42,x * numeric::log10(y) - z,"") - define_sfop3(43,x * numeric::sin(y) + z ,"") - define_sfop3(44,x * numeric::sin(y) - z ,"") - define_sfop3(45,x * numeric::cos(y) + z ,"") - define_sfop3(46,x * numeric::cos(y) - z ,"") - define_sfop3(47,details::is_true(x) ? y : z,"") - - #define define_sfop4(NN,OP0,OP1) \ - template \ - struct sf##NN##_op : public sf_base \ - { \ - typedef typename sf_base::Type const Type; \ - static inline T process(Type x, Type y, Type z, Type w) \ - { \ - return (OP0); \ - } \ - static inline std::string id() \ - { \ - return (OP1); \ - } \ - }; \ - - define_sfop4(48,(x + ((y + z) / w)),"t+((t+t)/t)") - define_sfop4(49,(x + ((y + z) * w)),"t+((t+t)*t)") - define_sfop4(50,(x + ((y - z) / w)),"t+((t-t)/t)") - define_sfop4(51,(x + ((y - z) * w)),"t+((t-t)*t)") - define_sfop4(52,(x + ((y * z) / w)),"t+((t*t)/t)") - define_sfop4(53,(x + ((y * z) * w)),"t+((t*t)*t)") - define_sfop4(54,(x + ((y / z) + w)),"t+((t/t)+t)") - define_sfop4(55,(x + ((y / z) / w)),"t+((t/t)/t)") - define_sfop4(56,(x + ((y / z) * w)),"t+((t/t)*t)") - define_sfop4(57,(x - ((y + z) / w)),"t-((t+t)/t)") - define_sfop4(58,(x - ((y + z) * w)),"t-((t+t)*t)") - define_sfop4(59,(x - ((y - z) / w)),"t-((t-t)/t)") - define_sfop4(60,(x - ((y - z) * w)),"t-((t-t)*t)") - define_sfop4(61,(x - ((y * z) / w)),"t-((t*t)/t)") - define_sfop4(62,(x - ((y * z) * w)),"t-((t*t)*t)") - define_sfop4(63,(x - ((y / z) / w)),"t-((t/t)/t)") - define_sfop4(64,(x - ((y / z) * w)),"t-((t/t)*t)") - define_sfop4(65,(((x + y) * z) - w),"((t+t)*t)-t") - define_sfop4(66,(((x - y) * z) - w),"((t-t)*t)-t") - define_sfop4(67,(((x * y) * z) - w),"((t*t)*t)-t") - define_sfop4(68,(((x / y) * z) - w),"((t/t)*t)-t") - define_sfop4(69,(((x + y) / z) - w),"((t+t)/t)-t") - define_sfop4(70,(((x - y) / z) - w),"((t-t)/t)-t") - define_sfop4(71,(((x * y) / z) - w),"((t*t)/t)-t") - define_sfop4(72,(((x / y) / z) - w),"((t/t)/t)-t") - define_sfop4(73,((x * y) + (z * w)),"(t*t)+(t*t)") - define_sfop4(74,((x * y) - (z * w)),"(t*t)-(t*t)") - define_sfop4(75,((x * y) + (z / w)),"(t*t)+(t/t)") - define_sfop4(76,((x * y) - (z / w)),"(t*t)-(t/t)") - define_sfop4(77,((x / y) + (z / w)),"(t/t)+(t/t)") - define_sfop4(78,((x / y) - (z / w)),"(t/t)-(t/t)") - define_sfop4(79,((x / y) - (z * w)),"(t/t)-(t*t)") - define_sfop4(80,(x / (y + (z * w))),"t/(t+(t*t))") - define_sfop4(81,(x / (y - (z * w))),"t/(t-(t*t))") - define_sfop4(82,(x * (y + (z * w))),"t*(t+(t*t))") - define_sfop4(83,(x * (y - (z * w))),"t*(t-(t*t))") - - define_sfop4(84,(axn(x,y) + axn(z,w)),"") - define_sfop4(85,(axn(x,y) + axn(z,w)),"") - define_sfop4(86,(axn(x,y) + axn(z,w)),"") - define_sfop4(87,(axn(x,y) + axn(z,w)),"") - define_sfop4(88,(axn(x,y) + axn(z,w)),"") - define_sfop4(89,(axn(x,y) + axn(z,w)),"") - define_sfop4(90,(axn(x,y) + axn(z,w)),"") - define_sfop4(91,(axn(x,y) + axn(z,w)),"") - define_sfop4(92,((details::is_true(x) && details::is_true(y)) ? z : w),"") - define_sfop4(93,((details::is_true(x) || details::is_true(y)) ? z : w),"") - define_sfop4(94,((x < y) ? z : w),"") - define_sfop4(95,((x <= y) ? z : w),"") - define_sfop4(96,((x > y) ? z : w),"") - define_sfop4(97,((x >= y) ? z : w),"") - define_sfop4(98,(details::is_true(numeric::equal(x,y)) ? z : w),"") - define_sfop4(99,(x * numeric::sin(y) + z * numeric::cos(w)),"") - - define_sfop4(ext00,((x + y) - (z * w)),"(t+t)-(t*t)") - define_sfop4(ext01,((x + y) - (z / w)),"(t+t)-(t/t)") - define_sfop4(ext02,((x + y) + (z * w)),"(t+t)+(t*t)") - define_sfop4(ext03,((x + y) + (z / w)),"(t+t)+(t/t)") - define_sfop4(ext04,((x - y) + (z * w)),"(t-t)+(t*t)") - define_sfop4(ext05,((x - y) + (z / w)),"(t-t)+(t/t)") - define_sfop4(ext06,((x - y) - (z * w)),"(t-t)-(t*t)") - define_sfop4(ext07,((x - y) - (z / w)),"(t-t)-(t/t)") - define_sfop4(ext08,((x + y) - (z - w)),"(t+t)-(t-t)") - define_sfop4(ext09,((x + y) + (z - w)),"(t+t)+(t-t)") - define_sfop4(ext10,((x + y) + (z + w)),"(t+t)+(t+t)") - define_sfop4(ext11,((x + y) * (z - w)),"(t+t)*(t-t)") - define_sfop4(ext12,((x + y) / (z - w)),"(t+t)/(t-t)") - define_sfop4(ext13,((x - y) - (z + w)),"(t-t)-(t+t)") - define_sfop4(ext14,((x - y) + (z + w)),"(t-t)+(t+t)") - define_sfop4(ext15,((x - y) * (z + w)),"(t-t)*(t+t)") - define_sfop4(ext16,((x - y) / (z + w)),"(t-t)/(t+t)") - define_sfop4(ext17,((x * y) - (z + w)),"(t*t)-(t+t)") - define_sfop4(ext18,((x / y) - (z + w)),"(t/t)-(t+t)") - define_sfop4(ext19,((x * y) + (z + w)),"(t*t)+(t+t)") - define_sfop4(ext20,((x / y) + (z + w)),"(t/t)+(t+t)") - define_sfop4(ext21,((x * y) + (z - w)),"(t*t)+(t-t)") - define_sfop4(ext22,((x / y) + (z - w)),"(t/t)+(t-t)") - define_sfop4(ext23,((x * y) - (z - w)),"(t*t)-(t-t)") - define_sfop4(ext24,((x / y) - (z - w)),"(t/t)-(t-t)") - define_sfop4(ext25,((x + y) * (z * w)),"(t+t)*(t*t)") - define_sfop4(ext26,((x + y) * (z / w)),"(t+t)*(t/t)") - define_sfop4(ext27,((x + y) / (z * w)),"(t+t)/(t*t)") - define_sfop4(ext28,((x + y) / (z / w)),"(t+t)/(t/t)") - define_sfop4(ext29,((x - y) / (z * w)),"(t-t)/(t*t)") - define_sfop4(ext30,((x - y) / (z / w)),"(t-t)/(t/t)") - define_sfop4(ext31,((x - y) * (z * w)),"(t-t)*(t*t)") - define_sfop4(ext32,((x - y) * (z / w)),"(t-t)*(t/t)") - define_sfop4(ext33,((x * y) * (z + w)),"(t*t)*(t+t)") - define_sfop4(ext34,((x / y) * (z + w)),"(t/t)*(t+t)") - define_sfop4(ext35,((x * y) / (z + w)),"(t*t)/(t+t)") - define_sfop4(ext36,((x / y) / (z + w)),"(t/t)/(t+t)") - define_sfop4(ext37,((x * y) / (z - w)),"(t*t)/(t-t)") - define_sfop4(ext38,((x / y) / (z - w)),"(t/t)/(t-t)") - define_sfop4(ext39,((x * y) * (z - w)),"(t*t)*(t-t)") - define_sfop4(ext40,((x * y) / (z * w)),"(t*t)/(t*t)") - define_sfop4(ext41,((x / y) * (z / w)),"(t/t)*(t/t)") - define_sfop4(ext42,((x / y) * (z - w)),"(t/t)*(t-t)") - define_sfop4(ext43,((x * y) * (z * w)),"(t*t)*(t*t)") - define_sfop4(ext44,(x + (y * (z / w))),"t+(t*(t/t))") - define_sfop4(ext45,(x - (y * (z / w))),"t-(t*(t/t))") - define_sfop4(ext46,(x + (y / (z * w))),"t+(t/(t*t))") - define_sfop4(ext47,(x - (y / (z * w))),"t-(t/(t*t))") - define_sfop4(ext48,(((x - y) - z) * w),"((t-t)-t)*t") - define_sfop4(ext49,(((x - y) - z) / w),"((t-t)-t)/t") - define_sfop4(ext50,(((x - y) + z) * w),"((t-t)+t)*t") - define_sfop4(ext51,(((x - y) + z) / w),"((t-t)+t)/t") - define_sfop4(ext52,((x + (y - z)) * w),"(t+(t-t))*t") - define_sfop4(ext53,((x + (y - z)) / w),"(t+(t-t))/t") - define_sfop4(ext54,((x + y) / (z + w)),"(t+t)/(t+t)") - define_sfop4(ext55,((x - y) / (z - w)),"(t-t)/(t-t)") - define_sfop4(ext56,((x + y) * (z + w)),"(t+t)*(t+t)") - define_sfop4(ext57,((x - y) * (z - w)),"(t-t)*(t-t)") - define_sfop4(ext58,((x - y) + (z - w)),"(t-t)+(t-t)") - define_sfop4(ext59,((x - y) - (z - w)),"(t-t)-(t-t)") - define_sfop4(ext60,((x / y) + (z * w)),"(t/t)+(t*t)") - define_sfop4(ext61,(((x * y) * z) / w),"((t*t)*t)/t") - - #undef define_sfop3 - #undef define_sfop4 - - template - class sf3_node exprtk_final : public trinary_node - { - public: - - typedef expression_node* expression_ptr; - - sf3_node(const operator_type& opr, - expression_ptr branch0, - expression_ptr branch1, - expression_ptr branch2) - : trinary_node(opr, branch0, branch1, branch2) - {} - - inline T value() const - { - assert(trinary_node::branch_[0].first); - assert(trinary_node::branch_[1].first); - assert(trinary_node::branch_[2].first); - - const T x = trinary_node::branch_[0].first->value(); - const T y = trinary_node::branch_[1].first->value(); - const T z = trinary_node::branch_[2].first->value(); - - return SpecialFunction::process(x, y, z); - } - }; - - template - class sf4_node exprtk_final : public quaternary_node - { - public: - - typedef expression_node* expression_ptr; - - sf4_node(const operator_type& opr, - expression_ptr branch0, - expression_ptr branch1, - expression_ptr branch2, - expression_ptr branch3) - : quaternary_node(opr, branch0, branch1, branch2, branch3) - {} - - inline T value() const - { - assert(quaternary_node::branch_[0].first); - assert(quaternary_node::branch_[1].first); - assert(quaternary_node::branch_[2].first); - assert(quaternary_node::branch_[3].first); - - const T x = quaternary_node::branch_[0].first->value(); - const T y = quaternary_node::branch_[1].first->value(); - const T z = quaternary_node::branch_[2].first->value(); - const T w = quaternary_node::branch_[3].first->value(); - - return SpecialFunction::process(x, y, z, w); - } - }; - - template - class sf3_var_node exprtk_final : public expression_node - { - public: - - typedef expression_node* expression_ptr; - - sf3_var_node(const T& v0, const T& v1, const T& v2) - : v0_(v0), - v1_(v1), - v2_(v2) - {} - - inline T value() const - { - return SpecialFunction::process(v0_, v1_, v2_); - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_trinary; - } - - private: - - sf3_var_node(sf3_var_node&); - sf3_var_node& operator=(sf3_var_node&); - - const T& v0_; - const T& v1_; - const T& v2_; - }; - - template - class sf4_var_node exprtk_final : public expression_node - { - public: - - typedef expression_node* expression_ptr; - - sf4_var_node(const T& v0, const T& v1, const T& v2, const T& v3) - : v0_(v0), - v1_(v1), - v2_(v2), - v3_(v3) - {} - - inline T value() const - { - return SpecialFunction::process(v0_, v1_, v2_, v3_); - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_trinary; - } - - private: - - sf4_var_node(sf4_var_node&); - sf4_var_node& operator=(sf4_var_node&); - - const T& v0_; - const T& v1_; - const T& v2_; - const T& v3_; - }; - - template - class vararg_node exprtk_final : public expression_node - { - public: - - typedef expression_node* expression_ptr; - typedef std::pair branch_t; - - template class Sequence> - explicit vararg_node(const Sequence& arg_list) - { - arg_list_.resize(arg_list.size()); - - for (std::size_t i = 0; i < arg_list.size(); ++i) - { - if (arg_list[i]) - { - construct_branch_pair(arg_list_[i],arg_list[i]); - } - else - { - arg_list_.clear(); - return; - } - } - } - - inline T value() const - { - return VarArgFunction::process(arg_list_); - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_vararg; - } - - void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) - { - expression_node::ndb_t::collect(arg_list_, node_delete_list); - } - - std::size_t node_depth() const - { - return expression_node::ndb_t::compute_node_depth(arg_list_); - } - - private: - - std::vector arg_list_; - }; - - template - class vararg_varnode exprtk_final : public expression_node - { - public: - - typedef expression_node* expression_ptr; - - template class Sequence> - explicit vararg_varnode(const Sequence& arg_list) - { - arg_list_.resize(arg_list.size()); - - for (std::size_t i = 0; i < arg_list.size(); ++i) - { - if (arg_list[i] && is_variable_node(arg_list[i])) - { - variable_node* var_node_ptr = static_cast*>(arg_list[i]); - arg_list_[i] = (&var_node_ptr->ref()); - } - else - { - arg_list_.clear(); - return; - } - } - } - - inline T value() const - { - if (!arg_list_.empty()) - return VarArgFunction::process(arg_list_); - else - return std::numeric_limits::quiet_NaN(); - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_vararg; - } - - private: - - std::vector arg_list_; - }; - - template - class vectorize_node exprtk_final : public expression_node - { - public: - - typedef expression_node* expression_ptr; - typedef std::pair branch_t; - - explicit vectorize_node(const expression_ptr v) - : ivec_ptr_(0) - { - construct_branch_pair(v_, v); - - if (is_ivector_node(v_.first)) - { - ivec_ptr_ = dynamic_cast*>(v_.first); - } - else - ivec_ptr_ = 0; - } - - inline T value() const - { - if (ivec_ptr_) - { - assert(v_.first); - - v_.first->value(); - - return VecFunction::process(ivec_ptr_); - } - else - return std::numeric_limits::quiet_NaN(); - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_vecfunc; - } - - void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) - { - expression_node::ndb_t::collect(v_, node_delete_list); - } - - std::size_t node_depth() const - { - return expression_node::ndb_t::compute_node_depth(v_); - } - - private: - - vector_interface* ivec_ptr_; - branch_t v_; - }; - - template - class assignment_node exprtk_final : public binary_node - { - public: - - typedef expression_node* expression_ptr; - - assignment_node(const operator_type& opr, - expression_ptr branch0, - expression_ptr branch1) - : binary_node(opr, branch0, branch1), - var_node_ptr_(0) - { - if (is_variable_node(binary_node::branch_[0].first)) - { - var_node_ptr_ = static_cast*>(binary_node::branch_[0].first); - } - } - - inline T value() const - { - if (var_node_ptr_) - { - assert(binary_node::branch_[1].first); - - T& result = var_node_ptr_->ref(); - - result = binary_node::branch_[1].first->value(); - - return result; - } - else - return std::numeric_limits::quiet_NaN(); - } - - private: - - variable_node* var_node_ptr_; - }; - - template - class assignment_vec_elem_node exprtk_final : public binary_node - { - public: - - typedef expression_node* expression_ptr; - - assignment_vec_elem_node(const operator_type& opr, - expression_ptr branch0, - expression_ptr branch1) - : binary_node(opr, branch0, branch1), - vec_node_ptr_(0) - { - if (is_vector_elem_node(binary_node::branch_[0].first)) - { - vec_node_ptr_ = static_cast*>(binary_node::branch_[0].first); - } - } - - inline T value() const - { - if (vec_node_ptr_) - { - assert(binary_node::branch_[1].first); - - T& result = vec_node_ptr_->ref(); - - result = binary_node::branch_[1].first->value(); - - return result; - } - else - return std::numeric_limits::quiet_NaN(); - } - - private: - - vector_elem_node* vec_node_ptr_; - }; - - template - class assignment_rebasevec_elem_node exprtk_final : public binary_node - { - public: - - typedef expression_node* expression_ptr; - - assignment_rebasevec_elem_node(const operator_type& opr, - expression_ptr branch0, - expression_ptr branch1) - : binary_node(opr, branch0, branch1), - rbvec_node_ptr_(0) - { - if (is_rebasevector_elem_node(binary_node::branch_[0].first)) - { - rbvec_node_ptr_ = static_cast*>(binary_node::branch_[0].first); - } - } - - inline T value() const - { - if (rbvec_node_ptr_) - { - assert(binary_node::branch_[1].first); - - T& result = rbvec_node_ptr_->ref(); - - result = binary_node::branch_[1].first->value(); - - return result; - } - else - return std::numeric_limits::quiet_NaN(); - } - - private: - - rebasevector_elem_node* rbvec_node_ptr_; - }; - - template - class assignment_rebasevec_celem_node exprtk_final : public binary_node - { - public: - - typedef expression_node* expression_ptr; - - assignment_rebasevec_celem_node(const operator_type& opr, - expression_ptr branch0, - expression_ptr branch1) - : binary_node(opr, branch0, branch1), - rbvec_node_ptr_(0) - { - if (is_rebasevector_celem_node(binary_node::branch_[0].first)) - { - rbvec_node_ptr_ = static_cast*>(binary_node::branch_[0].first); - } - } - - inline T value() const - { - if (rbvec_node_ptr_) - { - assert(binary_node::branch_[1].first); - - T& result = rbvec_node_ptr_->ref(); - - result = binary_node::branch_[1].first->value(); - - return result; - } - else - return std::numeric_limits::quiet_NaN(); - } - - private: - - rebasevector_celem_node* rbvec_node_ptr_; - }; - - template - class assignment_vec_node exprtk_final - : public binary_node , - public vector_interface - { - public: - - typedef expression_node* expression_ptr; - typedef vector_node* vector_node_ptr; - typedef vec_data_store vds_t; - - assignment_vec_node(const operator_type& opr, - expression_ptr branch0, - expression_ptr branch1) - : binary_node(opr, branch0, branch1), - vec_node_ptr_(0) - { - if (is_vector_node(binary_node::branch_[0].first)) - { - vec_node_ptr_ = static_cast*>(binary_node::branch_[0].first); - vds() = vec_node_ptr_->vds(); - } - } - - inline T value() const - { - if (vec_node_ptr_) - { - assert(binary_node::branch_[1].first); - - const T v = binary_node::branch_[1].first->value(); - - T* vec = vds().data(); - - loop_unroll::details lud(size()); - const T* upper_bound = vec + lud.upper_bound; - - while (vec < upper_bound) - { - #define exprtk_loop(N) \ - vec[N] = v; \ - - exprtk_loop( 0) exprtk_loop( 1) - exprtk_loop( 2) exprtk_loop( 3) - #ifndef exprtk_disable_superscalar_unroll - exprtk_loop( 4) exprtk_loop( 5) - exprtk_loop( 6) exprtk_loop( 7) - exprtk_loop( 8) exprtk_loop( 9) - exprtk_loop(10) exprtk_loop(11) - exprtk_loop(12) exprtk_loop(13) - exprtk_loop(14) exprtk_loop(15) - #endif - - vec += lud.batch_size; - } - - exprtk_disable_fallthrough_begin - switch (lud.remainder) - { - #define case_stmt(N) \ - case N : *vec++ = v; \ - - #ifndef exprtk_disable_superscalar_unroll - case_stmt(15) case_stmt(14) - case_stmt(13) case_stmt(12) - case_stmt(11) case_stmt(10) - case_stmt( 9) case_stmt( 8) - case_stmt( 7) case_stmt( 6) - case_stmt( 5) case_stmt( 4) - #endif - case_stmt( 3) case_stmt( 2) - case_stmt( 1) - } - exprtk_disable_fallthrough_end - - #undef exprtk_loop - #undef case_stmt - - return vec_node_ptr_->value(); - } - else - return std::numeric_limits::quiet_NaN(); - } - - vector_node_ptr vec() const - { - return vec_node_ptr_; - } - - vector_node_ptr vec() - { - return vec_node_ptr_; - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_vecvalass; - } - - std::size_t size() const - { - return vds().size(); - } - - vds_t& vds() - { - return vds_; - } - - const vds_t& vds() const - { - return vds_; - } - - private: - - vector_node* vec_node_ptr_; - vds_t vds_; - }; - - template - class assignment_vecvec_node exprtk_final - : public binary_node , - public vector_interface - { - public: - - typedef expression_node* expression_ptr; - typedef vector_node* vector_node_ptr; - typedef vec_data_store vds_t; - - assignment_vecvec_node(const operator_type& opr, - expression_ptr branch0, - expression_ptr branch1) - : binary_node(opr, branch0, branch1), - vec0_node_ptr_(0), - vec1_node_ptr_(0), - initialised_(false), - src_is_ivec_(false) - { - if (is_vector_node(binary_node::branch_[0].first)) - { - vec0_node_ptr_ = static_cast*>(binary_node::branch_[0].first); - vds() = vec0_node_ptr_->vds(); - } - - if (is_vector_node(binary_node::branch_[1].first)) - { - vec1_node_ptr_ = static_cast*>(binary_node::branch_[1].first); - vds_t::match_sizes(vds(),vec1_node_ptr_->vds()); - } - else if (is_ivector_node(binary_node::branch_[1].first)) - { - vector_interface* vi = reinterpret_cast*>(0); - - if (0 != (vi = dynamic_cast*>(binary_node::branch_[1].first))) - { - vec1_node_ptr_ = vi->vec(); - - if (!vi->side_effect()) - { - vi->vds() = vds(); - src_is_ivec_ = true; - } - else - vds_t::match_sizes(vds(),vi->vds()); - } - } - - initialised_ = (vec0_node_ptr_ && vec1_node_ptr_); - } - - inline T value() const - { - if (initialised_) - { - assert(binary_node::branch_[1].first); - - binary_node::branch_[1].first->value(); - - if (src_is_ivec_) - return vec0_node_ptr_->value(); - - T* vec0 = vec0_node_ptr_->vds().data(); - T* vec1 = vec1_node_ptr_->vds().data(); - - loop_unroll::details lud(size()); - const T* upper_bound = vec0 + lud.upper_bound; - - while (vec0 < upper_bound) - { - #define exprtk_loop(N) \ - vec0[N] = vec1[N]; \ - - exprtk_loop( 0) exprtk_loop( 1) - exprtk_loop( 2) exprtk_loop( 3) - #ifndef exprtk_disable_superscalar_unroll - exprtk_loop( 4) exprtk_loop( 5) - exprtk_loop( 6) exprtk_loop( 7) - exprtk_loop( 8) exprtk_loop( 9) - exprtk_loop(10) exprtk_loop(11) - exprtk_loop(12) exprtk_loop(13) - exprtk_loop(14) exprtk_loop(15) - #endif - - vec0 += lud.batch_size; - vec1 += lud.batch_size; - } - - exprtk_disable_fallthrough_begin - switch (lud.remainder) - { - #define case_stmt(N) \ - case N : *vec0++ = *vec1++; \ - - #ifndef exprtk_disable_superscalar_unroll - case_stmt(15) case_stmt(14) - case_stmt(13) case_stmt(12) - case_stmt(11) case_stmt(10) - case_stmt( 9) case_stmt( 8) - case_stmt( 7) case_stmt( 6) - case_stmt( 5) case_stmt( 4) - #endif - case_stmt( 3) case_stmt( 2) - case_stmt( 1) - } - exprtk_disable_fallthrough_end - - #undef exprtk_loop - #undef case_stmt - - return vec0_node_ptr_->value(); - } - else - return std::numeric_limits::quiet_NaN(); - } - - vector_node_ptr vec() const - { - return vec0_node_ptr_; - } - - vector_node_ptr vec() - { - return vec0_node_ptr_; - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_vecvecass; - } - - std::size_t size() const - { - return vds().size(); - } - - vds_t& vds() - { - return vds_; - } - - const vds_t& vds() const - { - return vds_; - } - - private: - - vector_node* vec0_node_ptr_; - vector_node* vec1_node_ptr_; - bool initialised_; - bool src_is_ivec_; - vds_t vds_; - }; - - template - class assignment_op_node exprtk_final : public binary_node - { - public: - - typedef expression_node* expression_ptr; - - assignment_op_node(const operator_type& opr, - expression_ptr branch0, - expression_ptr branch1) - : binary_node(opr, branch0, branch1), - var_node_ptr_(0) - { - if (is_variable_node(binary_node::branch_[0].first)) - { - var_node_ptr_ = static_cast*>(binary_node::branch_[0].first); - } - } - - inline T value() const - { - if (var_node_ptr_) - { - assert(binary_node::branch_[1].first); - - T& v = var_node_ptr_->ref(); - v = Operation::process(v,binary_node::branch_[1].first->value()); - - return v; - } - else - return std::numeric_limits::quiet_NaN(); - } - - private: - - variable_node* var_node_ptr_; - }; - - template - class assignment_vec_elem_op_node exprtk_final : public binary_node - { - public: - - typedef expression_node* expression_ptr; - - assignment_vec_elem_op_node(const operator_type& opr, - expression_ptr branch0, - expression_ptr branch1) - : binary_node(opr, branch0, branch1), - vec_node_ptr_(0) - { - if (is_vector_elem_node(binary_node::branch_[0].first)) - { - vec_node_ptr_ = static_cast*>(binary_node::branch_[0].first); - } - } - - inline T value() const - { - if (vec_node_ptr_) - { - assert(binary_node::branch_[1].first); - - T& v = vec_node_ptr_->ref(); - v = Operation::process(v,binary_node::branch_[1].first->value()); - - return v; - } - else - return std::numeric_limits::quiet_NaN(); - } - - private: - - vector_elem_node* vec_node_ptr_; - }; - - template - class assignment_rebasevec_elem_op_node exprtk_final : public binary_node - { - public: - - typedef expression_node* expression_ptr; - - assignment_rebasevec_elem_op_node(const operator_type& opr, - expression_ptr branch0, - expression_ptr branch1) - : binary_node(opr, branch0, branch1), - rbvec_node_ptr_(0) - { - if (is_rebasevector_elem_node(binary_node::branch_[0].first)) - { - rbvec_node_ptr_ = static_cast*>(binary_node::branch_[0].first); - } - } - - inline T value() const - { - if (rbvec_node_ptr_) - { - assert(binary_node::branch_[1].first); - - T& v = rbvec_node_ptr_->ref(); - v = Operation::process(v,binary_node::branch_[1].first->value()); - - return v; - } - else - return std::numeric_limits::quiet_NaN(); - } - - private: - - rebasevector_elem_node* rbvec_node_ptr_; - }; - - template - class assignment_rebasevec_celem_op_node exprtk_final : public binary_node - { - public: - - typedef expression_node* expression_ptr; - - assignment_rebasevec_celem_op_node(const operator_type& opr, - expression_ptr branch0, - expression_ptr branch1) - : binary_node(opr, branch0, branch1), - rbvec_node_ptr_(0) - { - if (is_rebasevector_celem_node(binary_node::branch_[0].first)) - { - rbvec_node_ptr_ = static_cast*>(binary_node::branch_[0].first); - } - } - - inline T value() const - { - if (rbvec_node_ptr_) - { - assert(binary_node::branch_[1].first); - - T& v = rbvec_node_ptr_->ref(); - v = Operation::process(v,binary_node::branch_[1].first->value()); - - return v; - } - else - return std::numeric_limits::quiet_NaN(); - } - - private: - - rebasevector_celem_node* rbvec_node_ptr_; - }; - - template - class assignment_vec_op_node exprtk_final - : public binary_node , - public vector_interface - { - public: - - typedef expression_node* expression_ptr; - typedef vector_node* vector_node_ptr; - typedef vec_data_store vds_t; - - assignment_vec_op_node(const operator_type& opr, - expression_ptr branch0, - expression_ptr branch1) - : binary_node(opr, branch0, branch1), - vec_node_ptr_(0) - { - if (is_vector_node(binary_node::branch_[0].first)) - { - vec_node_ptr_ = static_cast*>(binary_node::branch_[0].first); - vds() = vec_node_ptr_->vds(); - } - } - - inline T value() const - { - if (vec_node_ptr_) - { - assert(binary_node::branch_[1].first); - - const T v = binary_node::branch_[1].first->value(); - - T* vec = vds().data(); - - loop_unroll::details lud(size()); - const T* upper_bound = vec + lud.upper_bound; - - while (vec < upper_bound) - { - #define exprtk_loop(N) \ - Operation::assign(vec[N],v); \ - - exprtk_loop( 0) exprtk_loop( 1) - exprtk_loop( 2) exprtk_loop( 3) - #ifndef exprtk_disable_superscalar_unroll - exprtk_loop( 4) exprtk_loop( 5) - exprtk_loop( 6) exprtk_loop( 7) - exprtk_loop( 8) exprtk_loop( 9) - exprtk_loop(10) exprtk_loop(11) - exprtk_loop(12) exprtk_loop(13) - exprtk_loop(14) exprtk_loop(15) - #endif - - vec += lud.batch_size; - } - - exprtk_disable_fallthrough_begin - switch (lud.remainder) - { - #define case_stmt(N) \ - case N : Operation::assign(*vec++,v); \ - - #ifndef exprtk_disable_superscalar_unroll - case_stmt(15) case_stmt(14) - case_stmt(13) case_stmt(12) - case_stmt(11) case_stmt(10) - case_stmt( 9) case_stmt( 8) - case_stmt( 7) case_stmt( 6) - case_stmt( 5) case_stmt( 4) - #endif - case_stmt( 3) case_stmt( 2) - case_stmt( 1) - } - exprtk_disable_fallthrough_end - - - #undef exprtk_loop - #undef case_stmt - - return vec_node_ptr_->value(); - } - else - return std::numeric_limits::quiet_NaN(); - } - - vector_node_ptr vec() const - { - return vec_node_ptr_; - } - - vector_node_ptr vec() - { - return vec_node_ptr_; - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_vecopvalass; - } - - std::size_t size() const - { - return vds().size(); - } - - vds_t& vds() - { - return vds_; - } - - const vds_t& vds() const - { - return vds_; - } - - bool side_effect() const - { - return true; - } - - private: - - vector_node* vec_node_ptr_; - vds_t vds_; - }; - - template - class assignment_vecvec_op_node exprtk_final - : public binary_node , - public vector_interface - { - public: - - typedef expression_node* expression_ptr; - typedef vector_node* vector_node_ptr; - typedef vec_data_store vds_t; - - assignment_vecvec_op_node(const operator_type& opr, - expression_ptr branch0, - expression_ptr branch1) - : binary_node(opr, branch0, branch1), - vec0_node_ptr_(0), - vec1_node_ptr_(0), - initialised_(false) - { - if (is_vector_node(binary_node::branch_[0].first)) - { - vec0_node_ptr_ = static_cast*>(binary_node::branch_[0].first); - vds() = vec0_node_ptr_->vds(); - } - - if (is_vector_node(binary_node::branch_[1].first)) - { - vec1_node_ptr_ = static_cast*>(binary_node::branch_[1].first); - vec1_node_ptr_->vds() = vds(); - } - else if (is_ivector_node(binary_node::branch_[1].first)) - { - vector_interface* vi = reinterpret_cast*>(0); - - if (0 != (vi = dynamic_cast*>(binary_node::branch_[1].first))) - { - vec1_node_ptr_ = vi->vec(); - vec1_node_ptr_->vds() = vds(); - } - else - vds_t::match_sizes(vds(),vec1_node_ptr_->vds()); - } - - initialised_ = (vec0_node_ptr_ && vec1_node_ptr_); - } - - inline T value() const - { - if (initialised_) - { - assert(binary_node::branch_[0].first); - assert(binary_node::branch_[1].first); - - binary_node::branch_[0].first->value(); - binary_node::branch_[1].first->value(); - - T* vec0 = vec0_node_ptr_->vds().data(); - const T* vec1 = vec1_node_ptr_->vds().data(); - - loop_unroll::details lud(size()); - const T* upper_bound = vec0 + lud.upper_bound; - - while (vec0 < upper_bound) - { - #define exprtk_loop(N) \ - vec0[N] = Operation::process(vec0[N], vec1[N]); \ - - exprtk_loop( 0) exprtk_loop( 1) - exprtk_loop( 2) exprtk_loop( 3) - #ifndef exprtk_disable_superscalar_unroll - exprtk_loop( 4) exprtk_loop( 5) - exprtk_loop( 6) exprtk_loop( 7) - exprtk_loop( 8) exprtk_loop( 9) - exprtk_loop(10) exprtk_loop(11) - exprtk_loop(12) exprtk_loop(13) - exprtk_loop(14) exprtk_loop(15) - #endif - - vec0 += lud.batch_size; - vec1 += lud.batch_size; - } - - int i = 0; - - exprtk_disable_fallthrough_begin - switch (lud.remainder) - { - #define case_stmt(N) \ - case N : { vec0[i] = Operation::process(vec0[i], vec1[i]); ++i; } \ - - #ifndef exprtk_disable_superscalar_unroll - case_stmt(15) case_stmt(14) - case_stmt(13) case_stmt(12) - case_stmt(11) case_stmt(10) - case_stmt( 9) case_stmt( 8) - case_stmt( 7) case_stmt( 6) - case_stmt( 5) case_stmt( 4) - #endif - case_stmt( 3) case_stmt( 2) - case_stmt( 1) - } - exprtk_disable_fallthrough_end - - #undef exprtk_loop - #undef case_stmt - - return vec0_node_ptr_->value(); - } - else - return std::numeric_limits::quiet_NaN(); - } - - vector_node_ptr vec() const - { - return vec0_node_ptr_; - } - - vector_node_ptr vec() - { - return vec0_node_ptr_; - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_vecopvecass; - } - - std::size_t size() const - { - return vds().size(); - } - - vds_t& vds() - { - return vds_; - } - - const vds_t& vds() const - { - return vds_; - } - - bool side_effect() const - { - return true; - } - - private: - - vector_node* vec0_node_ptr_; - vector_node* vec1_node_ptr_; - bool initialised_; - vds_t vds_; - }; - - template - class vec_binop_vecvec_node exprtk_final - : public binary_node , - public vector_interface - { - public: - - typedef expression_node* expression_ptr; - typedef vector_node* vector_node_ptr; - typedef vector_holder* vector_holder_ptr; - typedef vec_data_store vds_t; - - vec_binop_vecvec_node(const operator_type& opr, - expression_ptr branch0, - expression_ptr branch1) - : binary_node(opr, branch0, branch1), - vec0_node_ptr_(0), - vec1_node_ptr_(0), - temp_ (0), - temp_vec_node_(0), - initialised_(false) - { - bool v0_is_ivec = false; - bool v1_is_ivec = false; - - if (is_vector_node(binary_node::branch_[0].first)) - { - vec0_node_ptr_ = static_cast(binary_node::branch_[0].first); - } - else if (is_ivector_node(binary_node::branch_[0].first)) - { - vector_interface* vi = reinterpret_cast*>(0); - - if (0 != (vi = dynamic_cast*>(binary_node::branch_[0].first))) - { - vec0_node_ptr_ = vi->vec(); - v0_is_ivec = true; - } - } - - if (is_vector_node(binary_node::branch_[1].first)) - { - vec1_node_ptr_ = static_cast(binary_node::branch_[1].first); - } - else if (is_ivector_node(binary_node::branch_[1].first)) - { - vector_interface* vi = reinterpret_cast*>(0); - - if (0 != (vi = dynamic_cast*>(binary_node::branch_[1].first))) - { - vec1_node_ptr_ = vi->vec(); - v1_is_ivec = true; - } - } - - if (vec0_node_ptr_ && vec1_node_ptr_) - { - vector_holder& vec0 = vec0_node_ptr_->vec_holder(); - vector_holder& vec1 = vec1_node_ptr_->vec_holder(); - - if (v0_is_ivec && (vec0.size() <= vec1.size())) - vds_ = vds_t(vec0_node_ptr_->vds()); - else if (v1_is_ivec && (vec1.size() <= vec0.size())) - vds_ = vds_t(vec1_node_ptr_->vds()); - else - vds_ = vds_t(std::min(vec0.size(),vec1.size())); - - temp_ = new vector_holder(vds().data(),vds().size()); - temp_vec_node_ = new vector_node (vds(),temp_); - - initialised_ = true; - } - } - - ~vec_binop_vecvec_node() - { - delete temp_; - delete temp_vec_node_; - } - - inline T value() const - { - if (initialised_) - { - assert(binary_node::branch_[0].first); - assert(binary_node::branch_[1].first); - - binary_node::branch_[0].first->value(); - binary_node::branch_[1].first->value(); - - const T* vec0 = vec0_node_ptr_->vds().data(); - const T* vec1 = vec1_node_ptr_->vds().data(); - T* vec2 = vds().data(); - - loop_unroll::details lud(size()); - const T* upper_bound = vec2 + lud.upper_bound; - - while (vec2 < upper_bound) - { - #define exprtk_loop(N) \ - vec2[N] = Operation::process(vec0[N], vec1[N]); \ - - exprtk_loop( 0) exprtk_loop( 1) - exprtk_loop( 2) exprtk_loop( 3) - #ifndef exprtk_disable_superscalar_unroll - exprtk_loop( 4) exprtk_loop( 5) - exprtk_loop( 6) exprtk_loop( 7) - exprtk_loop( 8) exprtk_loop( 9) - exprtk_loop(10) exprtk_loop(11) - exprtk_loop(12) exprtk_loop(13) - exprtk_loop(14) exprtk_loop(15) - #endif - - vec0 += lud.batch_size; - vec1 += lud.batch_size; - vec2 += lud.batch_size; - } - - int i = 0; - - exprtk_disable_fallthrough_begin - switch (lud.remainder) - { - #define case_stmt(N) \ - case N : { vec2[i] = Operation::process(vec0[i], vec1[i]); ++i; } \ - - #ifndef exprtk_disable_superscalar_unroll - case_stmt(15) case_stmt(14) - case_stmt(13) case_stmt(12) - case_stmt(11) case_stmt(10) - case_stmt( 9) case_stmt( 8) - case_stmt( 7) case_stmt( 6) - case_stmt( 5) case_stmt( 4) - #endif - case_stmt( 3) case_stmt( 2) - case_stmt( 1) - } - exprtk_disable_fallthrough_end - - #undef exprtk_loop - #undef case_stmt - - return (vds().data())[0]; - } - else - return std::numeric_limits::quiet_NaN(); - } - - vector_node_ptr vec() const - { - return temp_vec_node_; - } - - vector_node_ptr vec() - { - return temp_vec_node_; - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_vecvecarith; - } - - std::size_t size() const - { - return vds_.size(); - } - - vds_t& vds() - { - return vds_; - } - - const vds_t& vds() const - { - return vds_; - } - - private: - - vector_node_ptr vec0_node_ptr_; - vector_node_ptr vec1_node_ptr_; - vector_holder_ptr temp_; - vector_node_ptr temp_vec_node_; - bool initialised_; - vds_t vds_; - }; - - template - class vec_binop_vecval_node exprtk_final - : public binary_node , - public vector_interface - { - public: - - typedef expression_node* expression_ptr; - typedef vector_node* vector_node_ptr; - typedef vector_holder* vector_holder_ptr; - typedef vec_data_store vds_t; - - vec_binop_vecval_node(const operator_type& opr, - expression_ptr branch0, - expression_ptr branch1) - : binary_node(opr, branch0, branch1), - vec0_node_ptr_(0), - temp_ (0), - temp_vec_node_(0) - { - bool v0_is_ivec = false; - - if (is_vector_node(binary_node::branch_[0].first)) - { - vec0_node_ptr_ = static_cast(binary_node::branch_[0].first); - } - else if (is_ivector_node(binary_node::branch_[0].first)) - { - vector_interface* vi = reinterpret_cast*>(0); - - if (0 != (vi = dynamic_cast*>(binary_node::branch_[0].first))) - { - vec0_node_ptr_ = vi->vec(); - v0_is_ivec = true; - } - } - - if (vec0_node_ptr_) - { - if (v0_is_ivec) - vds() = vec0_node_ptr_->vds(); - else - vds() = vds_t(vec0_node_ptr_->size()); - - temp_ = new vector_holder(vds()); - temp_vec_node_ = new vector_node (vds(),temp_); - } - } - - ~vec_binop_vecval_node() - { - delete temp_; - delete temp_vec_node_; - } - - inline T value() const - { - if (vec0_node_ptr_) - { - assert(binary_node::branch_[0].first); - assert(binary_node::branch_[1].first); - - binary_node::branch_[0].first->value(); - const T v = binary_node::branch_[1].first->value(); - - const T* vec0 = vec0_node_ptr_->vds().data(); - T* vec1 = vds().data(); - - loop_unroll::details lud(size()); - const T* upper_bound = vec0 + lud.upper_bound; - - while (vec0 < upper_bound) - { - #define exprtk_loop(N) \ - vec1[N] = Operation::process(vec0[N], v); \ - - exprtk_loop( 0) exprtk_loop( 1) - exprtk_loop( 2) exprtk_loop( 3) - #ifndef exprtk_disable_superscalar_unroll - exprtk_loop( 4) exprtk_loop( 5) - exprtk_loop( 6) exprtk_loop( 7) - exprtk_loop( 8) exprtk_loop( 9) - exprtk_loop(10) exprtk_loop(11) - exprtk_loop(12) exprtk_loop(13) - exprtk_loop(14) exprtk_loop(15) - #endif - - vec0 += lud.batch_size; - vec1 += lud.batch_size; - } - - int i = 0; - - exprtk_disable_fallthrough_begin - switch (lud.remainder) - { - #define case_stmt(N) \ - case N : { vec1[i] = Operation::process(vec0[i], v); ++i; } \ - - #ifndef exprtk_disable_superscalar_unroll - case_stmt(15) case_stmt(14) - case_stmt(13) case_stmt(12) - case_stmt(11) case_stmt(10) - case_stmt( 9) case_stmt( 8) - case_stmt( 7) case_stmt( 6) - case_stmt( 5) case_stmt( 4) - #endif - case_stmt( 3) case_stmt( 2) - case_stmt( 1) - } - exprtk_disable_fallthrough_end - - #undef exprtk_loop - #undef case_stmt - - return (vds().data())[0]; - } - else - return std::numeric_limits::quiet_NaN(); - } - - vector_node_ptr vec() const - { - return temp_vec_node_; - } - - vector_node_ptr vec() - { - return temp_vec_node_; - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_vecvalarith; - } - - std::size_t size() const - { - return vds().size(); - } - - vds_t& vds() - { - return vds_; - } - - const vds_t& vds() const - { - return vds_; - } - - private: - - vector_node_ptr vec0_node_ptr_; - vector_holder_ptr temp_; - vector_node_ptr temp_vec_node_; - vds_t vds_; - }; - - template - class vec_binop_valvec_node exprtk_final - : public binary_node , - public vector_interface - { - public: - - typedef expression_node* expression_ptr; - typedef vector_node* vector_node_ptr; - typedef vector_holder* vector_holder_ptr; - typedef vec_data_store vds_t; - - vec_binop_valvec_node(const operator_type& opr, - expression_ptr branch0, - expression_ptr branch1) - : binary_node(opr, branch0, branch1), - vec1_node_ptr_(0), - temp_ (0), - temp_vec_node_(0) - { - bool v1_is_ivec = false; - - if (is_vector_node(binary_node::branch_[1].first)) - { - vec1_node_ptr_ = static_cast(binary_node::branch_[1].first); - } - else if (is_ivector_node(binary_node::branch_[1].first)) - { - vector_interface* vi = reinterpret_cast*>(0); - - if (0 != (vi = dynamic_cast*>(binary_node::branch_[1].first))) - { - vec1_node_ptr_ = vi->vec(); - v1_is_ivec = true; - } - } - - if (vec1_node_ptr_) - { - if (v1_is_ivec) - vds() = vec1_node_ptr_->vds(); - else - vds() = vds_t(vec1_node_ptr_->size()); - - temp_ = new vector_holder(vds()); - temp_vec_node_ = new vector_node (vds(),temp_); - } - } - - ~vec_binop_valvec_node() - { - delete temp_; - delete temp_vec_node_; - } - - inline T value() const - { - if (vec1_node_ptr_) - { - assert(binary_node::branch_[0].first); - assert(binary_node::branch_[1].first); - - const T v = binary_node::branch_[0].first->value(); - binary_node::branch_[1].first->value(); - - T* vec0 = vds().data(); - const T* vec1 = vec1_node_ptr_->vds().data(); - - loop_unroll::details lud(size()); - const T* upper_bound = vec0 + lud.upper_bound; - - while (vec0 < upper_bound) - { - #define exprtk_loop(N) \ - vec0[N] = Operation::process(v, vec1[N]); \ - - exprtk_loop( 0) exprtk_loop( 1) - exprtk_loop( 2) exprtk_loop( 3) - #ifndef exprtk_disable_superscalar_unroll - exprtk_loop( 4) exprtk_loop( 5) - exprtk_loop( 6) exprtk_loop( 7) - exprtk_loop( 8) exprtk_loop( 9) - exprtk_loop(10) exprtk_loop(11) - exprtk_loop(12) exprtk_loop(13) - exprtk_loop(14) exprtk_loop(15) - #endif - - vec0 += lud.batch_size; - vec1 += lud.batch_size; - } - - int i = 0; - - exprtk_disable_fallthrough_begin - switch (lud.remainder) - { - #define case_stmt(N) \ - case N : { vec0[i] = Operation::process(v, vec1[i]); ++i; } \ - - #ifndef exprtk_disable_superscalar_unroll - case_stmt(15) case_stmt(14) - case_stmt(13) case_stmt(12) - case_stmt(11) case_stmt(10) - case_stmt( 9) case_stmt( 8) - case_stmt( 7) case_stmt( 6) - case_stmt( 5) case_stmt( 4) - #endif - case_stmt( 3) case_stmt( 2) - case_stmt( 1) - } - exprtk_disable_fallthrough_end - - #undef exprtk_loop - #undef case_stmt - - return (vds().data())[0]; - } - else - return std::numeric_limits::quiet_NaN(); - } - - vector_node_ptr vec() const - { - return temp_vec_node_; - } - - vector_node_ptr vec() - { - return temp_vec_node_; - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_vecvalarith; - } - - std::size_t size() const - { - return vds().size(); - } - - vds_t& vds() - { - return vds_; - } - - const vds_t& vds() const - { - return vds_; - } - - private: - - vector_node_ptr vec1_node_ptr_; - vector_holder_ptr temp_; - vector_node_ptr temp_vec_node_; - vds_t vds_; - }; - - template - class unary_vector_node exprtk_final - : public unary_node , - public vector_interface - { - public: - - typedef expression_node* expression_ptr; - typedef vector_node* vector_node_ptr; - typedef vector_holder* vector_holder_ptr; - typedef vec_data_store vds_t; - - unary_vector_node(const operator_type& opr, expression_ptr branch0) - : unary_node(opr, branch0), - vec0_node_ptr_(0), - temp_ (0), - temp_vec_node_(0) - { - bool vec0_is_ivec = false; - - if (is_vector_node(unary_node::branch_.first)) - { - vec0_node_ptr_ = static_cast(unary_node::branch_.first); - } - else if (is_ivector_node(unary_node::branch_.first)) - { - vector_interface* vi = reinterpret_cast*>(0); - - if (0 != (vi = dynamic_cast*>(unary_node::branch_.first))) - { - vec0_node_ptr_ = vi->vec(); - vec0_is_ivec = true; - } - } - - if (vec0_node_ptr_) - { - if (vec0_is_ivec) - vds_ = vec0_node_ptr_->vds(); - else - vds_ = vds_t(vec0_node_ptr_->size()); - - temp_ = new vector_holder(vds()); - temp_vec_node_ = new vector_node (vds(),temp_); - } - } - - ~unary_vector_node() - { - delete temp_; - delete temp_vec_node_; - } - - inline T value() const - { - assert(unary_node::branch_.first); - - unary_node::branch_.first->value(); - - if (vec0_node_ptr_) - { - const T* vec0 = vec0_node_ptr_->vds().data(); - T* vec1 = vds().data(); - - loop_unroll::details lud(size()); - const T* upper_bound = vec0 + lud.upper_bound; - - while (vec0 < upper_bound) - { - #define exprtk_loop(N) \ - vec1[N] = Operation::process(vec0[N]); \ - - exprtk_loop( 0) exprtk_loop( 1) - exprtk_loop( 2) exprtk_loop( 3) - #ifndef exprtk_disable_superscalar_unroll - exprtk_loop( 4) exprtk_loop( 5) - exprtk_loop( 6) exprtk_loop( 7) - exprtk_loop( 8) exprtk_loop( 9) - exprtk_loop(10) exprtk_loop(11) - exprtk_loop(12) exprtk_loop(13) - exprtk_loop(14) exprtk_loop(15) - #endif - - vec0 += lud.batch_size; - vec1 += lud.batch_size; - } - - int i = 0; - - exprtk_disable_fallthrough_begin - switch (lud.remainder) - { - #define case_stmt(N) \ - case N : { vec1[i] = Operation::process(vec0[i]); ++i; } \ - - #ifndef exprtk_disable_superscalar_unroll - case_stmt(15) case_stmt(14) - case_stmt(13) case_stmt(12) - case_stmt(11) case_stmt(10) - case_stmt( 9) case_stmt( 8) - case_stmt( 7) case_stmt( 6) - case_stmt( 5) case_stmt( 4) - #endif - case_stmt( 3) case_stmt( 2) - case_stmt( 1) - } - exprtk_disable_fallthrough_end - - #undef exprtk_loop - #undef case_stmt - - return (vds().data())[0]; - } - else - return std::numeric_limits::quiet_NaN(); - } - - vector_node_ptr vec() const - { - return temp_vec_node_; - } - - vector_node_ptr vec() - { - return temp_vec_node_; - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_vecunaryop; - } - - std::size_t size() const - { - return vds().size(); - } - - vds_t& vds() - { - return vds_; - } - - const vds_t& vds() const - { - return vds_; - } - - private: - - vector_node_ptr vec0_node_ptr_; - vector_holder_ptr temp_; - vector_node_ptr temp_vec_node_; - vds_t vds_; - }; - - template - class scand_node exprtk_final : public binary_node - { - public: - - typedef expression_node* expression_ptr; - - scand_node(const operator_type& opr, - expression_ptr branch0, - expression_ptr branch1) - : binary_node(opr, branch0, branch1) - {} - - inline T value() const - { - assert(binary_node::branch_[0].first); - assert(binary_node::branch_[1].first); - - return ( - std::not_equal_to() - (T(0),binary_node::branch_[0].first->value()) && - std::not_equal_to() - (T(0),binary_node::branch_[1].first->value()) - ) ? T(1) : T(0); - } - }; - - template - class scor_node exprtk_final : public binary_node - { - public: - - typedef expression_node* expression_ptr; - - scor_node(const operator_type& opr, - expression_ptr branch0, - expression_ptr branch1) - : binary_node(opr, branch0, branch1) - {} - - inline T value() const - { - assert(binary_node::branch_[0].first); - assert(binary_node::branch_[1].first); - - return ( - std::not_equal_to() - (T(0),binary_node::branch_[0].first->value()) || - std::not_equal_to() - (T(0),binary_node::branch_[1].first->value()) - ) ? T(1) : T(0); - } - }; - - template - class function_N_node exprtk_final : public expression_node - { - public: - - // Function of N paramters. - typedef expression_node* expression_ptr; - typedef std::pair branch_t; - typedef IFunction ifunction; - - explicit function_N_node(ifunction* func) - : function_((N == func->param_count) ? func : reinterpret_cast(0)), - parameter_count_(func->param_count) - {} - - template - bool init_branches(expression_ptr (&b)[NumBranches]) - { - // Needed for incompetent and broken msvc compiler versions - #ifdef _MSC_VER - #pragma warning(push) - #pragma warning(disable: 4127) - #endif - if (N != NumBranches) - return false; - else - { - for (std::size_t i = 0; i < NumBranches; ++i) - { - if (b[i]) - branch_[i] = std::make_pair(b[i],branch_deletable(b[i])); - else - return false; - } - return true; - } - #ifdef _MSC_VER - #pragma warning(pop) - #endif - } - - inline bool operator <(const function_N_node& fn) const - { - return this < (&fn); - } - - inline T value() const - { - // Needed for incompetent and broken msvc compiler versions - #ifdef _MSC_VER - #pragma warning(push) - #pragma warning(disable: 4127) - #endif - if ((0 == function_) || (0 == N)) - return std::numeric_limits::quiet_NaN(); - else - { - T v[N]; - evaluate_branches::execute(v,branch_); - return invoke::execute(*function_,v); - } - #ifdef _MSC_VER - #pragma warning(pop) - #endif - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_function; - } - - void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) - { - expression_node::ndb_t::template collect(branch_, node_delete_list); - } - - std::size_t node_depth() const - { - return expression_node::ndb_t::template compute_node_depth(branch_); - } - - template - struct evaluate_branches - { - static inline void execute(T_ (&v)[BranchCount], const branch_t (&b)[BranchCount]) - { - for (std::size_t i = 0; i < BranchCount; ++i) - { - v[i] = b[i].first->value(); - } - } - }; - - template - struct evaluate_branches - { - static inline void execute(T_ (&v)[5], const branch_t (&b)[5]) - { - v[0] = b[0].first->value(); - v[1] = b[1].first->value(); - v[2] = b[2].first->value(); - v[3] = b[3].first->value(); - v[4] = b[4].first->value(); - } - }; - - template - struct evaluate_branches - { - static inline void execute(T_ (&v)[4], const branch_t (&b)[4]) - { - v[0] = b[0].first->value(); - v[1] = b[1].first->value(); - v[2] = b[2].first->value(); - v[3] = b[3].first->value(); - } - }; - - template - struct evaluate_branches - { - static inline void execute(T_ (&v)[3], const branch_t (&b)[3]) - { - v[0] = b[0].first->value(); - v[1] = b[1].first->value(); - v[2] = b[2].first->value(); - } - }; - - template - struct evaluate_branches - { - static inline void execute(T_ (&v)[2], const branch_t (&b)[2]) - { - v[0] = b[0].first->value(); - v[1] = b[1].first->value(); - } - }; - - template - struct evaluate_branches - { - static inline void execute(T_ (&v)[1], const branch_t (&b)[1]) - { - v[0] = b[0].first->value(); - } - }; - - template - struct invoke { static inline T execute(ifunction&, branch_t (&)[ParamCount]) { return std::numeric_limits::quiet_NaN(); } }; - - template - struct invoke - { - static inline T_ execute(ifunction& f, T_ (&v)[20]) - { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16],v[17],v[18],v[19]); } - }; - - template - struct invoke - { - static inline T_ execute(ifunction& f, T_ (&v)[19]) - { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16],v[17],v[18]); } - }; - - template - struct invoke - { - static inline T_ execute(ifunction& f, T_ (&v)[18]) - { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16],v[17]); } - }; - - template - struct invoke - { - static inline T_ execute(ifunction& f, T_ (&v)[17]) - { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16]); } - }; - - template - struct invoke - { - static inline T_ execute(ifunction& f, T_ (&v)[16]) - { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15]); } - }; - - template - struct invoke - { - static inline T_ execute(ifunction& f, T_ (&v)[15]) - { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14]); } - }; - - template - struct invoke - { - static inline T_ execute(ifunction& f, T_ (&v)[14]) - { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13]); } - }; - - template - struct invoke - { - static inline T_ execute(ifunction& f, T_ (&v)[13]) - { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12]); } - }; - - template - struct invoke - { - static inline T_ execute(ifunction& f, T_ (&v)[12]) - { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11]); } - }; - - template - struct invoke - { - static inline T_ execute(ifunction& f, T_ (&v)[11]) - { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10]); } - }; - - template - struct invoke - { - static inline T_ execute(ifunction& f, T_ (&v)[10]) - { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9]); } - }; - - template - struct invoke - { - static inline T_ execute(ifunction& f, T_ (&v)[9]) - { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8]); } - }; - - template - struct invoke - { - static inline T_ execute(ifunction& f, T_ (&v)[8]) - { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]); } - }; - - template - struct invoke - { - static inline T_ execute(ifunction& f, T_ (&v)[7]) - { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6]); } - }; - - template - struct invoke - { - static inline T_ execute(ifunction& f, T_ (&v)[6]) - { return f(v[0],v[1],v[2],v[3],v[4],v[5]); } - }; - - template - struct invoke - { - static inline T_ execute(ifunction& f, T_ (&v)[5]) - { return f(v[0],v[1],v[2],v[3],v[4]); } - }; - - template - struct invoke - { - static inline T_ execute(ifunction& f, T_ (&v)[4]) - { return f(v[0],v[1],v[2],v[3]); } - }; - - template - struct invoke - { - static inline T_ execute(ifunction& f, T_ (&v)[3]) - { return f(v[0],v[1],v[2]); } - }; - - template - struct invoke - { - static inline T_ execute(ifunction& f, T_ (&v)[2]) - { return f(v[0],v[1]); } - }; - - template - struct invoke - { - static inline T_ execute(ifunction& f, T_ (&v)[1]) - { return f(v[0]); } - }; - - private: - - ifunction* function_; - std::size_t parameter_count_; - branch_t branch_[N]; - }; - - template - class function_N_node exprtk_final : public expression_node - { - public: - - typedef expression_node* expression_ptr; - typedef IFunction ifunction; - - explicit function_N_node(ifunction* func) - : function_((0 == func->param_count) ? func : reinterpret_cast(0)) - {} - - inline bool operator <(const function_N_node& fn) const - { - return this < (&fn); - } - - inline T value() const - { - if (function_) - return (*function_)(); - else - return std::numeric_limits::quiet_NaN(); - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_function; - } - - private: - - ifunction* function_; - }; - - template - class vararg_function_node exprtk_final : public expression_node - { - public: - - typedef expression_node* expression_ptr; - - vararg_function_node(VarArgFunction* func, - const std::vector& arg_list) - : function_(func), - arg_list_(arg_list) - { - value_list_.resize(arg_list.size(),std::numeric_limits::quiet_NaN()); - } - - inline bool operator <(const vararg_function_node& fn) const - { - return this < (&fn); - } - - inline T value() const - { - if (function_) - { - populate_value_list(); - return (*function_)(value_list_); - } - else - return std::numeric_limits::quiet_NaN(); - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_vafunction; - } - - void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) - { - for (std::size_t i = 0; i < arg_list_.size(); ++i) - { - if (arg_list_[i] && !details::is_variable_node(arg_list_[i])) - { - node_delete_list.push_back(&arg_list_[i]); - } - } - } - - std::size_t node_depth() const - { - return expression_node::ndb_t::compute_node_depth(arg_list_); - } - - private: - - inline void populate_value_list() const - { - for (std::size_t i = 0; i < arg_list_.size(); ++i) - { - value_list_[i] = arg_list_[i]->value(); - } - } - - VarArgFunction* function_; - std::vector arg_list_; - mutable std::vector value_list_; - }; - - template - class generic_function_node : public expression_node - { - public: - - typedef type_store type_store_t; - typedef expression_node* expression_ptr; - typedef variable_node variable_node_t; - typedef vector_node vector_node_t; - typedef variable_node_t* variable_node_ptr_t; - typedef vector_node_t* vector_node_ptr_t; - typedef range_interface range_interface_t; - typedef range_data_type range_data_type_t; - typedef range_pack range_t; - typedef std::pair branch_t; - typedef std::pair void_t; - typedef std::vector tmp_vs_t; - typedef std::vector typestore_list_t; - typedef std::vector range_list_t; - - explicit generic_function_node(const std::vector& arg_list, - GenericFunction* func = reinterpret_cast(0)) - : function_(func), - arg_list_(arg_list) - {} - - virtual ~generic_function_node() - {} - - void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) - { - expression_node::ndb_t::collect(branch_, node_delete_list); - } - - std::size_t node_depth() const exprtk_final - { - return expression_node::ndb_t::compute_node_depth(branch_); - } - - virtual bool init_branches() - { - expr_as_vec1_store_.resize(arg_list_.size(),T(0) ); - typestore_list_ .resize(arg_list_.size(),type_store_t() ); - range_list_ .resize(arg_list_.size(),range_data_type_t()); - branch_ .resize(arg_list_.size(),branch_t(reinterpret_cast(0),false)); - - for (std::size_t i = 0; i < arg_list_.size(); ++i) - { - type_store_t& ts = typestore_list_[i]; - - if (0 == arg_list_[i]) - return false; - else if (is_ivector_node(arg_list_[i])) - { - vector_interface* vi = reinterpret_cast*>(0); - - if (0 == (vi = dynamic_cast*>(arg_list_[i]))) - return false; - - ts.size = vi->size(); - ts.data = vi->vds().data(); - ts.type = type_store_t::e_vector; - vi->vec()->vec_holder().set_ref(&ts.vec_data); - } - #ifndef exprtk_disable_string_capabilities - else if (is_generally_string_node(arg_list_[i])) - { - string_base_node* sbn = reinterpret_cast*>(0); - - if (0 == (sbn = dynamic_cast*>(arg_list_[i]))) - return false; - - ts.size = sbn->size(); - ts.data = reinterpret_cast(const_cast(sbn->base())); - ts.type = type_store_t::e_string; - - range_list_[i].data = ts.data; - range_list_[i].size = ts.size; - range_list_[i].type_size = sizeof(char); - range_list_[i].str_node = sbn; - - range_interface_t* ri = reinterpret_cast(0); - - if (0 == (ri = dynamic_cast(arg_list_[i]))) - return false; - - const range_t& rp = ri->range_ref(); - - if ( - rp.const_range() && - is_const_string_range_node(arg_list_[i]) - ) - { - ts.size = rp.const_size(); - ts.data = static_cast(ts.data) + rp.n0_c.second; - range_list_[i].range = reinterpret_cast(0); - } - else - range_list_[i].range = &(ri->range_ref()); - } - #endif - else if (is_variable_node(arg_list_[i])) - { - variable_node_ptr_t var = variable_node_ptr_t(0); - - if (0 == (var = dynamic_cast(arg_list_[i]))) - return false; - - ts.size = 1; - ts.data = &var->ref(); - ts.type = type_store_t::e_scalar; - } - else - { - ts.size = 1; - ts.data = reinterpret_cast(&expr_as_vec1_store_[i]); - ts.type = type_store_t::e_scalar; - } - - branch_[i] = std::make_pair(arg_list_[i],branch_deletable(arg_list_[i])); - } - - return true; - } - - inline bool operator <(const generic_function_node& fn) const - { - return this < (&fn); - } - - inline T value() const - { - if (function_) - { - if (populate_value_list()) - { - typedef typename GenericFunction::parameter_list_t parameter_list_t; - - return (*function_)(parameter_list_t(typestore_list_)); - } - } - - return std::numeric_limits::quiet_NaN(); - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_genfunction; - } - - protected: - - inline virtual bool populate_value_list() const - { - for (std::size_t i = 0; i < branch_.size(); ++i) - { - expr_as_vec1_store_[i] = branch_[i].first->value(); - } - - for (std::size_t i = 0; i < branch_.size(); ++i) - { - range_data_type_t& rdt = range_list_[i]; - - if (rdt.range) - { - const range_t& rp = (*rdt.range); - std::size_t r0 = 0; - std::size_t r1 = 0; - - if (rp(r0, r1, rdt.size)) - { - type_store_t& ts = typestore_list_[i]; - - ts.size = rp.cache_size(); - #ifndef exprtk_disable_string_capabilities - if (ts.type == type_store_t::e_string) - ts.data = const_cast(rdt.str_node->base()) + rp.cache.first; - else - #endif - ts.data = static_cast(rdt.data) + (rp.cache.first * rdt.type_size); - } - else - return false; - } - } - - return true; - } - - GenericFunction* function_; - mutable typestore_list_t typestore_list_; - - private: - - std::vector arg_list_; - std::vector branch_; - mutable tmp_vs_t expr_as_vec1_store_; - mutable range_list_t range_list_; - }; - - #ifndef exprtk_disable_string_capabilities - template - class string_function_node : public generic_function_node, - public string_base_node, - public range_interface - { - public: - - typedef generic_function_node gen_function_t; - typedef range_pack range_t; - - string_function_node(StringFunction* func, - const std::vector& arg_list) - : gen_function_t(arg_list,func) - { - range_.n0_c = std::make_pair(true,0); - range_.n1_c = std::make_pair(true,0); - range_.cache.first = range_.n0_c.second; - range_.cache.second = range_.n1_c.second; - } - - inline bool operator <(const string_function_node& fn) const - { - return this < (&fn); - } - - inline T value() const - { - if (gen_function_t::function_) - { - if (gen_function_t::populate_value_list()) - { - typedef typename StringFunction::parameter_list_t parameter_list_t; - - const T result = (*gen_function_t::function_) - ( - ret_string_, - parameter_list_t(gen_function_t::typestore_list_) - ); - - range_.n1_c.second = ret_string_.size() - 1; - range_.cache.second = range_.n1_c.second; - - return result; - } - } - - return std::numeric_limits::quiet_NaN(); - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_strfunction; - } - - std::string str() const - { - return ret_string_; - } - - char_cptr base() const - { - return &ret_string_[0]; - } - - std::size_t size() const - { - return ret_string_.size(); - } - - range_t& range_ref() - { - return range_; - } - - const range_t& range_ref() const - { - return range_; - } - - protected: - - mutable range_t range_; - mutable std::string ret_string_; - }; - #endif - - template - class multimode_genfunction_node : public generic_function_node - { - public: - - typedef generic_function_node gen_function_t; - typedef range_pack range_t; - - multimode_genfunction_node(GenericFunction* func, - const std::size_t& param_seq_index, - const std::vector& arg_list) - : gen_function_t(arg_list,func), - param_seq_index_(param_seq_index) - {} - - inline T value() const - { - if (gen_function_t::function_) - { - if (gen_function_t::populate_value_list()) - { - typedef typename GenericFunction::parameter_list_t parameter_list_t; - - return (*gen_function_t::function_) - ( - param_seq_index_, - parameter_list_t(gen_function_t::typestore_list_) - ); - } - } - - return std::numeric_limits::quiet_NaN(); - } - - inline typename expression_node::node_type type() const exprtk_final - { - return expression_node::e_genfunction; - } - - private: - - std::size_t param_seq_index_; - }; - - #ifndef exprtk_disable_string_capabilities - template - class multimode_strfunction_node exprtk_final : public string_function_node - { - public: - - typedef string_function_node str_function_t; - typedef range_pack range_t; - - multimode_strfunction_node(StringFunction* func, - const std::size_t& param_seq_index, - const std::vector& arg_list) - : str_function_t(func,arg_list), - param_seq_index_(param_seq_index) - {} - - inline T value() const - { - if (str_function_t::function_) - { - if (str_function_t::populate_value_list()) - { - typedef typename StringFunction::parameter_list_t parameter_list_t; - - const T result = (*str_function_t::function_) - ( - param_seq_index_, - str_function_t::ret_string_, - parameter_list_t(str_function_t::typestore_list_) - ); - - str_function_t::range_.n1_c.second = str_function_t::ret_string_.size() - 1; - str_function_t::range_.cache.second = str_function_t::range_.n1_c.second; - - return result; - } - } - - return std::numeric_limits::quiet_NaN(); - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_strfunction; - } - - private: - - const std::size_t param_seq_index_; - }; - #endif - - class return_exception - {}; - - template - class null_igenfunc - { - public: - - virtual ~null_igenfunc() - {} - - typedef type_store generic_type; - typedef typename generic_type::parameter_list parameter_list_t; - - inline virtual T operator() (parameter_list_t) - { - return std::numeric_limits::quiet_NaN(); - } - }; - - #ifndef exprtk_disable_return_statement - template - class return_node exprtk_final : public generic_function_node > - { - public: - - typedef null_igenfunc igeneric_function_t; - typedef igeneric_function_t* igeneric_function_ptr; - typedef generic_function_node gen_function_t; - typedef results_context results_context_t; - - return_node(const std::vector& arg_list, - results_context_t& rc) - : gen_function_t (arg_list), - results_context_(&rc) - {} - - inline T value() const - { - if ( - (0 != results_context_) && - gen_function_t::populate_value_list() - ) - { - typedef typename type_store::parameter_list parameter_list_t; - - results_context_-> - assign(parameter_list_t(gen_function_t::typestore_list_)); - - throw return_exception(); - } - - return std::numeric_limits::quiet_NaN(); - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_return; - } - - private: - - results_context_t* results_context_; - }; - - template - class return_envelope_node exprtk_final : public expression_node - { - public: - - typedef expression_node* expression_ptr; - typedef results_context results_context_t; - typedef std::pair branch_t; - - return_envelope_node(expression_ptr body, results_context_t& rc) - : results_context_(&rc ), - return_invoked_ (false) - { - construct_branch_pair(body_, body); - } - - inline T value() const - { - assert(body_.first); - - try - { - return_invoked_ = false; - results_context_->clear(); - - return body_.first->value(); - } - catch(const return_exception&) - { - return_invoked_ = true; - return std::numeric_limits::quiet_NaN(); - } - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_retenv; - } - - inline bool* retinvk_ptr() - { - return &return_invoked_; - } - - void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) - { - expression_node::ndb_t::collect(body_, node_delete_list); - } - - std::size_t node_depth() const - { - return expression_node::ndb_t::compute_node_depth(body_); - } - - private: - - results_context_t* results_context_; - mutable bool return_invoked_; - branch_t body_; - }; - #endif - - #define exprtk_define_unary_op(OpName) \ - template \ - struct OpName##_op \ - { \ - typedef typename functor_t::Type Type; \ - typedef typename expression_node::node_type node_t; \ - \ - static inline T process(Type v) \ - { \ - return numeric:: OpName (v); \ - } \ - \ - static inline node_t type() \ - { \ - return expression_node::e_##OpName; \ - } \ - \ - static inline details::operator_type operation() \ - { \ - return details::e_##OpName; \ - } \ - }; \ - - exprtk_define_unary_op(abs ) - exprtk_define_unary_op(acos ) - exprtk_define_unary_op(acosh) - exprtk_define_unary_op(asin ) - exprtk_define_unary_op(asinh) - exprtk_define_unary_op(atan ) - exprtk_define_unary_op(atanh) - exprtk_define_unary_op(ceil ) - exprtk_define_unary_op(cos ) - exprtk_define_unary_op(cosh ) - exprtk_define_unary_op(cot ) - exprtk_define_unary_op(csc ) - exprtk_define_unary_op(d2g ) - exprtk_define_unary_op(d2r ) - exprtk_define_unary_op(erf ) - exprtk_define_unary_op(erfc ) - exprtk_define_unary_op(exp ) - exprtk_define_unary_op(expm1) - exprtk_define_unary_op(floor) - exprtk_define_unary_op(frac ) - exprtk_define_unary_op(g2d ) - exprtk_define_unary_op(log ) - exprtk_define_unary_op(log10) - exprtk_define_unary_op(log2 ) - exprtk_define_unary_op(log1p) - exprtk_define_unary_op(ncdf ) - exprtk_define_unary_op(neg ) - exprtk_define_unary_op(notl ) - exprtk_define_unary_op(pos ) - exprtk_define_unary_op(r2d ) - exprtk_define_unary_op(round) - exprtk_define_unary_op(sec ) - exprtk_define_unary_op(sgn ) - exprtk_define_unary_op(sin ) - exprtk_define_unary_op(sinc ) - exprtk_define_unary_op(sinh ) - exprtk_define_unary_op(sqrt ) - exprtk_define_unary_op(tan ) - exprtk_define_unary_op(tanh ) - exprtk_define_unary_op(trunc) - #undef exprtk_define_unary_op - - template - struct opr_base - { - typedef typename details::functor_t::Type Type; - typedef typename details::functor_t::RefType RefType; - typedef typename details::functor_t functor_t; - typedef typename functor_t::qfunc_t quaternary_functor_t; - typedef typename functor_t::tfunc_t trinary_functor_t; - typedef typename functor_t::bfunc_t binary_functor_t; - typedef typename functor_t::ufunc_t unary_functor_t; - }; - - template - struct add_op : public opr_base - { - typedef typename opr_base::Type Type; - typedef typename opr_base::RefType RefType; - - static inline T process(Type t1, Type t2) { return t1 + t2; } - static inline T process(Type t1, Type t2, Type t3) { return t1 + t2 + t3; } - static inline void assign(RefType t1, Type t2) { t1 += t2; } - static inline typename expression_node::node_type type() { return expression_node::e_add; } - static inline details::operator_type operation() { return details::e_add; } - }; - - template - struct mul_op : public opr_base - { - typedef typename opr_base::Type Type; - typedef typename opr_base::RefType RefType; - - static inline T process(Type t1, Type t2) { return t1 * t2; } - static inline T process(Type t1, Type t2, Type t3) { return t1 * t2 * t3; } - static inline void assign(RefType t1, Type t2) { t1 *= t2; } - static inline typename expression_node::node_type type() { return expression_node::e_mul; } - static inline details::operator_type operation() { return details::e_mul; } - }; - - template - struct sub_op : public opr_base - { - typedef typename opr_base::Type Type; - typedef typename opr_base::RefType RefType; - - static inline T process(Type t1, Type t2) { return t1 - t2; } - static inline T process(Type t1, Type t2, Type t3) { return t1 - t2 - t3; } - static inline void assign(RefType t1, Type t2) { t1 -= t2; } - static inline typename expression_node::node_type type() { return expression_node::e_sub; } - static inline details::operator_type operation() { return details::e_sub; } - }; - - template - struct div_op : public opr_base - { - typedef typename opr_base::Type Type; - typedef typename opr_base::RefType RefType; - - static inline T process(Type t1, Type t2) { return t1 / t2; } - static inline T process(Type t1, Type t2, Type t3) { return t1 / t2 / t3; } - static inline void assign(RefType t1, Type t2) { t1 /= t2; } - static inline typename expression_node::node_type type() { return expression_node::e_div; } - static inline details::operator_type operation() { return details::e_div; } - }; - - template - struct mod_op : public opr_base - { - typedef typename opr_base::Type Type; - typedef typename opr_base::RefType RefType; - - static inline T process(Type t1, Type t2) { return numeric::modulus(t1,t2); } - static inline void assign(RefType t1, Type t2) { t1 = numeric::modulus(t1,t2); } - static inline typename expression_node::node_type type() { return expression_node::e_mod; } - static inline details::operator_type operation() { return details::e_mod; } - }; - - template - struct pow_op : public opr_base - { - typedef typename opr_base::Type Type; - typedef typename opr_base::RefType RefType; - - static inline T process(Type t1, Type t2) { return numeric::pow(t1,t2); } - static inline void assign(RefType t1, Type t2) { t1 = numeric::pow(t1,t2); } - static inline typename expression_node::node_type type() { return expression_node::e_pow; } - static inline details::operator_type operation() { return details::e_pow; } - }; - - template - struct lt_op : public opr_base - { - typedef typename opr_base::Type Type; - - static inline T process(Type t1, Type t2) { return ((t1 < t2) ? T(1) : T(0)); } - static inline T process(const std::string& t1, const std::string& t2) { return ((t1 < t2) ? T(1) : T(0)); } - static inline typename expression_node::node_type type() { return expression_node::e_lt; } - static inline details::operator_type operation() { return details::e_lt; } - }; - - template - struct lte_op : public opr_base - { - typedef typename opr_base::Type Type; - - static inline T process(Type t1, Type t2) { return ((t1 <= t2) ? T(1) : T(0)); } - static inline T process(const std::string& t1, const std::string& t2) { return ((t1 <= t2) ? T(1) : T(0)); } - static inline typename expression_node::node_type type() { return expression_node::e_lte; } - static inline details::operator_type operation() { return details::e_lte; } - }; - - template - struct gt_op : public opr_base - { - typedef typename opr_base::Type Type; - - static inline T process(Type t1, Type t2) { return ((t1 > t2) ? T(1) : T(0)); } - static inline T process(const std::string& t1, const std::string& t2) { return ((t1 > t2) ? T(1) : T(0)); } - static inline typename expression_node::node_type type() { return expression_node::e_gt; } - static inline details::operator_type operation() { return details::e_gt; } - }; - - template - struct gte_op : public opr_base - { - typedef typename opr_base::Type Type; - - static inline T process(Type t1, Type t2) { return ((t1 >= t2) ? T(1) : T(0)); } - static inline T process(const std::string& t1, const std::string& t2) { return ((t1 >= t2) ? T(1) : T(0)); } - static inline typename expression_node::node_type type() { return expression_node::e_gte; } - static inline details::operator_type operation() { return details::e_gte; } - }; - - template - struct eq_op : public opr_base - { - typedef typename opr_base::Type Type; - static inline T process(Type t1, Type t2) { return (std::equal_to()(t1,t2) ? T(1) : T(0)); } - static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); } - static inline typename expression_node::node_type type() { return expression_node::e_eq; } - static inline details::operator_type operation() { return details::e_eq; } - }; - - template - struct equal_op : public opr_base - { - typedef typename opr_base::Type Type; - - static inline T process(Type t1, Type t2) { return numeric::equal(t1,t2); } - static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); } - static inline typename expression_node::node_type type() { return expression_node::e_eq; } - static inline details::operator_type operation() { return details::e_equal; } - }; - - template - struct ne_op : public opr_base - { - typedef typename opr_base::Type Type; - - static inline T process(Type t1, Type t2) { return (std::not_equal_to()(t1,t2) ? T(1) : T(0)); } - static inline T process(const std::string& t1, const std::string& t2) { return ((t1 != t2) ? T(1) : T(0)); } - static inline typename expression_node::node_type type() { return expression_node::e_ne; } - static inline details::operator_type operation() { return details::e_ne; } - }; - - template - struct and_op : public opr_base - { - typedef typename opr_base::Type Type; - - static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(1) : T(0); } - static inline typename expression_node::node_type type() { return expression_node::e_and; } - static inline details::operator_type operation() { return details::e_and; } - }; - - template - struct nand_op : public opr_base - { - typedef typename opr_base::Type Type; - - static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(0) : T(1); } - static inline typename expression_node::node_type type() { return expression_node::e_nand; } - static inline details::operator_type operation() { return details::e_nand; } - }; - - template - struct or_op : public opr_base - { - typedef typename opr_base::Type Type; - - static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(1) : T(0); } - static inline typename expression_node::node_type type() { return expression_node::e_or; } - static inline details::operator_type operation() { return details::e_or; } - }; - - template - struct nor_op : public opr_base - { - typedef typename opr_base::Type Type; - - static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(0) : T(1); } - static inline typename expression_node::node_type type() { return expression_node::e_nor; } - static inline details::operator_type operation() { return details::e_nor; } - }; - - template - struct xor_op : public opr_base - { - typedef typename opr_base::Type Type; - - static inline T process(Type t1, Type t2) { return numeric::xor_opr(t1,t2); } - static inline typename expression_node::node_type type() { return expression_node::e_nor; } - static inline details::operator_type operation() { return details::e_xor; } - }; - - template - struct xnor_op : public opr_base - { - typedef typename opr_base::Type Type; - - static inline T process(Type t1, Type t2) { return numeric::xnor_opr(t1,t2); } - static inline typename expression_node::node_type type() { return expression_node::e_nor; } - static inline details::operator_type operation() { return details::e_xnor; } - }; - - template - struct in_op : public opr_base - { - typedef typename opr_base::Type Type; - - static inline T process(const T&, const T&) { return std::numeric_limits::quiet_NaN(); } - static inline T process(const std::string& t1, const std::string& t2) { return ((std::string::npos != t2.find(t1)) ? T(1) : T(0)); } - static inline typename expression_node::node_type type() { return expression_node::e_in; } - static inline details::operator_type operation() { return details::e_in; } - }; - - template - struct like_op : public opr_base - { - typedef typename opr_base::Type Type; - - static inline T process(const T&, const T&) { return std::numeric_limits::quiet_NaN(); } - static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_match(t2,t1) ? T(1) : T(0)); } - static inline typename expression_node::node_type type() { return expression_node::e_like; } - static inline details::operator_type operation() { return details::e_like; } - }; - - template - struct ilike_op : public opr_base - { - typedef typename opr_base::Type Type; - - static inline T process(const T&, const T&) { return std::numeric_limits::quiet_NaN(); } - static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_imatch(t2,t1) ? T(1) : T(0)); } - static inline typename expression_node::node_type type() { return expression_node::e_ilike; } - static inline details::operator_type operation() { return details::e_ilike; } - }; - - template - struct inrange_op : public opr_base - { - typedef typename opr_base::Type Type; - - static inline T process(const T& t0, const T& t1, const T& t2) { return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0); } - static inline T process(const std::string& t0, const std::string& t1, const std::string& t2) - { - return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0); - } - static inline typename expression_node::node_type type() { return expression_node::e_inranges; } - static inline details::operator_type operation() { return details::e_inrange; } - }; - - template - inline T value(details::expression_node* n) - { - return n->value(); - } - - template - inline T value(std::pair*,bool> n) - { - return n.first->value(); - } - - template - inline T value(const T* t) - { - return (*t); - } - - template - inline T value(const T& t) - { - return t; - } - - template - struct vararg_add_op : public opr_base - { - typedef typename opr_base::Type Type; - - template class Sequence> - static inline T process(const Sequence& arg_list) - { - switch (arg_list.size()) - { - case 0 : return T(0); - case 1 : return process_1(arg_list); - case 2 : return process_2(arg_list); - case 3 : return process_3(arg_list); - case 4 : return process_4(arg_list); - case 5 : return process_5(arg_list); - default : - { - T result = T(0); - - for (std::size_t i = 0; i < arg_list.size(); ++i) - { - result += value(arg_list[i]); - } - - return result; - } - } - } - - template - static inline T process_1(const Sequence& arg_list) - { - return value(arg_list[0]); - } - - template - static inline T process_2(const Sequence& arg_list) - { - return value(arg_list[0]) + value(arg_list[1]); - } - - template - static inline T process_3(const Sequence& arg_list) - { - return value(arg_list[0]) + value(arg_list[1]) + - value(arg_list[2]) ; - } - - template - static inline T process_4(const Sequence& arg_list) - { - return value(arg_list[0]) + value(arg_list[1]) + - value(arg_list[2]) + value(arg_list[3]) ; - } - - template - static inline T process_5(const Sequence& arg_list) - { - return value(arg_list[0]) + value(arg_list[1]) + - value(arg_list[2]) + value(arg_list[3]) + - value(arg_list[4]) ; - } - }; - - template - struct vararg_mul_op : public opr_base - { - typedef typename opr_base::Type Type; - - template class Sequence> - static inline T process(const Sequence& arg_list) - { - switch (arg_list.size()) - { - case 0 : return T(0); - case 1 : return process_1(arg_list); - case 2 : return process_2(arg_list); - case 3 : return process_3(arg_list); - case 4 : return process_4(arg_list); - case 5 : return process_5(arg_list); - default : - { - T result = T(value(arg_list[0])); - - for (std::size_t i = 1; i < arg_list.size(); ++i) - { - result *= value(arg_list[i]); - } - - return result; - } - } - } - - template - static inline T process_1(const Sequence& arg_list) - { - return value(arg_list[0]); - } - - template - static inline T process_2(const Sequence& arg_list) - { - return value(arg_list[0]) * value(arg_list[1]); - } - - template - static inline T process_3(const Sequence& arg_list) - { - return value(arg_list[0]) * value(arg_list[1]) * - value(arg_list[2]) ; - } - - template - static inline T process_4(const Sequence& arg_list) - { - return value(arg_list[0]) * value(arg_list[1]) * - value(arg_list[2]) * value(arg_list[3]) ; - } - - template - static inline T process_5(const Sequence& arg_list) - { - return value(arg_list[0]) * value(arg_list[1]) * - value(arg_list[2]) * value(arg_list[3]) * - value(arg_list[4]) ; - } - }; - - template - struct vararg_avg_op : public opr_base - { - typedef typename opr_base::Type Type; - - template class Sequence> - static inline T process(const Sequence& arg_list) - { - switch (arg_list.size()) - { - case 0 : return T(0); - case 1 : return process_1(arg_list); - case 2 : return process_2(arg_list); - case 3 : return process_3(arg_list); - case 4 : return process_4(arg_list); - case 5 : return process_5(arg_list); - default : return vararg_add_op::process(arg_list) / arg_list.size(); - } - } - - template - static inline T process_1(const Sequence& arg_list) - { - return value(arg_list[0]); - } - - template - static inline T process_2(const Sequence& arg_list) - { - return (value(arg_list[0]) + value(arg_list[1])) / T(2); - } - - template - static inline T process_3(const Sequence& arg_list) - { - return (value(arg_list[0]) + value(arg_list[1]) + value(arg_list[2])) / T(3); - } - - template - static inline T process_4(const Sequence& arg_list) - { - return (value(arg_list[0]) + value(arg_list[1]) + - value(arg_list[2]) + value(arg_list[3])) / T(4); - } - - template - static inline T process_5(const Sequence& arg_list) - { - return (value(arg_list[0]) + value(arg_list[1]) + - value(arg_list[2]) + value(arg_list[3]) + - value(arg_list[4])) / T(5); - } - }; - - template - struct vararg_min_op : public opr_base - { - typedef typename opr_base::Type Type; - - template class Sequence> - static inline T process(const Sequence& arg_list) - { - switch (arg_list.size()) - { - case 0 : return T(0); - case 1 : return process_1(arg_list); - case 2 : return process_2(arg_list); - case 3 : return process_3(arg_list); - case 4 : return process_4(arg_list); - case 5 : return process_5(arg_list); - default : - { - T result = T(value(arg_list[0])); - - for (std::size_t i = 1; i < arg_list.size(); ++i) - { - const T v = value(arg_list[i]); - - if (v < result) - result = v; - } - - return result; - } - } - } - - template - static inline T process_1(const Sequence& arg_list) - { - return value(arg_list[0]); - } - - template - static inline T process_2(const Sequence& arg_list) - { - return std::min(value(arg_list[0]),value(arg_list[1])); - } - - template - static inline T process_3(const Sequence& arg_list) - { - return std::min(std::min(value(arg_list[0]),value(arg_list[1])),value(arg_list[2])); - } - - template - static inline T process_4(const Sequence& arg_list) - { - return std::min( - std::min(value(arg_list[0]), value(arg_list[1])), - std::min(value(arg_list[2]), value(arg_list[3]))); - } - - template - static inline T process_5(const Sequence& arg_list) - { - return std::min( - std::min(std::min(value(arg_list[0]), value(arg_list[1])), - std::min(value(arg_list[2]), value(arg_list[3]))), - value(arg_list[4])); - } - }; - - template - struct vararg_max_op : public opr_base - { - typedef typename opr_base::Type Type; - - template class Sequence> - static inline T process(const Sequence& arg_list) - { - switch (arg_list.size()) - { - case 0 : return T(0); - case 1 : return process_1(arg_list); - case 2 : return process_2(arg_list); - case 3 : return process_3(arg_list); - case 4 : return process_4(arg_list); - case 5 : return process_5(arg_list); - default : - { - T result = T(value(arg_list[0])); - - for (std::size_t i = 1; i < arg_list.size(); ++i) - { - const T v = value(arg_list[i]); - - if (v > result) - result = v; - } - - return result; - } - } - } - - template - static inline T process_1(const Sequence& arg_list) - { - return value(arg_list[0]); - } - - template - static inline T process_2(const Sequence& arg_list) - { - return std::max(value(arg_list[0]),value(arg_list[1])); - } - - template - static inline T process_3(const Sequence& arg_list) - { - return std::max(std::max(value(arg_list[0]),value(arg_list[1])),value(arg_list[2])); - } - - template - static inline T process_4(const Sequence& arg_list) - { - return std::max( - std::max(value(arg_list[0]), value(arg_list[1])), - std::max(value(arg_list[2]), value(arg_list[3]))); - } - - template - static inline T process_5(const Sequence& arg_list) - { - return std::max( - std::max(std::max(value(arg_list[0]), value(arg_list[1])), - std::max(value(arg_list[2]), value(arg_list[3]))), - value(arg_list[4])); - } - }; - - template - struct vararg_mand_op : public opr_base - { - typedef typename opr_base::Type Type; - - template class Sequence> - static inline T process(const Sequence& arg_list) - { - switch (arg_list.size()) - { - case 1 : return process_1(arg_list); - case 2 : return process_2(arg_list); - case 3 : return process_3(arg_list); - case 4 : return process_4(arg_list); - case 5 : return process_5(arg_list); - default : - { - for (std::size_t i = 0; i < arg_list.size(); ++i) - { - if (std::equal_to()(T(0), value(arg_list[i]))) - return T(0); - } - - return T(1); - } - } - } - - template - static inline T process_1(const Sequence& arg_list) - { - return std::not_equal_to() - (T(0), value(arg_list[0])) ? T(1) : T(0); - } - - template - static inline T process_2(const Sequence& arg_list) - { - return ( - std::not_equal_to()(T(0), value(arg_list[0])) && - std::not_equal_to()(T(0), value(arg_list[1])) - ) ? T(1) : T(0); - } - - template - static inline T process_3(const Sequence& arg_list) - { - return ( - std::not_equal_to()(T(0), value(arg_list[0])) && - std::not_equal_to()(T(0), value(arg_list[1])) && - std::not_equal_to()(T(0), value(arg_list[2])) - ) ? T(1) : T(0); - } - - template - static inline T process_4(const Sequence& arg_list) - { - return ( - std::not_equal_to()(T(0), value(arg_list[0])) && - std::not_equal_to()(T(0), value(arg_list[1])) && - std::not_equal_to()(T(0), value(arg_list[2])) && - std::not_equal_to()(T(0), value(arg_list[3])) - ) ? T(1) : T(0); - } - - template - static inline T process_5(const Sequence& arg_list) - { - return ( - std::not_equal_to()(T(0), value(arg_list[0])) && - std::not_equal_to()(T(0), value(arg_list[1])) && - std::not_equal_to()(T(0), value(arg_list[2])) && - std::not_equal_to()(T(0), value(arg_list[3])) && - std::not_equal_to()(T(0), value(arg_list[4])) - ) ? T(1) : T(0); - } - }; - - template - struct vararg_mor_op : public opr_base - { - typedef typename opr_base::Type Type; - - template class Sequence> - static inline T process(const Sequence& arg_list) - { - switch (arg_list.size()) - { - case 1 : return process_1(arg_list); - case 2 : return process_2(arg_list); - case 3 : return process_3(arg_list); - case 4 : return process_4(arg_list); - case 5 : return process_5(arg_list); - default : - { - for (std::size_t i = 0; i < arg_list.size(); ++i) - { - if (std::not_equal_to()(T(0), value(arg_list[i]))) - return T(1); - } - - return T(0); - } - } - } - - template - static inline T process_1(const Sequence& arg_list) - { - return std::not_equal_to() - (T(0), value(arg_list[0])) ? T(1) : T(0); - } - - template - static inline T process_2(const Sequence& arg_list) - { - return ( - std::not_equal_to()(T(0), value(arg_list[0])) || - std::not_equal_to()(T(0), value(arg_list[1])) - ) ? T(1) : T(0); - } - - template - static inline T process_3(const Sequence& arg_list) - { - return ( - std::not_equal_to()(T(0), value(arg_list[0])) || - std::not_equal_to()(T(0), value(arg_list[1])) || - std::not_equal_to()(T(0), value(arg_list[2])) - ) ? T(1) : T(0); - } - - template - static inline T process_4(const Sequence& arg_list) - { - return ( - std::not_equal_to()(T(0), value(arg_list[0])) || - std::not_equal_to()(T(0), value(arg_list[1])) || - std::not_equal_to()(T(0), value(arg_list[2])) || - std::not_equal_to()(T(0), value(arg_list[3])) - ) ? T(1) : T(0); - } - - template - static inline T process_5(const Sequence& arg_list) - { - return ( - std::not_equal_to()(T(0), value(arg_list[0])) || - std::not_equal_to()(T(0), value(arg_list[1])) || - std::not_equal_to()(T(0), value(arg_list[2])) || - std::not_equal_to()(T(0), value(arg_list[3])) || - std::not_equal_to()(T(0), value(arg_list[4])) - ) ? T(1) : T(0); - } - }; - - template - struct vararg_multi_op : public opr_base - { - typedef typename opr_base::Type Type; - - template class Sequence> - static inline T process(const Sequence& arg_list) - { - switch (arg_list.size()) - { - case 0 : return std::numeric_limits::quiet_NaN(); - case 1 : return process_1(arg_list); - case 2 : return process_2(arg_list); - case 3 : return process_3(arg_list); - case 4 : return process_4(arg_list); - case 5 : return process_5(arg_list); - case 6 : return process_6(arg_list); - case 7 : return process_7(arg_list); - case 8 : return process_8(arg_list); - default : - { - for (std::size_t i = 0; i < (arg_list.size() - 1); ++i) - { - value(arg_list[i]); - } - - return value(arg_list.back()); - } - } - } - - template - static inline T process_1(const Sequence& arg_list) - { - return value(arg_list[0]); - } - - template - static inline T process_2(const Sequence& arg_list) - { - value(arg_list[0]); - return value(arg_list[1]); - } - - template - static inline T process_3(const Sequence& arg_list) - { - value(arg_list[0]); - value(arg_list[1]); - return value(arg_list[2]); - } - - template - static inline T process_4(const Sequence& arg_list) - { - value(arg_list[0]); - value(arg_list[1]); - value(arg_list[2]); - return value(arg_list[3]); - } - - template - static inline T process_5(const Sequence& arg_list) - { - value(arg_list[0]); - value(arg_list[1]); - value(arg_list[2]); - value(arg_list[3]); - return value(arg_list[4]); - } - - template - static inline T process_6(const Sequence& arg_list) - { - value(arg_list[0]); - value(arg_list[1]); - value(arg_list[2]); - value(arg_list[3]); - value(arg_list[4]); - return value(arg_list[5]); - } - - template - static inline T process_7(const Sequence& arg_list) - { - value(arg_list[0]); - value(arg_list[1]); - value(arg_list[2]); - value(arg_list[3]); - value(arg_list[4]); - value(arg_list[5]); - return value(arg_list[6]); - } - - template - static inline T process_8(const Sequence& arg_list) - { - value(arg_list[0]); - value(arg_list[1]); - value(arg_list[2]); - value(arg_list[3]); - value(arg_list[4]); - value(arg_list[5]); - value(arg_list[6]); - return value(arg_list[7]); - } - }; - - template - struct vec_add_op - { - typedef vector_interface* ivector_ptr; - - static inline T process(const ivector_ptr v) - { - const T* vec = v->vec()->vds().data(); - const std::size_t vec_size = v->vec()->vds().size(); - - loop_unroll::details lud(vec_size); - - if (vec_size <= static_cast(lud.batch_size)) - { - T result = T(0); - int i = 0; - - exprtk_disable_fallthrough_begin - switch (vec_size) - { - #define case_stmt(N) \ - case N : result += vec[i++]; \ - - #ifndef exprtk_disable_superscalar_unroll - case_stmt(16) case_stmt(15) - case_stmt(14) case_stmt(13) - case_stmt(12) case_stmt(11) - case_stmt(10) case_stmt( 9) - case_stmt( 8) case_stmt( 7) - case_stmt( 6) case_stmt( 5) - #endif - case_stmt( 4) case_stmt( 3) - case_stmt( 2) case_stmt( 1) - } - exprtk_disable_fallthrough_end - - #undef case_stmt - - return result; - } - - T r[] = { - T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0), - T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0) - }; - - const T* upper_bound = vec + lud.upper_bound; - - while (vec < upper_bound) - { - #define exprtk_loop(N) \ - r[N] += vec[N]; \ - - exprtk_loop( 0) exprtk_loop( 1) - exprtk_loop( 2) exprtk_loop( 3) - #ifndef exprtk_disable_superscalar_unroll - exprtk_loop( 4) exprtk_loop( 5) - exprtk_loop( 6) exprtk_loop( 7) - exprtk_loop( 8) exprtk_loop( 9) - exprtk_loop(10) exprtk_loop(11) - exprtk_loop(12) exprtk_loop(13) - exprtk_loop(14) exprtk_loop(15) - #endif - - vec += lud.batch_size; - } - - int i = 0; - - exprtk_disable_fallthrough_begin - switch (lud.remainder) - { - #define case_stmt(N) \ - case N : r[0] += vec[i++]; \ - - #ifndef exprtk_disable_superscalar_unroll - case_stmt(15) case_stmt(14) - case_stmt(13) case_stmt(12) - case_stmt(11) case_stmt(10) - case_stmt( 9) case_stmt( 8) - case_stmt( 7) case_stmt( 6) - case_stmt( 5) case_stmt( 4) - #endif - case_stmt( 3) case_stmt( 2) - case_stmt( 1) - } - exprtk_disable_fallthrough_end - - #undef exprtk_loop - #undef case_stmt - - return (r[ 0] + r[ 1] + r[ 2] + r[ 3]) - #ifndef exprtk_disable_superscalar_unroll - + (r[ 4] + r[ 5] + r[ 6] + r[ 7]) - + (r[ 8] + r[ 9] + r[10] + r[11]) - + (r[12] + r[13] + r[14] + r[15]) - #endif - ; - } - }; - - template - struct vec_mul_op - { - typedef vector_interface* ivector_ptr; - - static inline T process(const ivector_ptr v) - { - const T* vec = v->vec()->vds().data(); - const std::size_t vec_size = v->vec()->vds().size(); - - loop_unroll::details lud(vec_size); - - if (vec_size <= static_cast(lud.batch_size)) - { - T result = T(1); - int i = 0; - - exprtk_disable_fallthrough_begin - switch (vec_size) - { - #define case_stmt(N) \ - case N : result *= vec[i++]; \ - - #ifndef exprtk_disable_superscalar_unroll - case_stmt(16) case_stmt(15) - case_stmt(14) case_stmt(13) - case_stmt(12) case_stmt(11) - case_stmt(10) case_stmt( 9) - case_stmt( 8) case_stmt( 7) - case_stmt( 6) case_stmt( 5) - #endif - case_stmt( 4) case_stmt( 3) - case_stmt( 2) case_stmt( 1) - } - exprtk_disable_fallthrough_end - - #undef case_stmt - - return result; - } - - T r[] = { - T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1), - T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1) - }; - - const T* upper_bound = vec + lud.upper_bound; - - while (vec < upper_bound) - { - #define exprtk_loop(N) \ - r[N] *= vec[N]; \ - - exprtk_loop( 0) exprtk_loop( 1) - exprtk_loop( 2) exprtk_loop( 3) - #ifndef exprtk_disable_superscalar_unroll - exprtk_loop( 4) exprtk_loop( 5) - exprtk_loop( 6) exprtk_loop( 7) - exprtk_loop( 8) exprtk_loop( 9) - exprtk_loop(10) exprtk_loop(11) - exprtk_loop(12) exprtk_loop(13) - exprtk_loop(14) exprtk_loop(15) - #endif - - vec += lud.batch_size; - } - - int i = 0; - - exprtk_disable_fallthrough_begin - switch (lud.remainder) - { - #define case_stmt(N) \ - case N : r[0] *= vec[i++]; \ - - #ifndef exprtk_disable_superscalar_unroll - case_stmt(15) case_stmt(14) - case_stmt(13) case_stmt(12) - case_stmt(11) case_stmt(10) - case_stmt( 9) case_stmt( 8) - case_stmt( 7) case_stmt( 6) - case_stmt( 5) case_stmt( 4) - #endif - case_stmt( 3) case_stmt( 2) - case_stmt( 1) - } - exprtk_disable_fallthrough_end - - #undef exprtk_loop - #undef case_stmt - - return (r[ 0] * r[ 1] * r[ 2] * r[ 3]) - #ifndef exprtk_disable_superscalar_unroll - + (r[ 4] * r[ 5] * r[ 6] * r[ 7]) - + (r[ 8] * r[ 9] * r[10] * r[11]) - + (r[12] * r[13] * r[14] * r[15]) - #endif - ; - } - }; - - template - struct vec_avg_op - { - typedef vector_interface* ivector_ptr; - - static inline T process(const ivector_ptr v) - { - const std::size_t vec_size = v->vec()->vds().size(); - - return vec_add_op::process(v) / vec_size; - } - }; - - template - struct vec_min_op - { - typedef vector_interface* ivector_ptr; - - static inline T process(const ivector_ptr v) - { - const T* vec = v->vec()->vds().data(); - const std::size_t vec_size = v->vec()->vds().size(); - - T result = vec[0]; - - for (std::size_t i = 1; i < vec_size; ++i) - { - const T v_i = vec[i]; - - if (v_i < result) - result = v_i; - } - - return result; - } - }; - - template - struct vec_max_op - { - typedef vector_interface* ivector_ptr; - - static inline T process(const ivector_ptr v) - { - const T* vec = v->vec()->vds().data(); - const std::size_t vec_size = v->vec()->vds().size(); - - T result = vec[0]; - - for (std::size_t i = 1; i < vec_size; ++i) - { - const T v_i = vec[i]; - - if (v_i > result) - result = v_i; - } - - return result; - } - }; - - template - class vov_base_node : public expression_node - { - public: - - virtual ~vov_base_node() - {} - - inline virtual operator_type operation() const - { - return details::e_default; - } - - virtual const T& v0() const = 0; - - virtual const T& v1() const = 0; - }; - - template - class cov_base_node : public expression_node - { - public: - - virtual ~cov_base_node() - {} - - inline virtual operator_type operation() const - { - return details::e_default; - } - - virtual const T c() const = 0; - - virtual const T& v() const = 0; - }; - - template - class voc_base_node : public expression_node - { - public: - - virtual ~voc_base_node() - {} - - inline virtual operator_type operation() const - { - return details::e_default; - } - - virtual const T c() const = 0; - - virtual const T& v() const = 0; - }; - - template - class vob_base_node : public expression_node - { - public: - - virtual ~vob_base_node() - {} - - virtual const T& v() const = 0; - }; - - template - class bov_base_node : public expression_node - { - public: - - virtual ~bov_base_node() - {} - - virtual const T& v() const = 0; - }; - - template - class cob_base_node : public expression_node - { - public: - - virtual ~cob_base_node() - {} - - inline virtual operator_type operation() const - { - return details::e_default; - } - - virtual const T c() const = 0; - - virtual void set_c(const T) = 0; - - virtual expression_node* move_branch(const std::size_t& index) = 0; - }; - - template - class boc_base_node : public expression_node - { - public: - - virtual ~boc_base_node() - {} - - inline virtual operator_type operation() const - { - return details::e_default; - } - - virtual const T c() const = 0; - - virtual void set_c(const T) = 0; - - virtual expression_node* move_branch(const std::size_t& index) = 0; - }; - - template - class uv_base_node : public expression_node - { - public: - - virtual ~uv_base_node() - {} - - inline virtual operator_type operation() const - { - return details::e_default; - } - - virtual const T& v() const = 0; - }; - - template - class sos_base_node : public expression_node - { - public: - - virtual ~sos_base_node() - {} - - inline virtual operator_type operation() const - { - return details::e_default; - } - }; - - template - class sosos_base_node : public expression_node - { - public: - - virtual ~sosos_base_node() - {} - - inline virtual operator_type operation() const - { - return details::e_default; - } - }; - - template - class T0oT1oT2_base_node : public expression_node - { - public: - - virtual ~T0oT1oT2_base_node() - {} - - virtual std::string type_id() const = 0; - }; - - template - class T0oT1oT2oT3_base_node : public expression_node - { - public: - - virtual ~T0oT1oT2oT3_base_node() - {} - - virtual std::string type_id() const = 0; - }; - - template - class unary_variable_node exprtk_final : public uv_base_node - { - public: - - typedef expression_node* expression_ptr; - typedef Operation operation_t; - - explicit unary_variable_node(const T& var) - : v_(var) - {} - - inline T value() const - { - return Operation::process(v_); - } - - inline typename expression_node::node_type type() const - { - return Operation::type(); - } - - inline operator_type operation() const - { - return Operation::operation(); - } - - inline const T& v() const - { - return v_; - } - - private: - - unary_variable_node(unary_variable_node&); - unary_variable_node& operator=(unary_variable_node&); - - const T& v_; - }; - - template - class uvouv_node exprtk_final : public expression_node - { - public: - - // UOpr1(v0) Op UOpr2(v1) - - typedef expression_node* expression_ptr; - typedef typename details::functor_t functor_t; - typedef typename functor_t::bfunc_t bfunc_t; - typedef typename functor_t::ufunc_t ufunc_t; - - explicit uvouv_node(const T& var0,const T& var1, - ufunc_t uf0, ufunc_t uf1, bfunc_t bf) - : v0_(var0), - v1_(var1), - u0_(uf0 ), - u1_(uf1 ), - f_ (bf ) - {} - - inline T value() const - { - return f_(u0_(v0_),u1_(v1_)); - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_uvouv; - } - - inline operator_type operation() const - { - return details::e_default; - } - - inline const T& v0() - { - return v0_; - } - - inline const T& v1() - { - return v1_; - } - - inline ufunc_t u0() - { - return u0_; - } - - inline ufunc_t u1() - { - return u1_; - } - - inline ufunc_t f() - { - return f_; - } - - private: - - uvouv_node(uvouv_node&); - uvouv_node& operator=(uvouv_node&); - - const T& v0_; - const T& v1_; - const ufunc_t u0_; - const ufunc_t u1_; - const bfunc_t f_; - }; - - template - class unary_branch_node exprtk_final : public expression_node - { - public: - - typedef expression_node* expression_ptr; - typedef std::pair branch_t; - typedef Operation operation_t; - - explicit unary_branch_node(expression_ptr branch) - { - construct_branch_pair(branch_, branch); - } - - inline T value() const - { - return Operation::process(branch_.first->value()); - } - - inline typename expression_node::node_type type() const - { - return Operation::type(); - } - - inline operator_type operation() const - { - return Operation::operation(); - } - - inline expression_node* branch(const std::size_t&) const - { - return branch_.first; - } - - inline void release() - { - branch_.second = false; - } - - void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) - { - expression_node::ndb_t::collect(branch_, node_delete_list); - } - - std::size_t node_depth() const - { - return expression_node::ndb_t::compute_node_depth(branch_); - } - - private: - - unary_branch_node(unary_branch_node&); - unary_branch_node& operator=(unary_branch_node&); - - branch_t branch_; - }; - - template struct is_const { enum {result = 0}; }; - template struct is_const { enum {result = 1}; }; - template struct is_const_ref { enum {result = 0}; }; - template struct is_const_ref { enum {result = 1}; }; - template struct is_ref { enum {result = 0}; }; - template struct is_ref { enum {result = 1}; }; - template struct is_ref { enum {result = 0}; }; - - template - struct param_to_str { static std::string result() { static const std::string r("v"); return r; } }; - - template <> - struct param_to_str<0> { static std::string result() { static const std::string r("c"); return r; } }; - - #define exprtk_crtype(Type) \ - param_to_str::result>::result() \ - - template - struct T0oT1oT2process - { - typedef typename details::functor_t functor_t; - typedef typename functor_t::bfunc_t bfunc_t; - - struct mode0 - { - static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1) - { - // (T0 o0 T1) o1 T2 - return bf1(bf0(t0,t1),t2); - } - - template - static inline std::string id() - { - static const std::string result = "(" + exprtk_crtype(T0) + "o" + - exprtk_crtype(T1) + ")o(" + - exprtk_crtype(T2) + ")" ; - return result; - } - }; - - struct mode1 - { - static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1) - { - // T0 o0 (T1 o1 T2) - return bf0(t0,bf1(t1,t2)); - } - - template - static inline std::string id() - { - static const std::string result = "(" + exprtk_crtype(T0) + ")o(" + - exprtk_crtype(T1) + "o" + - exprtk_crtype(T2) + ")" ; - return result; - } - }; - }; - - template - struct T0oT1oT20T3process - { - typedef typename details::functor_t functor_t; - typedef typename functor_t::bfunc_t bfunc_t; - - struct mode0 - { - static inline T process(const T& t0, const T& t1, - const T& t2, const T& t3, - const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) - { - // (T0 o0 T1) o1 (T2 o2 T3) - return bf1(bf0(t0,t1),bf2(t2,t3)); - } - - template - static inline std::string id() - { - static const std::string result = "(" + exprtk_crtype(T0) + "o" + - exprtk_crtype(T1) + ")o" + - "(" + exprtk_crtype(T2) + "o" + - exprtk_crtype(T3) + ")" ; - return result; - } - }; - - struct mode1 - { - static inline T process(const T& t0, const T& t1, - const T& t2, const T& t3, - const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) - { - // (T0 o0 (T1 o1 (T2 o2 T3)) - return bf0(t0,bf1(t1,bf2(t2,t3))); - } - template - static inline std::string id() - { - static const std::string result = "(" + exprtk_crtype(T0) + ")o((" + - exprtk_crtype(T1) + ")o(" + - exprtk_crtype(T2) + "o" + - exprtk_crtype(T3) + "))" ; - return result; - } - }; - - struct mode2 - { - static inline T process(const T& t0, const T& t1, - const T& t2, const T& t3, - const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) - { - // (T0 o0 ((T1 o1 T2) o2 T3) - return bf0(t0,bf2(bf1(t1,t2),t3)); - } - - template - static inline std::string id() - { - static const std::string result = "(" + exprtk_crtype(T0) + ")o((" + - exprtk_crtype(T1) + "o" + - exprtk_crtype(T2) + ")o(" + - exprtk_crtype(T3) + "))" ; - return result; - } - }; - - struct mode3 - { - static inline T process(const T& t0, const T& t1, - const T& t2, const T& t3, - const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) - { - // (((T0 o0 T1) o1 T2) o2 T3) - return bf2(bf1(bf0(t0,t1),t2),t3); - } - - template - static inline std::string id() - { - static const std::string result = "((" + exprtk_crtype(T0) + "o" + - exprtk_crtype(T1) + ")o(" + - exprtk_crtype(T2) + "))o(" + - exprtk_crtype(T3) + ")"; - return result; - } - }; - - struct mode4 - { - static inline T process(const T& t0, const T& t1, - const T& t2, const T& t3, - const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) - { - // ((T0 o0 (T1 o1 T2)) o2 T3 - return bf2(bf0(t0,bf1(t1,t2)),t3); - } - - template - static inline std::string id() - { - static const std::string result = "((" + exprtk_crtype(T0) + ")o(" + - exprtk_crtype(T1) + "o" + - exprtk_crtype(T2) + "))o(" + - exprtk_crtype(T3) + ")" ; - return result; - } - }; - }; - - #undef exprtk_crtype - - template - struct nodetype_T0oT1 { static const typename expression_node::node_type result; }; - template - const typename expression_node::node_type nodetype_T0oT1::result = expression_node::e_none; - - #define synthesis_node_type_define(T0_,T1_,v_) \ - template \ - struct nodetype_T0oT1 { static const typename expression_node::node_type result; }; \ - template \ - const typename expression_node::node_type nodetype_T0oT1::result = expression_node:: v_; \ - - synthesis_node_type_define(const T0&, const T1&, e_vov) - synthesis_node_type_define(const T0&, const T1 , e_voc) - synthesis_node_type_define(const T0 , const T1&, e_cov) - synthesis_node_type_define( T0&, T1&, e_none) - synthesis_node_type_define(const T0 , const T1 , e_none) - synthesis_node_type_define( T0&, const T1 , e_none) - synthesis_node_type_define(const T0 , T1&, e_none) - synthesis_node_type_define(const T0&, T1&, e_none) - synthesis_node_type_define( T0&, const T1&, e_none) - #undef synthesis_node_type_define - - template - struct nodetype_T0oT1oT2 { static const typename expression_node::node_type result; }; - template - const typename expression_node::node_type nodetype_T0oT1oT2::result = expression_node::e_none; - - #define synthesis_node_type_define(T0_,T1_,T2_,v_) \ - template \ - struct nodetype_T0oT1oT2 { static const typename expression_node::node_type result; }; \ - template \ - const typename expression_node::node_type nodetype_T0oT1oT2::result = expression_node:: v_; \ - - synthesis_node_type_define(const T0&, const T1&, const T2&, e_vovov) - synthesis_node_type_define(const T0&, const T1&, const T2 , e_vovoc) - synthesis_node_type_define(const T0&, const T1 , const T2&, e_vocov) - synthesis_node_type_define(const T0 , const T1&, const T2&, e_covov) - synthesis_node_type_define(const T0 , const T1&, const T2 , e_covoc) - synthesis_node_type_define(const T0 , const T1 , const T2 , e_none ) - synthesis_node_type_define(const T0 , const T1 , const T2&, e_none ) - synthesis_node_type_define(const T0&, const T1 , const T2 , e_none ) - synthesis_node_type_define( T0&, T1&, T2&, e_none ) - #undef synthesis_node_type_define - - template - struct nodetype_T0oT1oT2oT3 { static const typename expression_node::node_type result; }; - template - const typename expression_node::node_type nodetype_T0oT1oT2oT3::result = expression_node::e_none; - - #define synthesis_node_type_define(T0_,T1_,T2_,T3_,v_) \ - template \ - struct nodetype_T0oT1oT2oT3 { static const typename expression_node::node_type result; }; \ - template \ - const typename expression_node::node_type nodetype_T0oT1oT2oT3::result = expression_node:: v_; \ - - synthesis_node_type_define(const T0&, const T1&, const T2&, const T3&, e_vovovov) - synthesis_node_type_define(const T0&, const T1&, const T2&, const T3 , e_vovovoc) - synthesis_node_type_define(const T0&, const T1&, const T2 , const T3&, e_vovocov) - synthesis_node_type_define(const T0&, const T1 , const T2&, const T3&, e_vocovov) - synthesis_node_type_define(const T0 , const T1&, const T2&, const T3&, e_covovov) - synthesis_node_type_define(const T0 , const T1&, const T2 , const T3&, e_covocov) - synthesis_node_type_define(const T0&, const T1 , const T2&, const T3 , e_vocovoc) - synthesis_node_type_define(const T0 , const T1&, const T2&, const T3 , e_covovoc) - synthesis_node_type_define(const T0&, const T1 , const T2 , const T3&, e_vococov) - synthesis_node_type_define(const T0 , const T1 , const T2 , const T3 , e_none ) - synthesis_node_type_define(const T0 , const T1 , const T2 , const T3&, e_none ) - synthesis_node_type_define(const T0 , const T1 , const T2&, const T3 , e_none ) - synthesis_node_type_define(const T0 , const T1&, const T2 , const T3 , e_none ) - synthesis_node_type_define(const T0&, const T1 , const T2 , const T3 , e_none ) - synthesis_node_type_define(const T0 , const T1 , const T2&, const T3&, e_none ) - synthesis_node_type_define(const T0&, const T1&, const T2 , const T3 , e_none ) - #undef synthesis_node_type_define - - template - class T0oT1 exprtk_final : public expression_node - { - public: - - typedef typename details::functor_t functor_t; - typedef typename functor_t::bfunc_t bfunc_t; - typedef T value_type; - typedef T0oT1 node_type; - - T0oT1(T0 p0, T1 p1, const bfunc_t p2) - : t0_(p0), - t1_(p1), - f_ (p2) - {} - - inline typename expression_node::node_type type() const - { - static const typename expression_node::node_type result = nodetype_T0oT1::result; - return result; - } - - inline operator_type operation() const - { - return e_default; - } - - inline T value() const - { - return f_(t0_,t1_); - } - - inline T0 t0() const - { - return t0_; - } - - inline T1 t1() const - { - return t1_; - } - - inline bfunc_t f() const - { - return f_; - } - - template - static inline expression_node* allocate(Allocator& allocator, - T0 p0, T1 p1, - bfunc_t p2) - { - return allocator - .template allocate_type - (p0, p1, p2); - } - - private: - - T0oT1(T0oT1&) {} - T0oT1& operator=(T0oT1&) { return (*this); } - - T0 t0_; - T1 t1_; - const bfunc_t f_; - }; - - template - class T0oT1oT2 exprtk_final : public T0oT1oT2_base_node - { - public: - - typedef typename details::functor_t functor_t; - typedef typename functor_t::bfunc_t bfunc_t; - typedef T value_type; - typedef T0oT1oT2 node_type; - typedef ProcessMode process_mode_t; - - T0oT1oT2(T0 p0, T1 p1, T2 p2, const bfunc_t p3, const bfunc_t p4) - : t0_(p0), - t1_(p1), - t2_(p2), - f0_(p3), - f1_(p4) - {} - - inline typename expression_node::node_type type() const - { - static const typename expression_node::node_type result = nodetype_T0oT1oT2::result; - return result; - } - - inline operator_type operation() const - { - return e_default; - } - - inline T value() const - { - return ProcessMode::process(t0_, t1_, t2_, f0_, f1_); - } - - inline T0 t0() const - { - return t0_; - } - - inline T1 t1() const - { - return t1_; - } - - inline T2 t2() const - { - return t2_; - } - - bfunc_t f0() const - { - return f0_; - } - - bfunc_t f1() const - { - return f1_; - } - - std::string type_id() const - { - return id(); - } - - static inline std::string id() - { - return process_mode_t::template id(); - } - - template - static inline expression_node* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, bfunc_t p3, bfunc_t p4) - { - return allocator - .template allocate_type - (p0, p1, p2, p3, p4); - } - - private: - - T0oT1oT2(node_type&) {} - node_type& operator=(node_type&) { return (*this); } - - T0 t0_; - T1 t1_; - T2 t2_; - const bfunc_t f0_; - const bfunc_t f1_; - }; - - template - class T0oT1oT2oT3 exprtk_final : public T0oT1oT2oT3_base_node - { - public: - - typedef typename details::functor_t functor_t; - typedef typename functor_t::bfunc_t bfunc_t; - typedef T value_type; - typedef T0_ T0; - typedef T1_ T1; - typedef T2_ T2; - typedef T3_ T3; - typedef T0oT1oT2oT3 node_type; - typedef ProcessMode process_mode_t; - - T0oT1oT2oT3(T0 p0, T1 p1, T2 p2, T3 p3, bfunc_t p4, bfunc_t p5, bfunc_t p6) - : t0_(p0), - t1_(p1), - t2_(p2), - t3_(p3), - f0_(p4), - f1_(p5), - f2_(p6) - {} - - inline T value() const - { - return ProcessMode::process(t0_, t1_, t2_, t3_, f0_, f1_, f2_); - } - - inline T0 t0() const - { - return t0_; - } - - inline T1 t1() const - { - return t1_; - } - - inline T2 t2() const - { - return t2_; - } - - inline T3 t3() const - { - return t3_; - } - - inline bfunc_t f0() const - { - return f0_; - } - - inline bfunc_t f1() const - { - return f1_; - } - - inline bfunc_t f2() const - { - return f2_; - } - - inline std::string type_id() const - { - return id(); - } - - static inline std::string id() - { - return process_mode_t::template id(); - } - - template - static inline expression_node* allocate(Allocator& allocator, - T0 p0, T1 p1, T2 p2, T3 p3, - bfunc_t p4, bfunc_t p5, bfunc_t p6) - { - return allocator - .template allocate_type - (p0, p1, p2, p3, p4, p5, p6); - } - - private: - - T0oT1oT2oT3(node_type&) {} - node_type& operator=(node_type&) { return (*this); } - - T0 t0_; - T1 t1_; - T2 t2_; - T3 t3_; - const bfunc_t f0_; - const bfunc_t f1_; - const bfunc_t f2_; - }; - - template - class T0oT1oT2_sf3 exprtk_final : public T0oT1oT2_base_node - { - public: - - typedef typename details::functor_t functor_t; - typedef typename functor_t::tfunc_t tfunc_t; - typedef T value_type; - typedef T0oT1oT2_sf3 node_type; - - T0oT1oT2_sf3(T0 p0, T1 p1, T2 p2, const tfunc_t p3) - : t0_(p0), - t1_(p1), - t2_(p2), - f_ (p3) - {} - - inline typename expression_node::node_type type() const - { - static const typename expression_node::node_type result = nodetype_T0oT1oT2::result; - return result; - } - - inline operator_type operation() const - { - return e_default; - } - - inline T value() const - { - return f_(t0_, t1_, t2_); - } - - inline T0 t0() const - { - return t0_; - } - - inline T1 t1() const - { - return t1_; - } - - inline T2 t2() const - { - return t2_; - } - - tfunc_t f() const - { - return f_; - } - - std::string type_id() const - { - return id(); - } - - static inline std::string id() - { - return "sf3"; - } - - template - static inline expression_node* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, tfunc_t p3) - { - return allocator - .template allocate_type - (p0, p1, p2, p3); - } - - private: - - T0oT1oT2_sf3(node_type&) {} - node_type& operator=(node_type&) { return (*this); } - - T0 t0_; - T1 t1_; - T2 t2_; - const tfunc_t f_; - }; - - template - class sf3ext_type_node : public T0oT1oT2_base_node - { - public: - - virtual ~sf3ext_type_node() - {} - - virtual T0 t0() const = 0; - - virtual T1 t1() const = 0; - - virtual T2 t2() const = 0; - }; - - template - class T0oT1oT2_sf3ext exprtk_final : public sf3ext_type_node - { - public: - - typedef typename details::functor_t functor_t; - typedef typename functor_t::tfunc_t tfunc_t; - typedef T value_type; - typedef T0oT1oT2_sf3ext node_type; - - T0oT1oT2_sf3ext(T0 p0, T1 p1, T2 p2) - : t0_(p0), - t1_(p1), - t2_(p2) - {} - - inline typename expression_node::node_type type() const - { - static const typename expression_node::node_type result = nodetype_T0oT1oT2::result; - return result; - } - - inline operator_type operation() const - { - return e_default; - } - - inline T value() const - { - return SF3Operation::process(t0_, t1_, t2_); - } - - T0 t0() const - { - return t0_; - } - - T1 t1() const - { - return t1_; - } - - T2 t2() const - { - return t2_; - } - - std::string type_id() const - { - return id(); - } - - static inline std::string id() - { - return SF3Operation::id(); - } - - template - static inline expression_node* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2) - { - return allocator - .template allocate_type - (p0, p1, p2); - } - - private: - - T0oT1oT2_sf3ext(node_type&) {} - node_type& operator=(node_type&) { return (*this); } - - T0 t0_; - T1 t1_; - T2 t2_; - }; - - template - inline bool is_sf3ext_node(const expression_node* n) - { - switch (n->type()) - { - case expression_node::e_vovov : return true; - case expression_node::e_vovoc : return true; - case expression_node::e_vocov : return true; - case expression_node::e_covov : return true; - case expression_node::e_covoc : return true; - default : return false; - } - } - - template - class T0oT1oT2oT3_sf4 exprtk_final : public T0oT1oT2_base_node - { - public: - - typedef typename details::functor_t functor_t; - typedef typename functor_t::qfunc_t qfunc_t; - typedef T value_type; - typedef T0oT1oT2oT3_sf4 node_type; - - T0oT1oT2oT3_sf4(T0 p0, T1 p1, T2 p2, T3 p3, const qfunc_t p4) - : t0_(p0), - t1_(p1), - t2_(p2), - t3_(p3), - f_ (p4) - {} - - inline typename expression_node::node_type type() const - { - static const typename expression_node::node_type result = nodetype_T0oT1oT2oT3::result; - return result; - } - - inline operator_type operation() const - { - return e_default; - } - - inline T value() const - { - return f_(t0_, t1_, t2_, t3_); - } - - inline T0 t0() const - { - return t0_; - } - - inline T1 t1() const - { - return t1_; - } - - inline T2 t2() const - { - return t2_; - } - - inline T3 t3() const - { - return t3_; - } - - qfunc_t f() const - { - return f_; - } - - std::string type_id() const - { - return id(); - } - - static inline std::string id() - { - return "sf4"; - } - - template - static inline expression_node* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3, qfunc_t p4) - { - return allocator - .template allocate_type - (p0, p1, p2, p3, p4); - } - - private: - - T0oT1oT2oT3_sf4(node_type&) {} - node_type& operator=(node_type&) { return (*this); } - - T0 t0_; - T1 t1_; - T2 t2_; - T3 t3_; - const qfunc_t f_; - }; - - template - class T0oT1oT2oT3_sf4ext exprtk_final : public T0oT1oT2oT3_base_node - { - public: - - typedef typename details::functor_t functor_t; - typedef typename functor_t::tfunc_t tfunc_t; - typedef T value_type; - typedef T0oT1oT2oT3_sf4ext node_type; - - T0oT1oT2oT3_sf4ext(T0 p0, T1 p1, T2 p2, T3 p3) - : t0_(p0), - t1_(p1), - t2_(p2), - t3_(p3) - {} - - inline typename expression_node::node_type type() const - { - static const typename expression_node::node_type result = nodetype_T0oT1oT2oT3::result; - return result; - } - - inline operator_type operation() const - { - return e_default; - } - - inline T value() const - { - return SF4Operation::process(t0_, t1_, t2_, t3_); - } - - inline T0 t0() const - { - return t0_; - } - - inline T1 t1() const - { - return t1_; - } - - inline T2 t2() const - { - return t2_; - } - - inline T3 t3() const - { - return t3_; - } - - std::string type_id() const - { - return id(); - } - - static inline std::string id() - { - return SF4Operation::id(); - } - - template - static inline expression_node* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3) - { - return allocator - .template allocate_type - (p0, p1, p2, p3); - } - - private: - - T0oT1oT2oT3_sf4ext(node_type&) {} - node_type& operator=(node_type&) { return (*this); } - - T0 t0_; - T1 t1_; - T2 t2_; - T3 t3_; - }; - - template - inline bool is_sf4ext_node(const expression_node* n) - { - switch (n->type()) - { - case expression_node::e_vovovov : return true; - case expression_node::e_vovovoc : return true; - case expression_node::e_vovocov : return true; - case expression_node::e_vocovov : return true; - case expression_node::e_covovov : return true; - case expression_node::e_covocov : return true; - case expression_node::e_vocovoc : return true; - case expression_node::e_covovoc : return true; - case expression_node::e_vococov : return true; - default : return false; - } - } - - template - struct T0oT1_define - { - typedef details::T0oT1 type0; - }; - - template - struct T0oT1oT2_define - { - typedef details::T0oT1oT2::mode0> type0; - typedef details::T0oT1oT2::mode1> type1; - typedef details::T0oT1oT2_sf3 sf3_type; - typedef details::sf3ext_type_node sf3_type_node; - }; - - template - struct T0oT1oT2oT3_define - { - typedef details::T0oT1oT2oT3::mode0> type0; - typedef details::T0oT1oT2oT3::mode1> type1; - typedef details::T0oT1oT2oT3::mode2> type2; - typedef details::T0oT1oT2oT3::mode3> type3; - typedef details::T0oT1oT2oT3::mode4> type4; - typedef details::T0oT1oT2oT3_sf4 sf4_type; - }; - - template - class vov_node exprtk_final : public vov_base_node - { - public: - - typedef expression_node* expression_ptr; - typedef Operation operation_t; - - // variable op variable node - explicit vov_node(const T& var0, const T& var1) - : v0_(var0), - v1_(var1) - {} - - inline T value() const - { - return Operation::process(v0_,v1_); - } - - inline typename expression_node::node_type type() const - { - return Operation::type(); - } - - inline operator_type operation() const - { - return Operation::operation(); - } - - inline const T& v0() const - { - return v0_; - } - - inline const T& v1() const - { - return v1_; - } - - protected: - - const T& v0_; - const T& v1_; - - private: - - vov_node(vov_node&); - vov_node& operator=(vov_node&); - }; - - template - class cov_node exprtk_final : public cov_base_node - { - public: - - typedef expression_node* expression_ptr; - typedef Operation operation_t; - - // constant op variable node - explicit cov_node(const T& const_var, const T& var) - : c_(const_var), - v_(var) - {} - - inline T value() const - { - return Operation::process(c_,v_); - } - - inline typename expression_node::node_type type() const - { - return Operation::type(); - } - - inline operator_type operation() const - { - return Operation::operation(); - } - - inline const T c() const - { - return c_; - } - - inline const T& v() const - { - return v_; - } - - protected: - - const T c_; - const T& v_; - - private: - - cov_node(const cov_node&); - cov_node& operator=(const cov_node&); - }; - - template - class voc_node exprtk_final : public voc_base_node - { - public: - - typedef expression_node* expression_ptr; - typedef Operation operation_t; - - // variable op constant node - explicit voc_node(const T& var, const T& const_var) - : v_(var), - c_(const_var) - {} - - inline T value() const - { - return Operation::process(v_,c_); - } - - inline operator_type operation() const - { - return Operation::operation(); - } - - inline const T c() const - { - return c_; - } - - inline const T& v() const - { - return v_; - } - - protected: - - const T& v_; - const T c_; - - private: - - voc_node(const voc_node&); - voc_node& operator=(const voc_node&); - }; - - template - class vob_node exprtk_final : public vob_base_node - { - public: - - typedef expression_node* expression_ptr; - typedef std::pair branch_t; - typedef Operation operation_t; - - // variable op constant node - explicit vob_node(const T& var, const expression_ptr branch) - : v_(var) - { - construct_branch_pair(branch_, branch); - } - - inline T value() const - { - assert(branch_.first); - return Operation::process(v_,branch_.first->value()); - } - - inline operator_type operation() const - { - return Operation::operation(); - } - - inline const T& v() const - { - return v_; - } - - inline expression_node* branch(const std::size_t&) const - { - return branch_.first; - } - - void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) - { - expression_node::ndb_t::template collect(branch_, node_delete_list); - } - - std::size_t node_depth() const - { - return expression_node::ndb_t::compute_node_depth(branch_); - } - - private: - - vob_node(const vob_node&); - vob_node& operator=(const vob_node&); - - const T& v_; - branch_t branch_; - }; - - template - class bov_node exprtk_final : public bov_base_node - { - public: - - typedef expression_node* expression_ptr; - typedef std::pair branch_t; - typedef Operation operation_t; - - // variable op constant node - explicit bov_node(const expression_ptr branch, const T& var) - : v_(var) - { - construct_branch_pair(branch_, branch); - } - - inline T value() const - { - assert(branch_.first); - return Operation::process(branch_.first->value(),v_); - } - - inline operator_type operation() const - { - return Operation::operation(); - } - - inline const T& v() const - { - return v_; - } - - inline expression_node* branch(const std::size_t&) const - { - return branch_.first; - } - - void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) - { - expression_node::ndb_t::template collect(branch_, node_delete_list); - } - - std::size_t node_depth() const - { - return expression_node::ndb_t::compute_node_depth(branch_); - } - - private: - - bov_node(const bov_node&); - bov_node& operator=(const bov_node&); - - const T& v_; - branch_t branch_; - }; - - template - class cob_node exprtk_final : public cob_base_node - { - public: - - typedef expression_node* expression_ptr; - typedef std::pair branch_t; - typedef Operation operation_t; - - // variable op constant node - explicit cob_node(const T const_var, const expression_ptr branch) - : c_(const_var) - { - construct_branch_pair(branch_, branch); - } - - inline T value() const - { - assert(branch_.first); - return Operation::process(c_,branch_.first->value()); - } - - inline operator_type operation() const - { - return Operation::operation(); - } - - inline const T c() const - { - return c_; - } - - inline void set_c(const T new_c) - { - (*const_cast(&c_)) = new_c; - } - - inline expression_node* branch(const std::size_t&) const - { - return branch_.first; - } - - inline expression_node* move_branch(const std::size_t&) - { - branch_.second = false; - return branch_.first; - } - - void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) - { - expression_node::ndb_t::template collect(branch_, node_delete_list); - } - - std::size_t node_depth() const - { - return expression_node::ndb_t::compute_node_depth(branch_); - } - - private: - - cob_node(const cob_node&); - cob_node& operator=(const cob_node&); - - const T c_; - branch_t branch_; - }; - - template - class boc_node exprtk_final : public boc_base_node - { - public: - - typedef expression_node* expression_ptr; - typedef std::pair branch_t; - typedef Operation operation_t; - - // variable op constant node - explicit boc_node(const expression_ptr branch, const T const_var) - : c_(const_var) - { - construct_branch_pair(branch_, branch); - } - - inline T value() const - { - assert(branch_.first); - return Operation::process(branch_.first->value(),c_); - } - - inline operator_type operation() const - { - return Operation::operation(); - } - - inline const T c() const - { - return c_; - } - - inline void set_c(const T new_c) - { - (*const_cast(&c_)) = new_c; - } - - inline expression_node* branch(const std::size_t&) const - { - return branch_.first; - } - - inline expression_node* move_branch(const std::size_t&) - { - branch_.second = false; - return branch_.first; - } - - void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) - { - expression_node::ndb_t::template collect(branch_, node_delete_list); - } - - std::size_t node_depth() const - { - return expression_node::ndb_t::compute_node_depth(branch_); - } - - private: - - boc_node(const boc_node&); - boc_node& operator=(const boc_node&); - - const T c_; - branch_t branch_; - }; - - #ifndef exprtk_disable_string_capabilities - template - class sos_node exprtk_final : public sos_base_node - { - public: - - typedef expression_node* expression_ptr; - typedef Operation operation_t; - - // string op string node - explicit sos_node(SType0 p0, SType1 p1) - : s0_(p0), - s1_(p1) - {} - - inline T value() const - { - return Operation::process(s0_,s1_); - } - - inline typename expression_node::node_type type() const - { - return Operation::type(); - } - - inline operator_type operation() const - { - return Operation::operation(); - } - - inline std::string& s0() - { - return s0_; - } - - inline std::string& s1() - { - return s1_; - } - - protected: - - SType0 s0_; - SType1 s1_; - - private: - - sos_node(sos_node&); - sos_node& operator=(sos_node&); - }; - - template - class str_xrox_node exprtk_final : public sos_base_node - { - public: - - typedef expression_node* expression_ptr; - typedef Operation operation_t; - - // string-range op string node - explicit str_xrox_node(SType0 p0, SType1 p1, RangePack rp0) - : s0_ (p0 ), - s1_ (p1 ), - rp0_(rp0) - {} - - ~str_xrox_node() - { - rp0_.free(); - } - - inline T value() const - { - std::size_t r0 = 0; - std::size_t r1 = 0; - - if (rp0_(r0, r1, s0_.size())) - return Operation::process(s0_.substr(r0, (r1 - r0) + 1), s1_); - else - return T(0); - } - - inline typename expression_node::node_type type() const - { - return Operation::type(); - } - - inline operator_type operation() const - { - return Operation::operation(); - } - - inline std::string& s0() - { - return s0_; - } - - inline std::string& s1() - { - return s1_; - } - - protected: - - SType0 s0_; - SType1 s1_; - RangePack rp0_; - - private: - - str_xrox_node(str_xrox_node&); - str_xrox_node& operator=(str_xrox_node&); - }; - - template - class str_xoxr_node exprtk_final : public sos_base_node - { - public: - - typedef expression_node* expression_ptr; - typedef Operation operation_t; - - // string op string range node - explicit str_xoxr_node(SType0 p0, SType1 p1, RangePack rp1) - : s0_ (p0 ), - s1_ (p1 ), - rp1_(rp1) - {} - - ~str_xoxr_node() - { - rp1_.free(); - } - - inline T value() const - { - std::size_t r0 = 0; - std::size_t r1 = 0; - - if (rp1_(r0, r1, s1_.size())) - return Operation::process(s0_, s1_.substr(r0, (r1 - r0) + 1)); - else - return T(0); - } - - inline typename expression_node::node_type type() const - { - return Operation::type(); - } - - inline operator_type operation() const - { - return Operation::operation(); - } - - inline std::string& s0() - { - return s0_; - } - - inline std::string& s1() - { - return s1_; - } - - protected: - - SType0 s0_; - SType1 s1_; - RangePack rp1_; - - private: - - str_xoxr_node(str_xoxr_node&); - str_xoxr_node& operator=(str_xoxr_node&); - }; - - template - class str_xroxr_node exprtk_final : public sos_base_node - { - public: - - typedef expression_node* expression_ptr; - typedef Operation operation_t; - - // string-range op string-range node - explicit str_xroxr_node(SType0 p0, SType1 p1, RangePack rp0, RangePack rp1) - : s0_ (p0 ), - s1_ (p1 ), - rp0_(rp0), - rp1_(rp1) - {} - - ~str_xroxr_node() - { - rp0_.free(); - rp1_.free(); - } - - inline T value() const - { - std::size_t r0_0 = 0; - std::size_t r0_1 = 0; - std::size_t r1_0 = 0; - std::size_t r1_1 = 0; - - if ( - rp0_(r0_0, r1_0, s0_.size()) && - rp1_(r0_1, r1_1, s1_.size()) - ) - { - return Operation::process( - s0_.substr(r0_0, (r1_0 - r0_0) + 1), - s1_.substr(r0_1, (r1_1 - r0_1) + 1) - ); - } - else - return T(0); - } - - inline typename expression_node::node_type type() const - { - return Operation::type(); - } - - inline operator_type operation() const - { - return Operation::operation(); - } - - inline std::string& s0() - { - return s0_; - } - - inline std::string& s1() - { - return s1_; - } - - protected: - - SType0 s0_; - SType1 s1_; - RangePack rp0_; - RangePack rp1_; - - private: - - str_xroxr_node(str_xroxr_node&); - str_xroxr_node& operator=(str_xroxr_node&); - }; - - template - class str_sogens_node exprtk_final : public binary_node - { - public: - - typedef expression_node * expression_ptr; - typedef string_base_node* str_base_ptr; - typedef range_pack range_t; - typedef range_t* range_ptr; - typedef range_interface irange_t; - typedef irange_t* irange_ptr; - - str_sogens_node(const operator_type& opr, - expression_ptr branch0, - expression_ptr branch1) - : binary_node(opr, branch0, branch1), - str0_base_ptr_ (0), - str1_base_ptr_ (0), - str0_range_ptr_(0), - str1_range_ptr_(0) - { - if (is_generally_string_node(binary_node::branch_[0].first)) - { - str0_base_ptr_ = dynamic_cast(binary_node::branch_[0].first); - - if (0 == str0_base_ptr_) - return; - - irange_ptr range = dynamic_cast(binary_node::branch_[0].first); - - if (0 == range) - return; - - str0_range_ptr_ = &(range->range_ref()); - } - - if (is_generally_string_node(binary_node::branch_[1].first)) - { - str1_base_ptr_ = dynamic_cast(binary_node::branch_[1].first); - - if (0 == str1_base_ptr_) - return; - - irange_ptr range = dynamic_cast(binary_node::branch_[1].first); - - if (0 == range) - return; - - str1_range_ptr_ = &(range->range_ref()); - } - } - - inline T value() const - { - if ( - str0_base_ptr_ && - str1_base_ptr_ && - str0_range_ptr_ && - str1_range_ptr_ - ) - { - binary_node::branch_[0].first->value(); - binary_node::branch_[1].first->value(); - - std::size_t str0_r0 = 0; - std::size_t str0_r1 = 0; - - std::size_t str1_r0 = 0; - std::size_t str1_r1 = 0; - - const range_t& range0 = (*str0_range_ptr_); - const range_t& range1 = (*str1_range_ptr_); - - if ( - range0(str0_r0, str0_r1, str0_base_ptr_->size()) && - range1(str1_r0, str1_r1, str1_base_ptr_->size()) - ) - { - return Operation::process( - str0_base_ptr_->str().substr(str0_r0,(str0_r1 - str0_r0) + 1), - str1_base_ptr_->str().substr(str1_r0,(str1_r1 - str1_r0) + 1) - ); - } - } - - return std::numeric_limits::quiet_NaN(); - } - - inline typename expression_node::node_type type() const - { - return Operation::type(); - } - - inline operator_type operation() const - { - return Operation::operation(); - } - - private: - - str_sogens_node(str_sogens_node&); - str_sogens_node& operator=(str_sogens_node&); - - str_base_ptr str0_base_ptr_; - str_base_ptr str1_base_ptr_; - range_ptr str0_range_ptr_; - range_ptr str1_range_ptr_; - }; - - template - class sosos_node exprtk_final : public sosos_base_node - { - public: - - typedef expression_node* expression_ptr; - typedef Operation operation_t; - - // variable op variable node - explicit sosos_node(SType0 p0, SType1 p1, SType2 p2) - : s0_(p0), - s1_(p1), - s2_(p2) - {} - - inline T value() const - { - return Operation::process(s0_,s1_,s2_); - } - - inline typename expression_node::node_type type() const - { - return Operation::type(); - } - - inline operator_type operation() const - { - return Operation::operation(); - } - - inline std::string& s0() - { - return s0_; - } - - inline std::string& s1() - { - return s1_; - } - - inline std::string& s2() - { - return s2_; - } - - protected: - - SType0 s0_; - SType1 s1_; - SType2 s2_; - - private: - - sosos_node(sosos_node&); - sosos_node& operator=(sosos_node&); - }; - #endif - - template - class ipow_node exprtk_final: public expression_node - { - public: - - typedef expression_node* expression_ptr; - typedef PowOp operation_t; - - explicit ipow_node(const T& v) - : v_(v) - {} - - inline T value() const - { - return PowOp::result(v_); - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_ipow; - } - - private: - - ipow_node(const ipow_node&); - ipow_node& operator=(const ipow_node&); - - const T& v_; - }; - - template - class bipow_node exprtk_final : public expression_node - { - public: - - typedef expression_node* expression_ptr; - typedef std::pair branch_t; - typedef PowOp operation_t; - - explicit bipow_node(expression_ptr branch) - { - construct_branch_pair(branch_, branch); - } - - inline T value() const - { - assert(branch_.first); - return PowOp::result(branch_.first->value()); - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_ipow; - } - - void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) - { - expression_node::ndb_t::collect(branch_, node_delete_list); - } - - std::size_t node_depth() const - { - return expression_node::ndb_t::compute_node_depth(branch_); - } - - private: - - bipow_node(const bipow_node&); - bipow_node& operator=(const bipow_node&); - - branch_t branch_; - }; - - template - class ipowinv_node exprtk_final : public expression_node - { - public: - - typedef expression_node* expression_ptr; - typedef PowOp operation_t; - - explicit ipowinv_node(const T& v) - : v_(v) - {} - - inline T value() const - { - return (T(1) / PowOp::result(v_)); - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_ipowinv; - } - - private: - - ipowinv_node(const ipowinv_node&); - ipowinv_node& operator=(const ipowinv_node&); - - const T& v_; - }; - - template - class bipowninv_node exprtk_final : public expression_node - { - public: - - typedef expression_node* expression_ptr; - typedef std::pair branch_t; - typedef PowOp operation_t; - - explicit bipowninv_node(expression_ptr branch) - { - construct_branch_pair(branch_, branch); - } - - inline T value() const - { - assert(branch_.first); - return (T(1) / PowOp::result(branch_.first->value())); - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_ipowinv; - } - - void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) - { - expression_node::ndb_t::template collect(branch_, node_delete_list); - } - - std::size_t node_depth() const - { - return expression_node::ndb_t::compute_node_depth(branch_); - } - - private: - - bipowninv_node(const bipowninv_node&); - bipowninv_node& operator=(const bipowninv_node&); - - branch_t branch_; - }; - - template - inline bool is_vov_node(const expression_node* node) - { - return (0 != dynamic_cast*>(node)); - } - - template - inline bool is_cov_node(const expression_node* node) - { - return (0 != dynamic_cast*>(node)); - } - - template - inline bool is_voc_node(const expression_node* node) - { - return (0 != dynamic_cast*>(node)); - } - - template - inline bool is_cob_node(const expression_node* node) - { - return (0 != dynamic_cast*>(node)); - } - - template - inline bool is_boc_node(const expression_node* node) - { - return (0 != dynamic_cast*>(node)); - } - - template - inline bool is_t0ot1ot2_node(const expression_node* node) - { - return (0 != dynamic_cast*>(node)); - } - - template - inline bool is_t0ot1ot2ot3_node(const expression_node* node) - { - return (0 != dynamic_cast*>(node)); - } - - template - inline bool is_uv_node(const expression_node* node) - { - return (0 != dynamic_cast*>(node)); - } - - template - inline bool is_string_node(const expression_node* node) - { - return node && (expression_node::e_stringvar == node->type()); - } - - template - inline bool is_string_range_node(const expression_node* node) - { - return node && (expression_node::e_stringvarrng == node->type()); - } - - template - inline bool is_const_string_node(const expression_node* node) - { - return node && (expression_node::e_stringconst == node->type()); - } - - template - inline bool is_const_string_range_node(const expression_node* node) - { - return node && (expression_node::e_cstringvarrng == node->type()); - } - - template - inline bool is_string_assignment_node(const expression_node* node) - { - return node && (expression_node::e_strass == node->type()); - } - - template - inline bool is_string_concat_node(const expression_node* node) - { - return node && (expression_node::e_strconcat == node->type()); - } - - template - inline bool is_string_function_node(const expression_node* node) - { - return node && (expression_node::e_strfunction == node->type()); - } - - template - inline bool is_string_condition_node(const expression_node* node) - { - return node && (expression_node::e_strcondition == node->type()); - } - - template - inline bool is_string_ccondition_node(const expression_node* node) - { - return node && (expression_node::e_strccondition == node->type()); - } - - template - inline bool is_string_vararg_node(const expression_node* node) - { - return node && (expression_node::e_stringvararg == node->type()); - } - - template - inline bool is_genricstring_range_node(const expression_node* node) - { - return node && (expression_node::e_strgenrange == node->type()); - } - - template - inline bool is_generally_string_node(const expression_node* node) - { - if (node) - { - switch (node->type()) - { - case expression_node::e_stringvar : - case expression_node::e_stringconst : - case expression_node::e_stringvarrng : - case expression_node::e_cstringvarrng : - case expression_node::e_strgenrange : - case expression_node::e_strass : - case expression_node::e_strconcat : - case expression_node::e_strfunction : - case expression_node::e_strcondition : - case expression_node::e_strccondition : - case expression_node::e_stringvararg : return true; - default : return false; - } - } - - return false; - } - - class node_allocator - { - public: - - template - inline expression_node* allocate(OpType& operation, ExprNode (&branch)[1]) - { - expression_node* result = - allocate(operation, branch[0]); - result->node_depth(); - return result; - } - - template - inline expression_node* allocate(OpType& operation, ExprNode (&branch)[2]) - { - expression_node* result = - allocate(operation, branch[0], branch[1]); - result->node_depth(); - return result; - } - - template - inline expression_node* allocate(OpType& operation, ExprNode (&branch)[3]) - { - expression_node* result = - allocate(operation, branch[0], branch[1], branch[2]); - result->node_depth(); - return result; - } - - template - inline expression_node* allocate(OpType& operation, ExprNode (&branch)[4]) - { - expression_node* result = - allocate(operation, branch[0], branch[1], branch[2], branch[3]); - result->node_depth(); - return result; - } - - template - inline expression_node* allocate(OpType& operation, ExprNode (&branch)[5]) - { - expression_node* result = - allocate(operation, branch[0],branch[1], branch[2], branch[3], branch[4]); - result->node_depth(); - return result; - } - - template - inline expression_node* allocate(OpType& operation, ExprNode (&branch)[6]) - { - expression_node* result = - allocate(operation, branch[0], branch[1], branch[2], branch[3], branch[4], branch[5]); - result->node_depth(); - return result; - } - - template - inline expression_node* allocate() const - { - return (new node_type()); - } - - template class Sequence> - inline expression_node* allocate(const Sequence& seq) const - { - expression_node* - result = (new node_type(seq)); - result->node_depth(); - return result; - } - - template - inline expression_node* allocate(T1& t1) const - { - expression_node* - result = (new node_type(t1)); - result->node_depth(); - return result; - } - - template - inline expression_node* allocate_c(const T1& t1) const - { - expression_node* - result = (new node_type(t1)); - result->node_depth(); - return result; - } - - template - inline expression_node* allocate(const T1& t1, const T2& t2) const - { - expression_node* - result = (new node_type(t1, t2)); - result->node_depth(); - return result; - } - - template - inline expression_node* allocate_cr(const T1& t1, T2& t2) const - { - expression_node* - result = (new node_type(t1, t2)); - result->node_depth(); - return result; - } - - template - inline expression_node* allocate_rc(T1& t1, const T2& t2) const - { - expression_node* - result = (new node_type(t1, t2)); - result->node_depth(); - return result; - } - - template - inline expression_node* allocate_rr(T1& t1, T2& t2) const - { - expression_node* - result = (new node_type(t1, t2)); - result->node_depth(); - return result; - } - - template - inline expression_node* allocate_tt(T1 t1, T2 t2) const - { - expression_node* - result = (new node_type(t1, t2)); - result->node_depth(); - return result; - } - - template - inline expression_node* allocate_ttt(T1 t1, T2 t2, T3 t3) const - { - expression_node* - result = (new node_type(t1, t2, t3)); - result->node_depth(); - return result; - } - - template - inline expression_node* allocate_tttt(T1 t1, T2 t2, T3 t3, T4 t4) const - { - expression_node* - result = (new node_type(t1, t2, t3, t4)); - result->node_depth(); - return result; - } - - template - inline expression_node* allocate_rrr(T1& t1, T2& t2, T3& t3) const - { - expression_node* - result = (new node_type(t1, t2, t3)); - result->node_depth(); - return result; - } - - template - inline expression_node* allocate_rrrr(T1& t1, T2& t2, T3& t3, T4& t4) const - { - expression_node* - result = (new node_type(t1, t2, t3, t4)); - result->node_depth(); - return result; - } - - template - inline expression_node* allocate_rrrrr(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5) const - { - expression_node* - result = (new node_type(t1, t2, t3, t4, t5)); - result->node_depth(); - return result; - } - - template - inline expression_node* allocate(const T1& t1, const T2& t2, - const T3& t3) const - { - expression_node* - result = (new node_type(t1, t2, t3)); - result->node_depth(); - return result; - } - - template - inline expression_node* allocate(const T1& t1, const T2& t2, - const T3& t3, const T4& t4) const - { - expression_node* - result = (new node_type(t1, t2, t3, t4)); - result->node_depth(); - return result; - } - - template - inline expression_node* allocate(const T1& t1, const T2& t2, - const T3& t3, const T4& t4, - const T5& t5) const - { - expression_node* - result = (new node_type(t1, t2, t3, t4, t5)); - result->node_depth(); - return result; - } - - template - inline expression_node* allocate(const T1& t1, const T2& t2, - const T3& t3, const T4& t4, - const T5& t5, const T6& t6) const - { - expression_node* - result = (new node_type(t1, t2, t3, t4, t5, t6)); - result->node_depth(); - return result; - } - - template - inline expression_node* allocate(const T1& t1, const T2& t2, - const T3& t3, const T4& t4, - const T5& t5, const T6& t6, - const T7& t7) const - { - expression_node* - result = (new node_type(t1, t2, t3, t4, t5, t6, t7)); - result->node_depth(); - return result; - } - - template - inline expression_node* allocate(const T1& t1, const T2& t2, - const T3& t3, const T4& t4, - const T5& t5, const T6& t6, - const T7& t7, const T8& t8) const - { - expression_node* - result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8)); - result->node_depth(); - return result; - } - - template - inline expression_node* allocate(const T1& t1, const T2& t2, - const T3& t3, const T4& t4, - const T5& t5, const T6& t6, - const T7& t7, const T8& t8, - const T9& t9) const - { - expression_node* - result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9)); - result->node_depth(); - return result; - } - - template - inline expression_node* allocate(const T1& t1, const T2& t2, - const T3& t3, const T4& t4, - const T5& t5, const T6& t6, - const T7& t7, const T8& t8, - const T9& t9, const T10& t10) const - { - expression_node* - result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10)); - result->node_depth(); - return result; - } - - template - inline expression_node* allocate_type(T1 t1, T2 t2, T3 t3) const - { - expression_node* - result = (new node_type(t1, t2, t3)); - result->node_depth(); - return result; - } - - template - inline expression_node* allocate_type(T1 t1, T2 t2, - T3 t3, T4 t4) const - { - expression_node* - result = (new node_type(t1, t2, t3, t4)); - result->node_depth(); - return result; - } - - template - inline expression_node* allocate_type(T1 t1, T2 t2, - T3 t3, T4 t4, - T5 t5) const - { - expression_node* - result = (new node_type(t1, t2, t3, t4, t5)); - result->node_depth(); - return result; - } - - template - inline expression_node* allocate_type(T1 t1, T2 t2, - T3 t3, T4 t4, - T5 t5, T6 t6) const - { - expression_node* - result = (new node_type(t1, t2, t3, t4, t5, t6)); - result->node_depth(); - return result; - } - - template - inline expression_node* allocate_type(T1 t1, T2 t2, - T3 t3, T4 t4, - T5 t5, T6 t6, - T7 t7) const - { - expression_node* - result = (new node_type(t1, t2, t3, t4, t5, t6, t7)); - result->node_depth(); - return result; - } - - template - void inline free(expression_node*& e) const - { - exprtk_debug(("node_allocator::free() - deleting expression_node " - "type: %03d addr: %p\n", - static_cast(e->type()), - reinterpret_cast(e))); - delete e; - e = 0; - } - }; - - inline void load_operations_map(std::multimap& m) - { - #define register_op(Symbol,Type,Args) \ - m.insert(std::make_pair(std::string(Symbol),details::base_operation_t(Type,Args))); \ - - register_op( "abs", e_abs , 1) - register_op( "acos", e_acos , 1) - register_op( "acosh", e_acosh , 1) - register_op( "asin", e_asin , 1) - register_op( "asinh", e_asinh , 1) - register_op( "atan", e_atan , 1) - register_op( "atanh", e_atanh , 1) - register_op( "ceil", e_ceil , 1) - register_op( "cos", e_cos , 1) - register_op( "cosh", e_cosh , 1) - register_op( "exp", e_exp , 1) - register_op( "expm1", e_expm1 , 1) - register_op( "floor", e_floor , 1) - register_op( "log", e_log , 1) - register_op( "log10", e_log10 , 1) - register_op( "log2", e_log2 , 1) - register_op( "log1p", e_log1p , 1) - register_op( "round", e_round , 1) - register_op( "sin", e_sin , 1) - register_op( "sinc", e_sinc , 1) - register_op( "sinh", e_sinh , 1) - register_op( "sec", e_sec , 1) - register_op( "csc", e_csc , 1) - register_op( "sqrt", e_sqrt , 1) - register_op( "tan", e_tan , 1) - register_op( "tanh", e_tanh , 1) - register_op( "cot", e_cot , 1) - register_op( "rad2deg", e_r2d , 1) - register_op( "deg2rad", e_d2r , 1) - register_op( "deg2grad", e_d2g , 1) - register_op( "grad2deg", e_g2d , 1) - register_op( "sgn", e_sgn , 1) - register_op( "not", e_notl , 1) - register_op( "erf", e_erf , 1) - register_op( "erfc", e_erfc , 1) - register_op( "ncdf", e_ncdf , 1) - register_op( "frac", e_frac , 1) - register_op( "trunc", e_trunc , 1) - register_op( "atan2", e_atan2 , 2) - register_op( "mod", e_mod , 2) - register_op( "logn", e_logn , 2) - register_op( "pow", e_pow , 2) - register_op( "root", e_root , 2) - register_op( "roundn", e_roundn , 2) - register_op( "equal", e_equal , 2) - register_op("not_equal", e_nequal , 2) - register_op( "hypot", e_hypot , 2) - register_op( "shr", e_shr , 2) - register_op( "shl", e_shl , 2) - register_op( "clamp", e_clamp , 3) - register_op( "iclamp", e_iclamp , 3) - register_op( "inrange", e_inrange , 3) - #undef register_op - } - - } // namespace details - - class function_traits - { - public: - - function_traits() - : allow_zero_parameters_(false), - has_side_effects_(true), - min_num_args_(0), - max_num_args_(std::numeric_limits::max()) - {} - - inline bool& allow_zero_parameters() - { - return allow_zero_parameters_; - } - - inline bool& has_side_effects() - { - return has_side_effects_; - } - - std::size_t& min_num_args() - { - return min_num_args_; - } - - std::size_t& max_num_args() - { - return max_num_args_; - } - - private: - - bool allow_zero_parameters_; - bool has_side_effects_; - std::size_t min_num_args_; - std::size_t max_num_args_; - }; - - template - void enable_zero_parameters(FunctionType& func) - { - func.allow_zero_parameters() = true; - - if (0 != func.min_num_args()) - { - func.min_num_args() = 0; - } - } - - template - void disable_zero_parameters(FunctionType& func) - { - func.allow_zero_parameters() = false; - } - - template - void enable_has_side_effects(FunctionType& func) - { - func.has_side_effects() = true; - } - - template - void disable_has_side_effects(FunctionType& func) - { - func.has_side_effects() = false; - } - - template - void set_min_num_args(FunctionType& func, const std::size_t& num_args) - { - func.min_num_args() = num_args; - - if ((0 != func.min_num_args()) && func.allow_zero_parameters()) - func.allow_zero_parameters() = false; - } - - template - void set_max_num_args(FunctionType& func, const std::size_t& num_args) - { - func.max_num_args() = num_args; - } - - template - class ifunction : public function_traits - { - public: - - explicit ifunction(const std::size_t& pc) - : param_count(pc) - {} - - virtual ~ifunction() - {} - - #define empty_method_body(N) \ - { \ - exprtk_debug(("ifunction::operator() - Operator(" #N ") has not been overridden\n")); \ - return std::numeric_limits::quiet_NaN(); \ - } \ - - inline virtual T operator() () - empty_method_body(0) - - inline virtual T operator() (const T&) - empty_method_body(1) - - inline virtual T operator() (const T&,const T&) - empty_method_body(2) - - inline virtual T operator() (const T&, const T&, const T&) - empty_method_body(3) - - inline virtual T operator() (const T&, const T&, const T&, const T&) - empty_method_body(4) - - inline virtual T operator() (const T&, const T&, const T&, const T&, const T&) - empty_method_body(5) - - inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&) - empty_method_body(6) - - inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&) - empty_method_body(7) - - inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) - empty_method_body(8) - - inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) - empty_method_body(9) - - inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) - empty_method_body(10) - - inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, - const T&) - empty_method_body(11) - - inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, - const T&, const T&) - empty_method_body(12) - - inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, - const T&, const T&, const T&) - empty_method_body(13) - - inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, - const T&, const T&, const T&, const T&) - empty_method_body(14) - - inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, - const T&, const T&, const T&, const T&, const T&) - empty_method_body(15) - - inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, - const T&, const T&, const T&, const T&, const T&, const T&) - empty_method_body(16) - - inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, - const T&, const T&, const T&, const T&, const T&, const T&, const T&) - empty_method_body(17) - - inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, - const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) - empty_method_body(18) - - inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, - const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) - empty_method_body(19) - - inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, - const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) - empty_method_body(20) - - #undef empty_method_body - - std::size_t param_count; - }; - - template - class ivararg_function : public function_traits - { - public: - - virtual ~ivararg_function() - {} - - inline virtual T operator() (const std::vector&) - { - exprtk_debug(("ivararg_function::operator() - Operator has not been overridden\n")); - return std::numeric_limits::quiet_NaN(); - } - }; - - template - class igeneric_function : public function_traits - { - public: - - enum return_type - { - e_rtrn_scalar = 0, - e_rtrn_string = 1, - e_rtrn_overload = 2 - }; - - typedef T type; - typedef type_store generic_type; - typedef typename generic_type::parameter_list parameter_list_t; - - igeneric_function(const std::string& param_seq = "", const return_type rtr_type = e_rtrn_scalar) - : parameter_sequence(param_seq), - rtrn_type(rtr_type) - {} - - virtual ~igeneric_function() - {} - - #define igeneric_function_empty_body(N) \ - { \ - exprtk_debug(("igeneric_function::operator() - Operator(" #N ") has not been overridden\n")); \ - return std::numeric_limits::quiet_NaN(); \ - } \ - - // f(i_0,i_1,....,i_N) --> Scalar - inline virtual T operator() (parameter_list_t) - igeneric_function_empty_body(1) - - // f(i_0,i_1,....,i_N) --> String - inline virtual T operator() (std::string&, parameter_list_t) - igeneric_function_empty_body(2) - - // f(psi,i_0,i_1,....,i_N) --> Scalar - inline virtual T operator() (const std::size_t&, parameter_list_t) - igeneric_function_empty_body(3) - - // f(psi,i_0,i_1,....,i_N) --> String - inline virtual T operator() (const std::size_t&, std::string&, parameter_list_t) - igeneric_function_empty_body(4) - - std::string parameter_sequence; - return_type rtrn_type; - }; - - template class parser; - template class expression_helper; - - template - class symbol_table - { - public: - - typedef T (*ff00_functor)(); - typedef T (*ff01_functor)(T); - typedef T (*ff02_functor)(T, T); - typedef T (*ff03_functor)(T, T, T); - typedef T (*ff04_functor)(T, T, T, T); - typedef T (*ff05_functor)(T, T, T, T, T); - typedef T (*ff06_functor)(T, T, T, T, T, T); - typedef T (*ff07_functor)(T, T, T, T, T, T, T); - typedef T (*ff08_functor)(T, T, T, T, T, T, T, T); - typedef T (*ff09_functor)(T, T, T, T, T, T, T, T, T); - typedef T (*ff10_functor)(T, T, T, T, T, T, T, T, T, T); - typedef T (*ff11_functor)(T, T, T, T, T, T, T, T, T, T, T); - typedef T (*ff12_functor)(T, T, T, T, T, T, T, T, T, T, T, T); - typedef T (*ff13_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T); - typedef T (*ff14_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T); - typedef T (*ff15_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T); - - protected: - - struct freefunc00 : public exprtk::ifunction - { - using exprtk::ifunction::operator(); - - explicit freefunc00(ff00_functor ff) : exprtk::ifunction(0), f(ff) {} - inline T operator() () - { return f(); } - ff00_functor f; - }; - - struct freefunc01 : public exprtk::ifunction - { - using exprtk::ifunction::operator(); - - explicit freefunc01(ff01_functor ff) : exprtk::ifunction(1), f(ff) {} - inline T operator() (const T& v0) - { return f(v0); } - ff01_functor f; - }; - - struct freefunc02 : public exprtk::ifunction - { - using exprtk::ifunction::operator(); - - explicit freefunc02(ff02_functor ff) : exprtk::ifunction(2), f(ff) {} - inline T operator() (const T& v0, const T& v1) - { return f(v0, v1); } - ff02_functor f; - }; - - struct freefunc03 : public exprtk::ifunction - { - using exprtk::ifunction::operator(); - - explicit freefunc03(ff03_functor ff) : exprtk::ifunction(3), f(ff) {} - inline T operator() (const T& v0, const T& v1, const T& v2) - { return f(v0, v1, v2); } - ff03_functor f; - }; - - struct freefunc04 : public exprtk::ifunction - { - using exprtk::ifunction::operator(); - - explicit freefunc04(ff04_functor ff) : exprtk::ifunction(4), f(ff) {} - inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3) - { return f(v0, v1, v2, v3); } - ff04_functor f; - }; - - struct freefunc05 : public exprtk::ifunction - { - using exprtk::ifunction::operator(); - - explicit freefunc05(ff05_functor ff) : exprtk::ifunction(5), f(ff) {} - inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4) - { return f(v0, v1, v2, v3, v4); } - ff05_functor f; - }; - - struct freefunc06 : public exprtk::ifunction - { - using exprtk::ifunction::operator(); - - explicit freefunc06(ff06_functor ff) : exprtk::ifunction(6), f(ff) {} - inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5) - { return f(v0, v1, v2, v3, v4, v5); } - ff06_functor f; - }; - - struct freefunc07 : public exprtk::ifunction - { - using exprtk::ifunction::operator(); - - explicit freefunc07(ff07_functor ff) : exprtk::ifunction(7), f(ff) {} - inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, - const T& v5, const T& v6) - { return f(v0, v1, v2, v3, v4, v5, v6); } - ff07_functor f; - }; - - struct freefunc08 : public exprtk::ifunction - { - using exprtk::ifunction::operator(); - - explicit freefunc08(ff08_functor ff) : exprtk::ifunction(8), f(ff) {} - inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, - const T& v5, const T& v6, const T& v7) - { return f(v0, v1, v2, v3, v4, v5, v6, v7); } - ff08_functor f; - }; - - struct freefunc09 : public exprtk::ifunction - { - using exprtk::ifunction::operator(); - - explicit freefunc09(ff09_functor ff) : exprtk::ifunction(9), f(ff) {} - inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, - const T& v5, const T& v6, const T& v7, const T& v8) - { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8); } - ff09_functor f; - }; - - struct freefunc10 : public exprtk::ifunction - { - using exprtk::ifunction::operator(); - - explicit freefunc10(ff10_functor ff) : exprtk::ifunction(10), f(ff) {} - inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, - const T& v5, const T& v6, const T& v7, const T& v8, const T& v9) - { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9); } - ff10_functor f; - }; - - struct freefunc11 : public exprtk::ifunction - { - using exprtk::ifunction::operator(); - - explicit freefunc11(ff11_functor ff) : exprtk::ifunction(11), f(ff) {} - inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, - const T& v5, const T& v6, const T& v7, const T& v8, const T& v9, const T& v10) - { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10); } - ff11_functor f; - }; - - struct freefunc12 : public exprtk::ifunction - { - using exprtk::ifunction::operator(); - - explicit freefunc12(ff12_functor ff) : exprtk::ifunction(12), f(ff) {} - inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, - const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, - const T& v10, const T& v11) - { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11); } - ff12_functor f; - }; - - struct freefunc13 : public exprtk::ifunction - { - using exprtk::ifunction::operator(); - - explicit freefunc13(ff13_functor ff) : exprtk::ifunction(13), f(ff) {} - inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, - const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, - const T& v10, const T& v11, const T& v12) - { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12); } - ff13_functor f; - }; - - struct freefunc14 : public exprtk::ifunction - { - using exprtk::ifunction::operator(); - - explicit freefunc14(ff14_functor ff) : exprtk::ifunction(14), f(ff) {} - inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, - const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, - const T& v10, const T& v11, const T& v12, const T& v13) - { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13); } - ff14_functor f; - }; - - struct freefunc15 : public exprtk::ifunction - { - using exprtk::ifunction::operator(); - - explicit freefunc15(ff15_functor ff) : exprtk::ifunction(15), f(ff) {} - inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, - const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, - const T& v10, const T& v11, const T& v12, const T& v13, const T& v14) - { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13, v14); } - ff15_functor f; - }; - - template - struct type_store - { - typedef details::expression_node* expression_ptr; - typedef typename details::variable_node variable_node_t; - typedef ifunction ifunction_t; - typedef ivararg_function ivararg_function_t; - typedef igeneric_function igeneric_function_t; - typedef details::vector_holder vector_t; - #ifndef exprtk_disable_string_capabilities - typedef typename details::stringvar_node stringvar_node_t; - #endif - - typedef Type type_t; - typedef type_t* type_ptr; - typedef std::pair type_pair_t; - typedef std::map type_map_t; - typedef typename type_map_t::iterator tm_itr_t; - typedef typename type_map_t::const_iterator tm_const_itr_t; - - enum { lut_size = 256 }; - - type_map_t map; - std::size_t size; - - type_store() - : size(0) - {} - - struct deleter - { - #define exprtk_define_process(Type) \ - static inline void process(std::pair& n) \ - { \ - delete n.second; \ - } \ - - exprtk_define_process(variable_node_t ) - exprtk_define_process(vector_t ) - #ifndef exprtk_disable_string_capabilities - exprtk_define_process(stringvar_node_t) - #endif - - #undef exprtk_define_process - - template - static inline void process(std::pair&) - {} - }; - - inline bool symbol_exists(const std::string& symbol_name) const - { - if (symbol_name.empty()) - return false; - else if (map.end() != map.find(symbol_name)) - return true; - else - return false; - } - - template - inline std::string entity_name(const PtrType& ptr) const - { - if (map.empty()) - return std::string(); - - tm_const_itr_t itr = map.begin(); - - while (map.end() != itr) - { - if (itr->second.second == ptr) - { - return itr->first; - } - else - ++itr; - } - - return std::string(); - } - - inline bool is_constant(const std::string& symbol_name) const - { - if (symbol_name.empty()) - return false; - else - { - const tm_const_itr_t itr = map.find(symbol_name); - - if (map.end() == itr) - return false; - else - return (*itr).second.first; - } - } - - template - inline bool add_impl(const std::string& symbol_name, RType t, const bool is_const) - { - if (symbol_name.size() > 1) - { - for (std::size_t i = 0; i < details::reserved_symbols_size; ++i) - { - if (details::imatch(symbol_name, details::reserved_symbols[i])) - { - return false; - } - } - } - - const tm_itr_t itr = map.find(symbol_name); - - if (map.end() == itr) - { - map[symbol_name] = Tie::make(t,is_const); - ++size; - } - - return true; - } - - struct tie_array - { - static inline std::pair make(std::pair v, const bool is_const = false) - { - return std::make_pair(is_const, new vector_t(v.first, v.second)); - } - }; - - struct tie_stdvec - { - template - static inline std::pair make(std::vector& v, const bool is_const = false) - { - return std::make_pair(is_const, new vector_t(v)); - } - }; - - struct tie_vecview - { - static inline std::pair make(exprtk::vector_view& v, const bool is_const = false) - { - return std::make_pair(is_const, new vector_t(v)); - } - }; - - struct tie_stddeq - { - template - static inline std::pair make(std::deque& v, const bool is_const = false) - { - return std::make_pair(is_const, new vector_t(v)); - } - }; - - template - inline bool add(const std::string& symbol_name, T (&v)[v_size], const bool is_const = false) - { - return add_impl > - (symbol_name, std::make_pair(v,v_size), is_const); - } - - inline bool add(const std::string& symbol_name, T* v, const std::size_t v_size, const bool is_const = false) - { - return add_impl > - (symbol_name, std::make_pair(v,v_size), is_const); - } - - template - inline bool add(const std::string& symbol_name, std::vector& v, const bool is_const = false) - { - return add_impl&> - (symbol_name, v, is_const); - } - - inline bool add(const std::string& symbol_name, exprtk::vector_view& v, const bool is_const = false) - { - return add_impl&> - (symbol_name, v, is_const); - } - - template - inline bool add(const std::string& symbol_name, std::deque& v, const bool is_const = false) - { - return add_impl&> - (symbol_name, v, is_const); - } - - inline bool add(const std::string& symbol_name, RawType& t, const bool is_const = false) - { - struct tie - { - static inline std::pair make(T& t,const bool is_const = false) - { - return std::make_pair(is_const, new variable_node_t(t)); - } - - #ifndef exprtk_disable_string_capabilities - static inline std::pair make(std::string& t,const bool is_const = false) - { - return std::make_pair(is_const, new stringvar_node_t(t)); - } - #endif - - static inline std::pair make(function_t& t, const bool is_constant = false) - { - return std::make_pair(is_constant,&t); - } - - static inline std::pair make(vararg_function_t& t, const bool is_const = false) - { - return std::make_pair(is_const,&t); - } - - static inline std::pair make(generic_function_t& t, const bool is_constant = false) - { - return std::make_pair(is_constant,&t); - } - }; - - const tm_itr_t itr = map.find(symbol_name); - - if (map.end() == itr) - { - map[symbol_name] = tie::make(t,is_const); - ++size; - } - - return true; - } - - inline type_ptr get(const std::string& symbol_name) const - { - const tm_const_itr_t itr = map.find(symbol_name); - - if (map.end() == itr) - return reinterpret_cast(0); - else - return itr->second.second; - } - - template - struct ptr_match - { - static inline bool test(const PtrType, const void*) - { - return false; - } - }; - - template - struct ptr_match - { - static inline bool test(const variable_node_t* p, const void* ptr) - { - exprtk_debug(("ptr_match::test() - %p <--> %p\n",(void*)(&(p->ref())),ptr)); - return (&(p->ref()) == ptr); - } - }; - - inline type_ptr get_from_varptr(const void* ptr) const - { - tm_const_itr_t itr = map.begin(); - - while (map.end() != itr) - { - type_ptr ret_ptr = itr->second.second; - - if (ptr_match::test(ret_ptr,ptr)) - { - return ret_ptr; - } - - ++itr; - } - - return type_ptr(0); - } - - inline bool remove(const std::string& symbol_name, const bool delete_node = true) - { - const tm_itr_t itr = map.find(symbol_name); - - if (map.end() != itr) - { - if (delete_node) - { - deleter::process((*itr).second); - } - - map.erase(itr); - --size; - - return true; - } - else - return false; - } - - inline RawType& type_ref(const std::string& symbol_name) - { - struct init_type - { - static inline double set(double) { return (0.0); } - static inline double set(long double) { return (0.0); } - static inline float set(float) { return (0.0f); } - static inline std::string set(std::string) { return std::string(""); } - }; - - static RawType null_type = init_type::set(RawType()); - - const tm_const_itr_t itr = map.find(symbol_name); - - if (map.end() == itr) - return null_type; - else - return itr->second.second->ref(); - } - - inline void clear(const bool delete_node = true) - { - if (!map.empty()) - { - if (delete_node) - { - tm_itr_t itr = map.begin(); - tm_itr_t end = map.end (); - - while (end != itr) - { - deleter::process((*itr).second); - ++itr; - } - } - - map.clear(); - } - - size = 0; - } - - template class Sequence> - inline std::size_t get_list(Sequence,Allocator>& list) const - { - std::size_t count = 0; - - if (!map.empty()) - { - tm_const_itr_t itr = map.begin(); - tm_const_itr_t end = map.end (); - - while (end != itr) - { - list.push_back(std::make_pair((*itr).first,itr->second.second->ref())); - ++itr; - ++count; - } - } - - return count; - } - - template class Sequence> - inline std::size_t get_list(Sequence& vlist) const - { - std::size_t count = 0; - - if (!map.empty()) - { - tm_const_itr_t itr = map.begin(); - tm_const_itr_t end = map.end (); - - while (end != itr) - { - vlist.push_back((*itr).first); - ++itr; - ++count; - } - } - - return count; - } - }; - - typedef details::expression_node* expression_ptr; - typedef typename details::variable_node variable_t; - typedef typename details::vector_holder vector_holder_t; - typedef variable_t* variable_ptr; - #ifndef exprtk_disable_string_capabilities - typedef typename details::stringvar_node stringvar_t; - typedef stringvar_t* stringvar_ptr; - #endif - typedef ifunction function_t; - typedef ivararg_function vararg_function_t; - typedef igeneric_function generic_function_t; - typedef function_t* function_ptr; - typedef vararg_function_t* vararg_function_ptr; - typedef generic_function_t* generic_function_ptr; - - static const std::size_t lut_size = 256; - - // Symbol Table Holder - struct control_block - { - struct st_data - { - type_store variable_store; - type_store function_store; - type_store vararg_function_store; - type_store generic_function_store; - type_store string_function_store; - type_store overload_function_store; - type_store vector_store; - #ifndef exprtk_disable_string_capabilities - type_store stringvar_store; - #endif - - st_data() - { - for (std::size_t i = 0; i < details::reserved_words_size; ++i) - { - reserved_symbol_table_.insert(details::reserved_words[i]); - } - - for (std::size_t i = 0; i < details::reserved_symbols_size; ++i) - { - reserved_symbol_table_.insert(details::reserved_symbols[i]); - } - } - - ~st_data() - { - for (std::size_t i = 0; i < free_function_list_.size(); ++i) - { - delete free_function_list_[i]; - } - } - - inline bool is_reserved_symbol(const std::string& symbol) const - { - return (reserved_symbol_table_.end() != reserved_symbol_table_.find(symbol)); - } - - static inline st_data* create() - { - return (new st_data); - } - - static inline void destroy(st_data*& sd) - { - delete sd; - sd = reinterpret_cast(0); - } - - std::list local_symbol_list_; - std::list local_stringvar_list_; - std::set reserved_symbol_table_; - std::vector*> free_function_list_; - }; - - control_block() - : ref_count(1), - data_(st_data::create()) - {} - - explicit control_block(st_data* data) - : ref_count(1), - data_(data) - {} - - ~control_block() - { - if (data_ && (0 == ref_count)) - { - st_data::destroy(data_); - } - } - - static inline control_block* create() - { - return (new control_block); - } - - template - static inline void destroy(control_block*& cntrl_blck, SymTab* sym_tab) - { - if (cntrl_blck) - { - if ( - (0 != cntrl_blck->ref_count) && - (0 == --cntrl_blck->ref_count) - ) - { - if (sym_tab) - sym_tab->clear(); - - delete cntrl_blck; - } - - cntrl_blck = 0; - } - } - - std::size_t ref_count; - st_data* data_; - }; - - public: - - symbol_table() - : control_block_(control_block::create()) - { - clear(); - } - - ~symbol_table() - { - control_block::destroy(control_block_,this); - } - - symbol_table(const symbol_table& st) - { - control_block_ = st.control_block_; - control_block_->ref_count++; - } - - inline symbol_table& operator=(const symbol_table& st) - { - if (this != &st) - { - control_block::destroy(control_block_,reinterpret_cast*>(0)); - - control_block_ = st.control_block_; - control_block_->ref_count++; - } - - return (*this); - } - - inline bool operator==(const symbol_table& st) const - { - return (this == &st) || (control_block_ == st.control_block_); - } - - inline void clear_variables(const bool delete_node = true) - { - local_data().variable_store.clear(delete_node); - } - - inline void clear_functions() - { - local_data().function_store.clear(); - } - - inline void clear_strings() - { - #ifndef exprtk_disable_string_capabilities - local_data().stringvar_store.clear(); - #endif - } - - inline void clear_vectors() - { - local_data().vector_store.clear(); - } - - inline void clear_local_constants() - { - local_data().local_symbol_list_.clear(); - } - - inline void clear() - { - if (!valid()) return; - clear_variables (); - clear_functions (); - clear_strings (); - clear_vectors (); - clear_local_constants(); - } - - inline std::size_t variable_count() const - { - if (valid()) - return local_data().variable_store.size; - else - return 0; - } - - #ifndef exprtk_disable_string_capabilities - inline std::size_t stringvar_count() const - { - if (valid()) - return local_data().stringvar_store.size; - else - return 0; - } - #endif - - inline std::size_t function_count() const - { - if (valid()) - return local_data().function_store.size; - else - return 0; - } - - inline std::size_t vector_count() const - { - if (valid()) - return local_data().vector_store.size; - else - return 0; - } - - inline variable_ptr get_variable(const std::string& variable_name) const - { - if (!valid()) - return reinterpret_cast(0); - else if (!valid_symbol(variable_name)) - return reinterpret_cast(0); - else - return local_data().variable_store.get(variable_name); - } - - inline variable_ptr get_variable(const T& var_ref) const - { - if (!valid()) - return reinterpret_cast(0); - else - return local_data().variable_store.get_from_varptr( - reinterpret_cast(&var_ref)); - } - - #ifndef exprtk_disable_string_capabilities - inline stringvar_ptr get_stringvar(const std::string& string_name) const - { - if (!valid()) - return reinterpret_cast(0); - else if (!valid_symbol(string_name)) - return reinterpret_cast(0); - else - return local_data().stringvar_store.get(string_name); - } - #endif - - inline function_ptr get_function(const std::string& function_name) const - { - if (!valid()) - return reinterpret_cast(0); - else if (!valid_symbol(function_name)) - return reinterpret_cast(0); - else - return local_data().function_store.get(function_name); - } - - inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const - { - if (!valid()) - return reinterpret_cast(0); - else if (!valid_symbol(vararg_function_name)) - return reinterpret_cast(0); - else - return local_data().vararg_function_store.get(vararg_function_name); - } - - inline generic_function_ptr get_generic_function(const std::string& function_name) const - { - if (!valid()) - return reinterpret_cast(0); - else if (!valid_symbol(function_name)) - return reinterpret_cast(0); - else - return local_data().generic_function_store.get(function_name); - } - - inline generic_function_ptr get_string_function(const std::string& function_name) const - { - if (!valid()) - return reinterpret_cast(0); - else if (!valid_symbol(function_name)) - return reinterpret_cast(0); - else - return local_data().string_function_store.get(function_name); - } - - inline generic_function_ptr get_overload_function(const std::string& function_name) const - { - if (!valid()) - return reinterpret_cast(0); - else if (!valid_symbol(function_name)) - return reinterpret_cast(0); - else - return local_data().overload_function_store.get(function_name); - } - - typedef vector_holder_t* vector_holder_ptr; - - inline vector_holder_ptr get_vector(const std::string& vector_name) const - { - if (!valid()) - return reinterpret_cast(0); - else if (!valid_symbol(vector_name)) - return reinterpret_cast(0); - else - return local_data().vector_store.get(vector_name); - } - - inline T& variable_ref(const std::string& symbol_name) - { - static T null_var = T(0); - if (!valid()) - return null_var; - else if (!valid_symbol(symbol_name)) - return null_var; - else - return local_data().variable_store.type_ref(symbol_name); - } - - #ifndef exprtk_disable_string_capabilities - inline std::string& stringvar_ref(const std::string& symbol_name) - { - static std::string null_stringvar; - if (!valid()) - return null_stringvar; - else if (!valid_symbol(symbol_name)) - return null_stringvar; - else - return local_data().stringvar_store.type_ref(symbol_name); - } - #endif - - inline bool is_constant_node(const std::string& symbol_name) const - { - if (!valid()) - return false; - else if (!valid_symbol(symbol_name)) - return false; - else - return local_data().variable_store.is_constant(symbol_name); - } - - #ifndef exprtk_disable_string_capabilities - inline bool is_constant_string(const std::string& symbol_name) const - { - if (!valid()) - return false; - else if (!valid_symbol(symbol_name)) - return false; - else if (!local_data().stringvar_store.symbol_exists(symbol_name)) - return false; - else - return local_data().stringvar_store.is_constant(symbol_name); - } - #endif - - inline bool create_variable(const std::string& variable_name, const T& value = T(0)) - { - if (!valid()) - return false; - else if (!valid_symbol(variable_name)) - return false; - else if (symbol_exists(variable_name)) - return false; - - local_data().local_symbol_list_.push_back(value); - T& t = local_data().local_symbol_list_.back(); - - return add_variable(variable_name,t); - } - - #ifndef exprtk_disable_string_capabilities - inline bool create_stringvar(const std::string& stringvar_name, const std::string& value = std::string("")) - { - if (!valid()) - return false; - else if (!valid_symbol(stringvar_name)) - return false; - else if (symbol_exists(stringvar_name)) - return false; - - local_data().local_stringvar_list_.push_back(value); - std::string& s = local_data().local_stringvar_list_.back(); - - return add_stringvar(stringvar_name,s); - } - #endif - - inline bool add_variable(const std::string& variable_name, T& t, const bool is_constant = false) - { - if (!valid()) - return false; - else if (!valid_symbol(variable_name)) - return false; - else if (symbol_exists(variable_name)) - return false; - else - return local_data().variable_store.add(variable_name, t, is_constant); - } - - inline bool add_constant(const std::string& constant_name, const T& value) - { - if (!valid()) - return false; - else if (!valid_symbol(constant_name)) - return false; - else if (symbol_exists(constant_name)) - return false; - - local_data().local_symbol_list_.push_back(value); - T& t = local_data().local_symbol_list_.back(); - - return add_variable(constant_name, t, true); - } - - #ifndef exprtk_disable_string_capabilities - inline bool add_stringvar(const std::string& stringvar_name, std::string& s, const bool is_constant = false) - { - if (!valid()) - return false; - else if (!valid_symbol(stringvar_name)) - return false; - else if (symbol_exists(stringvar_name)) - return false; - else - return local_data().stringvar_store.add(stringvar_name, s, is_constant); - } - #endif - - inline bool add_function(const std::string& function_name, function_t& function) - { - if (!valid()) - return false; - else if (!valid_symbol(function_name)) - return false; - else if (symbol_exists(function_name)) - return false; - else - return local_data().function_store.add(function_name,function); - } - - inline bool add_function(const std::string& vararg_function_name, vararg_function_t& vararg_function) - { - if (!valid()) - return false; - else if (!valid_symbol(vararg_function_name)) - return false; - else if (symbol_exists(vararg_function_name)) - return false; - else - return local_data().vararg_function_store.add(vararg_function_name,vararg_function); - } - - inline bool add_function(const std::string& function_name, generic_function_t& function) - { - if (!valid()) - return false; - else if (!valid_symbol(function_name)) - return false; - else if (symbol_exists(function_name)) - return false; - else - { - switch (function.rtrn_type) - { - case generic_function_t::e_rtrn_scalar : - return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ? - local_data().generic_function_store.add(function_name,function) : false; - - case generic_function_t::e_rtrn_string : - return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ? - local_data().string_function_store.add(function_name,function) : false; - - case generic_function_t::e_rtrn_overload : - return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|:")) ? - local_data().overload_function_store.add(function_name,function) : false; - } - } - - return false; - } - - #define exprtk_define_freefunction(NN) \ - inline bool add_function(const std::string& function_name, ff##NN##_functor function) \ - { \ - if (!valid()) \ - { return false; } \ - if (!valid_symbol(function_name)) \ - { return false; } \ - if (symbol_exists(function_name)) \ - { return false; } \ - \ - exprtk::ifunction* ifunc = new freefunc##NN(function); \ - \ - local_data().free_function_list_.push_back(ifunc); \ - \ - return add_function(function_name,(*local_data().free_function_list_.back())); \ - } \ - - exprtk_define_freefunction(00) exprtk_define_freefunction(01) - exprtk_define_freefunction(02) exprtk_define_freefunction(03) - exprtk_define_freefunction(04) exprtk_define_freefunction(05) - exprtk_define_freefunction(06) exprtk_define_freefunction(07) - exprtk_define_freefunction(08) exprtk_define_freefunction(09) - exprtk_define_freefunction(10) exprtk_define_freefunction(11) - exprtk_define_freefunction(12) exprtk_define_freefunction(13) - exprtk_define_freefunction(14) exprtk_define_freefunction(15) - - #undef exprtk_define_freefunction - - inline bool add_reserved_function(const std::string& function_name, function_t& function) - { - if (!valid()) - return false; - else if (!valid_symbol(function_name,false)) - return false; - else if (symbol_exists(function_name,false)) - return false; - else - return local_data().function_store.add(function_name,function); - } - - inline bool add_reserved_function(const std::string& vararg_function_name, vararg_function_t& vararg_function) - { - if (!valid()) - return false; - else if (!valid_symbol(vararg_function_name,false)) - return false; - else if (symbol_exists(vararg_function_name,false)) - return false; - else - return local_data().vararg_function_store.add(vararg_function_name,vararg_function); - } - - inline bool add_reserved_function(const std::string& function_name, generic_function_t& function) - { - if (!valid()) - return false; - else if (!valid_symbol(function_name,false)) - return false; - else if (symbol_exists(function_name,false)) - return false; - else - { - switch (function.rtrn_type) - { - case generic_function_t::e_rtrn_scalar : - return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ? - local_data().generic_function_store.add(function_name,function) : false; - - case generic_function_t::e_rtrn_string : - return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ? - local_data().string_function_store.add(function_name,function) : false; - - case generic_function_t::e_rtrn_overload : - return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|:")) ? - local_data().overload_function_store.add(function_name,function) : false; - } - } - - return false; - } - - template - inline bool add_vector(const std::string& vector_name, T (&v)[N]) - { - if (!valid()) - return false; - else if (!valid_symbol(vector_name)) - return false; - else if (symbol_exists(vector_name)) - return false; - else - return local_data().vector_store.add(vector_name,v); - } - - inline bool add_vector(const std::string& vector_name, T* v, const std::size_t& v_size) - { - if (!valid()) - return false; - else if (!valid_symbol(vector_name)) - return false; - else if (symbol_exists(vector_name)) - return false; - else if (0 == v_size) - return false; - else - return local_data().vector_store.add(vector_name, v, v_size); - } - - template - inline bool add_vector(const std::string& vector_name, std::vector& v) - { - if (!valid()) - return false; - else if (!valid_symbol(vector_name)) - return false; - else if (symbol_exists(vector_name)) - return false; - else if (0 == v.size()) - return false; - else - return local_data().vector_store.add(vector_name,v); - } - - inline bool add_vector(const std::string& vector_name, exprtk::vector_view& v) - { - if (!valid()) - return false; - else if (!valid_symbol(vector_name)) - return false; - else if (symbol_exists(vector_name)) - return false; - else if (0 == v.size()) - return false; - else - return local_data().vector_store.add(vector_name,v); - } - - inline bool remove_variable(const std::string& variable_name, const bool delete_node = true) - { - if (!valid()) - return false; - else - return local_data().variable_store.remove(variable_name, delete_node); - } - - #ifndef exprtk_disable_string_capabilities - inline bool remove_stringvar(const std::string& string_name) - { - if (!valid()) - return false; - else - return local_data().stringvar_store.remove(string_name); - } - #endif - - inline bool remove_function(const std::string& function_name) - { - if (!valid()) - return false; - else - return local_data().function_store.remove(function_name); - } - - inline bool remove_vararg_function(const std::string& vararg_function_name) - { - if (!valid()) - return false; - else - return local_data().vararg_function_store.remove(vararg_function_name); - } - - inline bool remove_vector(const std::string& vector_name) - { - if (!valid()) - return false; - else - return local_data().vector_store.remove(vector_name); - } - - inline bool add_constants() - { - return add_pi () && - add_epsilon () && - add_infinity() ; - } - - inline bool add_pi() - { - const typename details::numeric::details::number_type::type num_type; - static const T local_pi = details::numeric::details::const_pi_impl(num_type); - return add_constant("pi",local_pi); - } - - inline bool add_epsilon() - { - static const T local_epsilon = details::numeric::details::epsilon_type::value(); - return add_constant("epsilon",local_epsilon); - } - - inline bool add_infinity() - { - static const T local_infinity = std::numeric_limits::infinity(); - return add_constant("inf",local_infinity); - } - - template - inline bool add_package(Package& package) - { - return package.register_package(*this); - } - - template class Sequence> - inline std::size_t get_variable_list(Sequence,Allocator>& vlist) const - { - if (!valid()) - return 0; - else - return local_data().variable_store.get_list(vlist); - } - - template class Sequence> - inline std::size_t get_variable_list(Sequence& vlist) const - { - if (!valid()) - return 0; - else - return local_data().variable_store.get_list(vlist); - } - - #ifndef exprtk_disable_string_capabilities - template class Sequence> - inline std::size_t get_stringvar_list(Sequence,Allocator>& svlist) const - { - if (!valid()) - return 0; - else - return local_data().stringvar_store.get_list(svlist); - } - - template class Sequence> - inline std::size_t get_stringvar_list(Sequence& svlist) const - { - if (!valid()) - return 0; - else - return local_data().stringvar_store.get_list(svlist); - } - #endif - - template class Sequence> - inline std::size_t get_vector_list(Sequence& vlist) const - { - if (!valid()) - return 0; - else - return local_data().vector_store.get_list(vlist); - } - - inline bool symbol_exists(const std::string& symbol_name, const bool check_reserved_symb = true) const - { - /* - Function will return true if symbol_name exists as either a - reserved symbol, variable, stringvar, vector or function name - in any of the type stores. - */ - if (!valid()) - return false; - else if (local_data().variable_store.symbol_exists(symbol_name)) - return true; - #ifndef exprtk_disable_string_capabilities - else if (local_data().stringvar_store.symbol_exists(symbol_name)) - return true; - #endif - else if (local_data().vector_store.symbol_exists(symbol_name)) - return true; - else if (local_data().function_store.symbol_exists(symbol_name)) - return true; - else if (check_reserved_symb && local_data().is_reserved_symbol(symbol_name)) - return true; - else - return false; - } - - inline bool is_variable(const std::string& variable_name) const - { - if (!valid()) - return false; - else - return local_data().variable_store.symbol_exists(variable_name); - } - - #ifndef exprtk_disable_string_capabilities - inline bool is_stringvar(const std::string& stringvar_name) const - { - if (!valid()) - return false; - else - return local_data().stringvar_store.symbol_exists(stringvar_name); - } - - inline bool is_conststr_stringvar(const std::string& symbol_name) const - { - if (!valid()) - return false; - else if (!valid_symbol(symbol_name)) - return false; - else if (!local_data().stringvar_store.symbol_exists(symbol_name)) - return false; - - return ( - local_data().stringvar_store.symbol_exists(symbol_name) || - local_data().stringvar_store.is_constant (symbol_name) - ); - } - #endif - - inline bool is_function(const std::string& function_name) const - { - if (!valid()) - return false; - else - return local_data().function_store.symbol_exists(function_name); - } - - inline bool is_vararg_function(const std::string& vararg_function_name) const - { - if (!valid()) - return false; - else - return local_data().vararg_function_store.symbol_exists(vararg_function_name); - } - - inline bool is_vector(const std::string& vector_name) const - { - if (!valid()) - return false; - else - return local_data().vector_store.symbol_exists(vector_name); - } - - inline std::string get_variable_name(const expression_ptr& ptr) const - { - return local_data().variable_store.entity_name(ptr); - } - - inline std::string get_vector_name(const vector_holder_ptr& ptr) const - { - return local_data().vector_store.entity_name(ptr); - } - - #ifndef exprtk_disable_string_capabilities - inline std::string get_stringvar_name(const expression_ptr& ptr) const - { - return local_data().stringvar_store.entity_name(ptr); - } - - inline std::string get_conststr_stringvar_name(const expression_ptr& ptr) const - { - return local_data().stringvar_store.entity_name(ptr); - } - #endif - - inline bool valid() const - { - // Symbol table sanity check. - return control_block_ && control_block_->data_; - } - - inline void load_from(const symbol_table& st) - { - { - std::vector name_list; - - st.local_data().function_store.get_list(name_list); - - if (!name_list.empty()) - { - for (std::size_t i = 0; i < name_list.size(); ++i) - { - exprtk::ifunction& ifunc = *st.get_function(name_list[i]); - add_function(name_list[i],ifunc); - } - } - } - - { - std::vector name_list; - - st.local_data().vararg_function_store.get_list(name_list); - - if (!name_list.empty()) - { - for (std::size_t i = 0; i < name_list.size(); ++i) - { - exprtk::ivararg_function& ivafunc = *st.get_vararg_function(name_list[i]); - add_function(name_list[i],ivafunc); - } - } - } - - { - std::vector name_list; - - st.local_data().generic_function_store.get_list(name_list); - - if (!name_list.empty()) - { - for (std::size_t i = 0; i < name_list.size(); ++i) - { - exprtk::igeneric_function& ifunc = *st.get_generic_function(name_list[i]); - add_function(name_list[i],ifunc); - } - } - } - - { - std::vector name_list; - - st.local_data().string_function_store.get_list(name_list); - - if (!name_list.empty()) - { - for (std::size_t i = 0; i < name_list.size(); ++i) - { - exprtk::igeneric_function& ifunc = *st.get_string_function(name_list[i]); - add_function(name_list[i],ifunc); - } - } - } - - { - std::vector name_list; - - st.local_data().overload_function_store.get_list(name_list); - - if (!name_list.empty()) - { - for (std::size_t i = 0; i < name_list.size(); ++i) - { - exprtk::igeneric_function& ifunc = *st.get_overload_function(name_list[i]); - add_function(name_list[i],ifunc); - } - } - } - } - - private: - - inline bool valid_symbol(const std::string& symbol, const bool check_reserved_symb = true) const - { - if (symbol.empty()) - return false; - else if (!details::is_letter(symbol[0])) - return false; - else if (symbol.size() > 1) - { - for (std::size_t i = 1; i < symbol.size(); ++i) - { - if ( - !details::is_letter_or_digit(symbol[i]) && - ('_' != symbol[i]) - ) - { - if ((i < (symbol.size() - 1)) && ('.' == symbol[i])) - continue; - else - return false; - } - } - } - - return (check_reserved_symb) ? (!local_data().is_reserved_symbol(symbol)) : true; - } - - inline bool valid_function(const std::string& symbol) const - { - if (symbol.empty()) - return false; - else if (!details::is_letter(symbol[0])) - return false; - else if (symbol.size() > 1) - { - for (std::size_t i = 1; i < symbol.size(); ++i) - { - if ( - !details::is_letter_or_digit(symbol[i]) && - ('_' != symbol[i]) - ) - { - if ((i < (symbol.size() - 1)) && ('.' == symbol[i])) - continue; - else - return false; - } - } - } - - return true; - } - - typedef typename control_block::st_data local_data_t; - - inline local_data_t& local_data() - { - return *(control_block_->data_); - } - - inline const local_data_t& local_data() const - { - return *(control_block_->data_); - } - - control_block* control_block_; - - friend class parser; - }; - - template - class function_compositor; - - template - class expression - { - private: - - typedef details::expression_node* expression_ptr; - typedef details::vector_holder* vector_holder_ptr; - typedef std::vector > symtab_list_t; - - struct control_block - { - enum data_type - { - e_unknown , - e_expr , - e_vecholder, - e_data , - e_vecdata , - e_string - }; - - struct data_pack - { - data_pack() - : pointer(0), - type(e_unknown), - size(0) - {} - - data_pack(void* ptr, const data_type dt, const std::size_t sz = 0) - : pointer(ptr), - type(dt), - size(sz) - {} - - void* pointer; - data_type type; - std::size_t size; - }; - - typedef std::vector local_data_list_t; - typedef results_context results_context_t; - - control_block() - : ref_count(0), - expr (0), - results (0), - retinv_null(false), - return_invoked(&retinv_null) - {} - - explicit control_block(expression_ptr e) - : ref_count(1), - expr (e), - results (0), - retinv_null(false), - return_invoked(&retinv_null) - {} - - ~control_block() - { - if (expr && details::branch_deletable(expr)) - { - destroy_node(expr); - } - - if (!local_data_list.empty()) - { - for (std::size_t i = 0; i < local_data_list.size(); ++i) - { - switch (local_data_list[i].type) - { - case e_expr : delete reinterpret_cast(local_data_list[i].pointer); - break; - - case e_vecholder : delete reinterpret_cast(local_data_list[i].pointer); - break; - - case e_data : delete reinterpret_cast(local_data_list[i].pointer); - break; - - case e_vecdata : delete [] reinterpret_cast(local_data_list[i].pointer); - break; - - case e_string : delete reinterpret_cast(local_data_list[i].pointer); - break; - - default : break; - } - } - } - - if (results) - { - delete results; - } - } - - static inline control_block* create(expression_ptr e) - { - return new control_block(e); - } - - static inline void destroy(control_block*& cntrl_blck) - { - if (cntrl_blck) - { - if ( - (0 != cntrl_blck->ref_count) && - (0 == --cntrl_blck->ref_count) - ) - { - delete cntrl_blck; - } - - cntrl_blck = 0; - } - } - - std::size_t ref_count; - expression_ptr expr; - local_data_list_t local_data_list; - results_context_t* results; - bool retinv_null; - bool* return_invoked; - - friend class function_compositor; - }; - - public: - - expression() - : control_block_(0) - { - set_expression(new details::null_node()); - } - - expression(const expression& e) - : control_block_ (e.control_block_ ), - symbol_table_list_(e.symbol_table_list_) - { - control_block_->ref_count++; - } - - explicit expression(const symbol_table& symbol_table) - : control_block_(0) - { - set_expression(new details::null_node()); - symbol_table_list_.push_back(symbol_table); - } - - inline expression& operator=(const expression& e) - { - if (this != &e) - { - if (control_block_) - { - if ( - (0 != control_block_->ref_count) && - (0 == --control_block_->ref_count) - ) - { - delete control_block_; - } - - control_block_ = 0; - } - - control_block_ = e.control_block_; - control_block_->ref_count++; - symbol_table_list_ = e.symbol_table_list_; - } - - return *this; - } - - inline bool operator==(const expression& e) const - { - return (this == &e); - } - - inline bool operator!() const - { - return ( - (0 == control_block_ ) || - (0 == control_block_->expr) - ); - } - - inline expression& release() - { - control_block::destroy(control_block_); - - return (*this); - } - - ~expression() - { - control_block::destroy(control_block_); - } - - inline T value() const - { - assert(control_block_ ); - assert(control_block_->expr); - - return control_block_->expr->value(); - } - - inline T operator() () const - { - return value(); - } - - inline operator T() const - { - return value(); - } - - inline operator bool() const - { - return details::is_true(value()); - } - - inline void register_symbol_table(symbol_table& st) - { - symbol_table_list_.push_back(st); - } - - inline const symbol_table& get_symbol_table(const std::size_t& index = 0) const - { - return symbol_table_list_[index]; - } - - inline symbol_table& get_symbol_table(const std::size_t& index = 0) - { - return symbol_table_list_[index]; - } - - typedef results_context results_context_t; - - inline const results_context_t& results() const - { - if (control_block_->results) - return (*control_block_->results); - else - { - static const results_context_t null_results; - return null_results; - } - } - - inline bool return_invoked() const - { - return (*control_block_->return_invoked); - } - - private: - - inline symtab_list_t get_symbol_table_list() const - { - return symbol_table_list_; - } - - inline void set_expression(const expression_ptr expr) - { - if (expr) - { - if (control_block_) - { - if (0 == --control_block_->ref_count) - { - delete control_block_; - } - } - - control_block_ = control_block::create(expr); - } - } - - inline void register_local_var(expression_ptr expr) - { - if (expr) - { - if (control_block_) - { - control_block_-> - local_data_list.push_back( - typename expression::control_block:: - data_pack(reinterpret_cast(expr), - control_block::e_expr)); - } - } - } - - inline void register_local_var(vector_holder_ptr vec_holder) - { - if (vec_holder) - { - if (control_block_) - { - control_block_-> - local_data_list.push_back( - typename expression::control_block:: - data_pack(reinterpret_cast(vec_holder), - control_block::e_vecholder)); - } - } - } - - inline void register_local_data(void* data, const std::size_t& size = 0, const std::size_t data_mode = 0) - { - if (data) - { - if (control_block_) - { - typename control_block::data_type dt = control_block::e_data; - - switch (data_mode) - { - case 0 : dt = control_block::e_data; break; - case 1 : dt = control_block::e_vecdata; break; - case 2 : dt = control_block::e_string; break; - } - - control_block_-> - local_data_list.push_back( - typename expression::control_block:: - data_pack(reinterpret_cast(data), dt, size)); - } - } - } - - inline const typename control_block::local_data_list_t& local_data_list() - { - if (control_block_) - { - return control_block_->local_data_list; - } - else - { - static typename control_block::local_data_list_t null_local_data_list; - return null_local_data_list; - } - } - - inline void register_return_results(results_context_t* rc) - { - if (control_block_ && rc) - { - control_block_->results = rc; - } - } - - inline void set_retinvk(bool* retinvk_ptr) - { - if (control_block_) - { - control_block_->return_invoked = retinvk_ptr; - } - } - - control_block* control_block_; - symtab_list_t symbol_table_list_; - - friend class parser; - friend class expression_helper; - friend class function_compositor; - }; - - template - class expression_helper - { - public: - - static inline bool is_constant(const expression& expr) - { - return details::is_constant_node(expr.control_block_->expr); - } - - static inline bool is_variable(const expression& expr) - { - return details::is_variable_node(expr.control_block_->expr); - } - - static inline bool is_unary(const expression& expr) - { - return details::is_unary_node(expr.control_block_->expr); - } - - static inline bool is_binary(const expression& expr) - { - return details::is_binary_node(expr.control_block_->expr); - } - - static inline bool is_function(const expression& expr) - { - return details::is_function(expr.control_block_->expr); - } - - static inline bool is_null(const expression& expr) - { - return details::is_null_node(expr.control_block_->expr); - } - }; - - template - inline bool is_valid(const expression& expr) - { - return !expression_helper::is_null(expr); - } - - namespace parser_error - { - enum error_mode - { - e_unknown = 0, - e_syntax = 1, - e_token = 2, - e_numeric = 4, - e_symtab = 5, - e_lexer = 6, - e_helper = 7, - e_parser = 8 - }; - - struct type - { - type() - : mode(parser_error::e_unknown), - line_no (0), - column_no(0) - {} - - lexer::token token; - error_mode mode; - std::string diagnostic; - std::string src_location; - std::string error_line; - std::size_t line_no; - std::size_t column_no; - }; - - inline type make_error(const error_mode mode, - const std::string& diagnostic = "", - const std::string& src_location = "") - { - type t; - t.mode = mode; - t.token.type = lexer::token::e_error; - t.diagnostic = diagnostic; - t.src_location = src_location; - exprtk_debug(("%s\n",diagnostic .c_str())); - return t; - } - - inline type make_error(const error_mode mode, - const lexer::token& tk, - const std::string& diagnostic = "", - const std::string& src_location = "") - { - type t; - t.mode = mode; - t.token = tk; - t.diagnostic = diagnostic; - t.src_location = src_location; - exprtk_debug(("%s\n",diagnostic .c_str())); - return t; - } - - inline std::string to_str(error_mode mode) - { - switch (mode) - { - case e_unknown : return std::string("Unknown Error"); - case e_syntax : return std::string("Syntax Error" ); - case e_token : return std::string("Token Error" ); - case e_numeric : return std::string("Numeric Error"); - case e_symtab : return std::string("Symbol Error" ); - case e_lexer : return std::string("Lexer Error" ); - case e_helper : return std::string("Helper Error" ); - case e_parser : return std::string("Parser Error" ); - default : return std::string("Unknown Error"); - } - } - - inline bool update_error(type& error, const std::string& expression) - { - if ( - expression.empty() || - (error.token.position > expression.size()) || - (std::numeric_limits::max() == error.token.position) - ) - { - return false; - } - - std::size_t error_line_start = 0; - - for (std::size_t i = error.token.position; i > 0; --i) - { - const details::char_t c = expression[i]; - - if (('\n' == c) || ('\r' == c)) - { - error_line_start = i + 1; - break; - } - } - - std::size_t next_nl_position = std::min(expression.size(), - expression.find_first_of('\n',error.token.position + 1)); - - error.column_no = error.token.position - error_line_start; - error.error_line = expression.substr(error_line_start, - next_nl_position - error_line_start); - - error.line_no = 0; - - for (std::size_t i = 0; i < next_nl_position; ++i) - { - if ('\n' == expression[i]) - ++error.line_no; - } - - return true; - } - - inline void dump_error(const type& error) - { - printf("Position: %02d Type: [%s] Msg: %s\n", - static_cast(error.token.position), - exprtk::parser_error::to_str(error.mode).c_str(), - error.diagnostic.c_str()); - } - } - - namespace details - { - template - inline void disable_type_checking(Parser& p) - { - p.state_.type_check_enabled = false; - } - } - - template - class parser : public lexer::parser_helper - { - private: - - enum precedence_level - { - e_level00, e_level01, e_level02, e_level03, e_level04, - e_level05, e_level06, e_level07, e_level08, e_level09, - e_level10, e_level11, e_level12, e_level13, e_level14 - }; - - typedef const T& cref_t; - typedef const T const_t; - typedef ifunction F; - typedef ivararg_function VAF; - typedef igeneric_function GF; - typedef ifunction ifunction_t; - typedef ivararg_function ivararg_function_t; - typedef igeneric_function igeneric_function_t; - typedef details::expression_node expression_node_t; - typedef details::literal_node literal_node_t; - typedef details::unary_node unary_node_t; - typedef details::binary_node binary_node_t; - typedef details::trinary_node trinary_node_t; - typedef details::quaternary_node quaternary_node_t; - typedef details::conditional_node conditional_node_t; - typedef details::cons_conditional_node cons_conditional_node_t; - typedef details::while_loop_node while_loop_node_t; - typedef details::repeat_until_loop_node repeat_until_loop_node_t; - typedef details::for_loop_node for_loop_node_t; - #ifndef exprtk_disable_break_continue - typedef details::while_loop_bc_node while_loop_bc_node_t; - typedef details::repeat_until_loop_bc_node repeat_until_loop_bc_node_t; - typedef details::for_loop_bc_node for_loop_bc_node_t; - #endif - typedef details::switch_node switch_node_t; - typedef details::variable_node variable_node_t; - typedef details::vector_elem_node vector_elem_node_t; - typedef details::rebasevector_elem_node rebasevector_elem_node_t; - typedef details::rebasevector_celem_node rebasevector_celem_node_t; - typedef details::vector_node vector_node_t; - typedef details::range_pack range_t; - #ifndef exprtk_disable_string_capabilities - typedef details::stringvar_node stringvar_node_t; - typedef details::string_literal_node string_literal_node_t; - typedef details::string_range_node string_range_node_t; - typedef details::const_string_range_node const_string_range_node_t; - typedef details::generic_string_range_node generic_string_range_node_t; - typedef details::string_concat_node string_concat_node_t; - typedef details::assignment_string_node assignment_string_node_t; - typedef details::assignment_string_range_node assignment_string_range_node_t; - typedef details::conditional_string_node conditional_string_node_t; - typedef details::cons_conditional_str_node cons_conditional_str_node_t; - #endif - typedef details::assignment_node assignment_node_t; - typedef details::assignment_vec_elem_node assignment_vec_elem_node_t; - typedef details::assignment_rebasevec_elem_node assignment_rebasevec_elem_node_t; - typedef details::assignment_rebasevec_celem_node assignment_rebasevec_celem_node_t; - typedef details::assignment_vec_node assignment_vec_node_t; - typedef details::assignment_vecvec_node assignment_vecvec_node_t; - typedef details::scand_node scand_node_t; - typedef details::scor_node scor_node_t; - typedef lexer::token token_t; - typedef expression_node_t* expression_node_ptr; - typedef expression expression_t; - typedef symbol_table symbol_table_t; - typedef typename expression::symtab_list_t symbol_table_list_t; - typedef details::vector_holder* vector_holder_ptr; - - typedef typename details::functor_t functor_t; - typedef typename functor_t::qfunc_t quaternary_functor_t; - typedef typename functor_t::tfunc_t trinary_functor_t; - typedef typename functor_t::bfunc_t binary_functor_t; - typedef typename functor_t::ufunc_t unary_functor_t; - - typedef details::operator_type operator_t; - - typedef std::map unary_op_map_t; - typedef std::map binary_op_map_t; - typedef std::map trinary_op_map_t; - - typedef std::map > sf3_map_t; - typedef std::map > sf4_map_t; - - typedef std::map inv_binary_op_map_t; - typedef std::multimap base_ops_map_t; - typedef std::set disabled_func_set_t; - - typedef details::T0oT1_define vov_t; - typedef details::T0oT1_define cov_t; - typedef details::T0oT1_define voc_t; - - typedef details::T0oT1oT2_define vovov_t; - typedef details::T0oT1oT2_define vovoc_t; - typedef details::T0oT1oT2_define vocov_t; - typedef details::T0oT1oT2_define covov_t; - typedef details::T0oT1oT2_define covoc_t; - typedef details::T0oT1oT2_define cocov_t; - typedef details::T0oT1oT2_define vococ_t; - - typedef details::T0oT1oT2oT3_define vovovov_t; - typedef details::T0oT1oT2oT3_define vovovoc_t; - typedef details::T0oT1oT2oT3_define vovocov_t; - typedef details::T0oT1oT2oT3_define vocovov_t; - typedef details::T0oT1oT2oT3_define covovov_t; - - typedef details::T0oT1oT2oT3_define covocov_t; - typedef details::T0oT1oT2oT3_define vocovoc_t; - typedef details::T0oT1oT2oT3_define covovoc_t; - typedef details::T0oT1oT2oT3_define vococov_t; - - typedef results_context results_context_t; - - typedef parser_helper prsrhlpr_t; - - struct scope_element - { - enum element_type - { - e_none , - e_variable, - e_vector , - e_vecelem , - e_string - }; - - typedef details::vector_holder vector_holder_t; - typedef variable_node_t* variable_node_ptr; - typedef vector_holder_t* vector_holder_ptr; - typedef expression_node_t* expression_node_ptr; - #ifndef exprtk_disable_string_capabilities - typedef stringvar_node_t* stringvar_node_ptr; - #endif - - scope_element() - : name("???"), - size (std::numeric_limits::max()), - index(std::numeric_limits::max()), - depth(std::numeric_limits::max()), - ref_count(0), - ip_index (0), - type (e_none), - active(false), - data (0), - var_node (0), - vec_node (0) - #ifndef exprtk_disable_string_capabilities - ,str_node(0) - #endif - {} - - bool operator < (const scope_element& se) const - { - if (ip_index < se.ip_index) - return true; - else if (ip_index > se.ip_index) - return false; - else if (depth < se.depth) - return true; - else if (depth > se.depth) - return false; - else if (index < se.index) - return true; - else if (index > se.index) - return false; - else - return (name < se.name); - } - - void clear() - { - name = "???"; - size = std::numeric_limits::max(); - index = std::numeric_limits::max(); - depth = std::numeric_limits::max(); - type = e_none; - active = false; - ref_count = 0; - ip_index = 0; - data = 0; - var_node = 0; - vec_node = 0; - #ifndef exprtk_disable_string_capabilities - str_node = 0; - #endif - } - - std::string name; - std::size_t size; - std::size_t index; - std::size_t depth; - std::size_t ref_count; - std::size_t ip_index; - element_type type; - bool active; - void* data; - expression_node_ptr var_node; - vector_holder_ptr vec_node; - #ifndef exprtk_disable_string_capabilities - stringvar_node_ptr str_node; - #endif - }; - - class scope_element_manager - { - public: - - typedef expression_node_t* expression_node_ptr; - typedef variable_node_t* variable_node_ptr; - typedef parser parser_t; - - explicit scope_element_manager(parser& p) - : parser_(p), - input_param_cnt_(0) - {} - - inline std::size_t size() const - { - return element_.size(); - } - - inline bool empty() const - { - return element_.empty(); - } - - inline scope_element& get_element(const std::size_t& index) - { - if (index < element_.size()) - return element_[index]; - else - return null_element_; - } - - inline scope_element& get_element(const std::string& var_name, - const std::size_t index = std::numeric_limits::max()) - { - const std::size_t current_depth = parser_.state_.scope_depth; - - for (std::size_t i = 0; i < element_.size(); ++i) - { - scope_element& se = element_[i]; - - if (se.depth > current_depth) - continue; - else if ( - details::imatch(se.name, var_name) && - (se.index == index) - ) - return se; - } - - return null_element_; - } - - inline scope_element& get_active_element(const std::string& var_name, - const std::size_t index = std::numeric_limits::max()) - { - const std::size_t current_depth = parser_.state_.scope_depth; - - for (std::size_t i = 0; i < element_.size(); ++i) - { - scope_element& se = element_[i]; - - if (se.depth > current_depth) - continue; - else if ( - details::imatch(se.name, var_name) && - (se.index == index) && - (se.active) - ) - return se; - } - - return null_element_; - } - - inline bool add_element(const scope_element& se) - { - for (std::size_t i = 0; i < element_.size(); ++i) - { - scope_element& cse = element_[i]; - - if ( - details::imatch(cse.name, se.name) && - (cse.depth <= se.depth) && - (cse.index == se.index) && - (cse.size == se.size ) && - (cse.type == se.type ) && - (cse.active) - ) - return false; - } - - element_.push_back(se); - std::sort(element_.begin(),element_.end()); - - return true; - } - - inline void deactivate(const std::size_t& scope_depth) - { - exprtk_debug(("deactivate() - Scope depth: %d\n", - static_cast(parser_.state_.scope_depth))); - - for (std::size_t i = 0; i < element_.size(); ++i) - { - scope_element& se = element_[i]; - - if (se.active && (se.depth >= scope_depth)) - { - exprtk_debug(("deactivate() - element[%02d] '%s'\n", - static_cast(i), - se.name.c_str())); - - se.active = false; - } - } - } - - inline void free_element(scope_element& se) - { - exprtk_debug(("free_element() - se[%s]\n", se.name.c_str())); - - switch (se.type) - { - case scope_element::e_variable : delete reinterpret_cast(se.data); - delete se.var_node; - break; - - case scope_element::e_vector : delete[] reinterpret_cast(se.data); - delete se.vec_node; - break; - - case scope_element::e_vecelem : delete se.var_node; - break; - - #ifndef exprtk_disable_string_capabilities - case scope_element::e_string : delete reinterpret_cast(se.data); - delete se.str_node; - break; - #endif - - default : return; - } - - se.clear(); - } - - inline void cleanup() - { - for (std::size_t i = 0; i < element_.size(); ++i) - { - free_element(element_[i]); - } - - element_.clear(); - - input_param_cnt_ = 0; - } - - inline std::size_t next_ip_index() - { - return ++input_param_cnt_; - } - - inline expression_node_ptr get_variable(const T& v) - { - for (std::size_t i = 0; i < element_.size(); ++i) - { - scope_element& se = element_[i]; - - if ( - se.active && - se.var_node && - details::is_variable_node(se.var_node) - ) - { - variable_node_ptr vn = reinterpret_cast(se.var_node); - - if (&(vn->ref()) == (&v)) - { - return se.var_node; - } - } - } - - return expression_node_ptr(0); - } - - private: - - scope_element_manager& operator=(const scope_element_manager&); - - parser_t& parser_; - std::vector element_; - scope_element null_element_; - std::size_t input_param_cnt_; - }; - - class scope_handler - { - public: - - typedef parser parser_t; - - explicit scope_handler(parser& p) - : parser_(p) - { - parser_.state_.scope_depth++; - #ifdef exprtk_enable_debugging - const std::string depth(2 * parser_.state_.scope_depth,'-'); - exprtk_debug(("%s> Scope Depth: %02d\n", - depth.c_str(), - static_cast(parser_.state_.scope_depth))); - #endif - } - - ~scope_handler() - { - parser_.sem_.deactivate(parser_.state_.scope_depth); - parser_.state_.scope_depth--; - #ifdef exprtk_enable_debugging - const std::string depth(2 * parser_.state_.scope_depth,'-'); - exprtk_debug(("<%s Scope Depth: %02d\n", - depth.c_str(), - static_cast(parser_.state_.scope_depth))); - #endif - } - - private: - - scope_handler& operator=(const scope_handler&); - - parser_t& parser_; - }; - - class stack_limit_handler - { - public: - - typedef parser parser_t; - - explicit stack_limit_handler(parser& p) - : parser_(p), - limit_exceeded_(false) - { - if (++parser_.state_.stack_depth > parser_.settings_.max_stack_depth_) - { - limit_exceeded_ = true; - parser_.set_error( - make_error(parser_error::e_parser, - "ERR000 - Current stack depth " + details::to_str(parser_.state_.stack_depth) + - " exceeds maximum allowed stack depth of " + details::to_str(parser_.settings_.max_stack_depth_), - exprtk_error_location)); - } - } - - ~stack_limit_handler() - { - parser_.state_.stack_depth--; - } - - bool operator!() - { - return limit_exceeded_; - } - - private: - - stack_limit_handler& operator=(const stack_limit_handler&); - - parser_t& parser_; - bool limit_exceeded_; - }; - - struct symtab_store - { - symbol_table_list_t symtab_list_; - - typedef typename symbol_table_t::local_data_t local_data_t; - typedef typename symbol_table_t::variable_ptr variable_ptr; - typedef typename symbol_table_t::function_ptr function_ptr; - #ifndef exprtk_disable_string_capabilities - typedef typename symbol_table_t::stringvar_ptr stringvar_ptr; - #endif - typedef typename symbol_table_t::vector_holder_ptr vector_holder_ptr; - typedef typename symbol_table_t::vararg_function_ptr vararg_function_ptr; - typedef typename symbol_table_t::generic_function_ptr generic_function_ptr; - - inline bool empty() const - { - return symtab_list_.empty(); - } - - inline void clear() - { - symtab_list_.clear(); - } - - inline bool valid() const - { - if (!empty()) - { - for (std::size_t i = 0; i < symtab_list_.size(); ++i) - { - if (symtab_list_[i].valid()) - return true; - } - } - - return false; - } - - inline bool valid_symbol(const std::string& symbol) const - { - if (!symtab_list_.empty()) - return symtab_list_[0].valid_symbol(symbol); - else - return false; - } - - inline bool valid_function_name(const std::string& symbol) const - { - if (!symtab_list_.empty()) - return symtab_list_[0].valid_function(symbol); - else - return false; - } - - inline variable_ptr get_variable(const std::string& variable_name) const - { - if (!valid_symbol(variable_name)) - return reinterpret_cast(0); - - variable_ptr result = reinterpret_cast(0); - - for (std::size_t i = 0; i < symtab_list_.size(); ++i) - { - if (!symtab_list_[i].valid()) - continue; - else - result = local_data(i) - .variable_store.get(variable_name); - - if (result) break; - } - - return result; - } - - inline variable_ptr get_variable(const T& var_ref) const - { - variable_ptr result = reinterpret_cast(0); - - for (std::size_t i = 0; i < symtab_list_.size(); ++i) - { - if (!symtab_list_[i].valid()) - continue; - else - result = local_data(i).variable_store - .get_from_varptr(reinterpret_cast(&var_ref)); - - if (result) break; - } - - return result; - } - - #ifndef exprtk_disable_string_capabilities - inline stringvar_ptr get_stringvar(const std::string& string_name) const - { - if (!valid_symbol(string_name)) - return reinterpret_cast(0); - - stringvar_ptr result = reinterpret_cast(0); - - for (std::size_t i = 0; i < symtab_list_.size(); ++i) - { - if (!symtab_list_[i].valid()) - continue; - else - result = local_data(i) - .stringvar_store.get(string_name); - - if (result) break; - } - - return result; - } - #endif - - inline function_ptr get_function(const std::string& function_name) const - { - if (!valid_function_name(function_name)) - return reinterpret_cast(0); - - function_ptr result = reinterpret_cast(0); - - for (std::size_t i = 0; i < symtab_list_.size(); ++i) - { - if (!symtab_list_[i].valid()) - continue; - else - result = local_data(i) - .function_store.get(function_name); - - if (result) break; - } - - return result; - } - - inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const - { - if (!valid_function_name(vararg_function_name)) - return reinterpret_cast(0); - - vararg_function_ptr result = reinterpret_cast(0); - - for (std::size_t i = 0; i < symtab_list_.size(); ++i) - { - if (!symtab_list_[i].valid()) - continue; - else - result = local_data(i) - .vararg_function_store.get(vararg_function_name); - - if (result) break; - } - - return result; - } - - inline generic_function_ptr get_generic_function(const std::string& function_name) const - { - if (!valid_function_name(function_name)) - return reinterpret_cast(0); - - generic_function_ptr result = reinterpret_cast(0); - - for (std::size_t i = 0; i < symtab_list_.size(); ++i) - { - if (!symtab_list_[i].valid()) - continue; - else - result = local_data(i) - .generic_function_store.get(function_name); - - if (result) break; - } - - return result; - } - - inline generic_function_ptr get_string_function(const std::string& function_name) const - { - if (!valid_function_name(function_name)) - return reinterpret_cast(0); - - generic_function_ptr result = reinterpret_cast(0); - - for (std::size_t i = 0; i < symtab_list_.size(); ++i) - { - if (!symtab_list_[i].valid()) - continue; - else - result = - local_data(i).string_function_store.get(function_name); - - if (result) break; - } - - return result; - } - - inline generic_function_ptr get_overload_function(const std::string& function_name) const - { - if (!valid_function_name(function_name)) - return reinterpret_cast(0); - - generic_function_ptr result = reinterpret_cast(0); - - for (std::size_t i = 0; i < symtab_list_.size(); ++i) - { - if (!symtab_list_[i].valid()) - continue; - else - result = - local_data(i).overload_function_store.get(function_name); - - if (result) break; - } - - return result; - } - - inline vector_holder_ptr get_vector(const std::string& vector_name) const - { - if (!valid_symbol(vector_name)) - return reinterpret_cast(0); - - vector_holder_ptr result = reinterpret_cast(0); - - for (std::size_t i = 0; i < symtab_list_.size(); ++i) - { - if (!symtab_list_[i].valid()) - continue; - else - result = - local_data(i).vector_store.get(vector_name); - - if (result) break; - } - - return result; - } - - inline bool is_constant_node(const std::string& symbol_name) const - { - if (!valid_symbol(symbol_name)) - return false; - - for (std::size_t i = 0; i < symtab_list_.size(); ++i) - { - if (!symtab_list_[i].valid()) - continue; - else if (local_data(i).variable_store.is_constant(symbol_name)) - return true; - } - - return false; - } - - #ifndef exprtk_disable_string_capabilities - inline bool is_constant_string(const std::string& symbol_name) const - { - if (!valid_symbol(symbol_name)) - return false; - - for (std::size_t i = 0; i < symtab_list_.size(); ++i) - { - if (!symtab_list_[i].valid()) - continue; - else if (!local_data(i).stringvar_store.symbol_exists(symbol_name)) - continue; - else if (local_data(i).stringvar_store.is_constant(symbol_name)) - return true; - } - - return false; - } - #endif - - inline bool symbol_exists(const std::string& symbol) const - { - for (std::size_t i = 0; i < symtab_list_.size(); ++i) - { - if (!symtab_list_[i].valid()) - continue; - else if (symtab_list_[i].symbol_exists(symbol)) - return true; - } - - return false; - } - - inline bool is_variable(const std::string& variable_name) const - { - for (std::size_t i = 0; i < symtab_list_.size(); ++i) - { - if (!symtab_list_[i].valid()) - continue; - else if ( - symtab_list_[i].local_data().variable_store - .symbol_exists(variable_name) - ) - return true; - } - - return false; - } - - #ifndef exprtk_disable_string_capabilities - inline bool is_stringvar(const std::string& stringvar_name) const - { - for (std::size_t i = 0; i < symtab_list_.size(); ++i) - { - if (!symtab_list_[i].valid()) - continue; - else if ( - symtab_list_[i].local_data().stringvar_store - .symbol_exists(stringvar_name) - ) - return true; - } - - return false; - } - - inline bool is_conststr_stringvar(const std::string& symbol_name) const - { - for (std::size_t i = 0; i < symtab_list_.size(); ++i) - { - if (!symtab_list_[i].valid()) - continue; - else if ( - symtab_list_[i].local_data().stringvar_store - .symbol_exists(symbol_name) - ) - { - return ( - local_data(i).stringvar_store.symbol_exists(symbol_name) || - local_data(i).stringvar_store.is_constant (symbol_name) - ); - - } - } - - return false; - } - #endif - - inline bool is_function(const std::string& function_name) const - { - for (std::size_t i = 0; i < symtab_list_.size(); ++i) - { - if (!symtab_list_[i].valid()) - continue; - else if ( - local_data(i).vararg_function_store - .symbol_exists(function_name) - ) - return true; - } - - return false; - } - - inline bool is_vararg_function(const std::string& vararg_function_name) const - { - for (std::size_t i = 0; i < symtab_list_.size(); ++i) - { - if (!symtab_list_[i].valid()) - continue; - else if ( - local_data(i).vararg_function_store - .symbol_exists(vararg_function_name) - ) - return true; - } - - return false; - } - - inline bool is_vector(const std::string& vector_name) const - { - for (std::size_t i = 0; i < symtab_list_.size(); ++i) - { - if (!symtab_list_[i].valid()) - continue; - else if ( - local_data(i).vector_store - .symbol_exists(vector_name) - ) - return true; - } - - return false; - } - - inline std::string get_variable_name(const expression_node_ptr& ptr) const - { - return local_data().variable_store.entity_name(ptr); - } - - inline std::string get_vector_name(const vector_holder_ptr& ptr) const - { - return local_data().vector_store.entity_name(ptr); - } - - #ifndef exprtk_disable_string_capabilities - inline std::string get_stringvar_name(const expression_node_ptr& ptr) const - { - return local_data().stringvar_store.entity_name(ptr); - } - - inline std::string get_conststr_stringvar_name(const expression_node_ptr& ptr) const - { - return local_data().stringvar_store.entity_name(ptr); - } - #endif - - inline local_data_t& local_data(const std::size_t& index = 0) - { - return symtab_list_[index].local_data(); - } - - inline const local_data_t& local_data(const std::size_t& index = 0) const - { - return symtab_list_[index].local_data(); - } - - inline symbol_table_t& get_symbol_table(const std::size_t& index = 0) - { - return symtab_list_[index]; - } - }; - - struct parser_state - { - parser_state() - : type_check_enabled(true) - { - reset(); - } - - void reset() - { - parsing_return_stmt = false; - parsing_break_stmt = false; - return_stmt_present = false; - side_effect_present = false; - scope_depth = 0; - stack_depth = 0; - parsing_loop_stmt_count = 0; - } - - #ifndef exprtk_enable_debugging - void activate_side_effect(const std::string&) - #else - void activate_side_effect(const std::string& source) - #endif - { - if (!side_effect_present) - { - side_effect_present = true; - - exprtk_debug(("activate_side_effect() - caller: %s\n",source.c_str())); - } - } - - bool parsing_return_stmt; - bool parsing_break_stmt; - bool return_stmt_present; - bool side_effect_present; - bool type_check_enabled; - std::size_t scope_depth; - std::size_t stack_depth; - std::size_t parsing_loop_stmt_count; - }; - - public: - - struct unknown_symbol_resolver - { - - enum usr_symbol_type - { - e_usr_unknown_type = 0, - e_usr_variable_type = 1, - e_usr_constant_type = 2 - }; - - enum usr_mode - { - e_usrmode_default = 0, - e_usrmode_extended = 1 - }; - - usr_mode mode; - - unknown_symbol_resolver(const usr_mode m = e_usrmode_default) - : mode(m) - {} - - virtual ~unknown_symbol_resolver() - {} - - virtual bool process(const std::string& /*unknown_symbol*/, - usr_symbol_type& st, - T& default_value, - std::string& error_message) - { - if (e_usrmode_default != mode) - return false; - - st = e_usr_variable_type; - default_value = T(0); - error_message.clear(); - - return true; - } - - virtual bool process(const std::string& /* unknown_symbol */, - symbol_table_t& /* symbol_table */, - std::string& /* error_message */) - { - return false; - } - }; - - enum collect_type - { - e_ct_none = 0, - e_ct_variables = 1, - e_ct_functions = 2, - e_ct_assignments = 4 - }; - - enum symbol_type - { - e_st_unknown = 0, - e_st_variable = 1, - e_st_vector = 2, - e_st_vecelem = 3, - e_st_string = 4, - e_st_function = 5, - e_st_local_variable = 6, - e_st_local_vector = 7, - e_st_local_string = 8 - }; - - class dependent_entity_collector - { - public: - - typedef std::pair symbol_t; - typedef std::vector symbol_list_t; - - dependent_entity_collector(const std::size_t options = e_ct_none) - : options_(options), - collect_variables_ ((options_ & e_ct_variables ) == e_ct_variables ), - collect_functions_ ((options_ & e_ct_functions ) == e_ct_functions ), - collect_assignments_((options_ & e_ct_assignments) == e_ct_assignments), - return_present_ (false), - final_stmt_return_(false) - {} - - template class Sequence> - inline std::size_t symbols(Sequence& symbols_list) - { - if (!collect_variables_ && !collect_functions_) - return 0; - else if (symbol_name_list_.empty()) - return 0; - - for (std::size_t i = 0; i < symbol_name_list_.size(); ++i) - { - details::case_normalise(symbol_name_list_[i].first); - } - - std::sort(symbol_name_list_.begin(),symbol_name_list_.end()); - - std::unique_copy(symbol_name_list_.begin(), - symbol_name_list_.end (), - std::back_inserter(symbols_list)); - - return symbols_list.size(); - } - - template class Sequence> - inline std::size_t assignment_symbols(Sequence& assignment_list) - { - if (!collect_assignments_) - return 0; - else if (assignment_name_list_.empty()) - return 0; - - for (std::size_t i = 0; i < assignment_name_list_.size(); ++i) - { - details::case_normalise(assignment_name_list_[i].first); - } - - std::sort(assignment_name_list_.begin(),assignment_name_list_.end()); - - std::unique_copy(assignment_name_list_.begin(), - assignment_name_list_.end (), - std::back_inserter(assignment_list)); - - return assignment_list.size(); - } - - void clear() - { - symbol_name_list_ .clear(); - assignment_name_list_.clear(); - retparam_list_ .clear(); - return_present_ = false; - final_stmt_return_ = false; - } - - bool& collect_variables() - { - return collect_variables_; - } - - bool& collect_functions() - { - return collect_functions_; - } - - bool& collect_assignments() - { - return collect_assignments_; - } - - bool return_present() const - { - return return_present_; - } - - bool final_stmt_return() const - { - return final_stmt_return_; - } - - typedef std::vector retparam_list_t; - - retparam_list_t return_param_type_list() const - { - return retparam_list_; - } - - private: - - inline void add_symbol(const std::string& symbol, const symbol_type st) - { - switch (st) - { - case e_st_variable : - case e_st_vector : - case e_st_string : - case e_st_local_variable : - case e_st_local_vector : - case e_st_local_string : if (collect_variables_) - symbol_name_list_ - .push_back(std::make_pair(symbol, st)); - break; - - case e_st_function : if (collect_functions_) - symbol_name_list_ - .push_back(std::make_pair(symbol, st)); - break; - - default : return; - } - } - - inline void add_assignment(const std::string& symbol, const symbol_type st) - { - switch (st) - { - case e_st_variable : - case e_st_vector : - case e_st_string : if (collect_assignments_) - assignment_name_list_ - .push_back(std::make_pair(symbol, st)); - break; - - default : return; - } - } - - std::size_t options_; - bool collect_variables_; - bool collect_functions_; - bool collect_assignments_; - bool return_present_; - bool final_stmt_return_; - symbol_list_t symbol_name_list_; - symbol_list_t assignment_name_list_; - retparam_list_t retparam_list_; - - friend class parser; - }; - - class settings_store - { - private: - - typedef std::set disabled_entity_set_t; - typedef disabled_entity_set_t::iterator des_itr_t; - - public: - - enum settings_compilation_options - { - e_unknown = 0, - e_replacer = 1, - e_joiner = 2, - e_numeric_check = 4, - e_bracket_check = 8, - e_sequence_check = 16, - e_commutative_check = 32, - e_strength_reduction = 64, - e_disable_vardef = 128, - e_collect_vars = 256, - e_collect_funcs = 512, - e_collect_assings = 1024, - e_disable_usr_on_rsrvd = 2048, - e_disable_zero_return = 4096 - }; - - enum settings_base_funcs - { - e_bf_unknown = 0, - e_bf_abs , e_bf_acos , e_bf_acosh , e_bf_asin , - e_bf_asinh , e_bf_atan , e_bf_atan2 , e_bf_atanh , - e_bf_avg , e_bf_ceil , e_bf_clamp , e_bf_cos , - e_bf_cosh , e_bf_cot , e_bf_csc , e_bf_equal , - e_bf_erf , e_bf_erfc , e_bf_exp , e_bf_expm1 , - e_bf_floor , e_bf_frac , e_bf_hypot , e_bf_iclamp , - e_bf_like , e_bf_log , e_bf_log10 , e_bf_log1p , - e_bf_log2 , e_bf_logn , e_bf_mand , e_bf_max , - e_bf_min , e_bf_mod , e_bf_mor , e_bf_mul , - e_bf_ncdf , e_bf_pow , e_bf_root , e_bf_round , - e_bf_roundn , e_bf_sec , e_bf_sgn , e_bf_sin , - e_bf_sinc , e_bf_sinh , e_bf_sqrt , e_bf_sum , - e_bf_swap , e_bf_tan , e_bf_tanh , e_bf_trunc , - e_bf_not_equal , e_bf_inrange , e_bf_deg2grad , e_bf_deg2rad, - e_bf_rad2deg , e_bf_grad2deg - }; - - enum settings_control_structs - { - e_ctrl_unknown = 0, - e_ctrl_ifelse, - e_ctrl_switch, - e_ctrl_for_loop, - e_ctrl_while_loop, - e_ctrl_repeat_loop, - e_ctrl_return - }; - - enum settings_logic_opr - { - e_logic_unknown = 0, - e_logic_and, e_logic_nand, e_logic_nor, - e_logic_not, e_logic_or, e_logic_xnor, - e_logic_xor, e_logic_scand, e_logic_scor - }; - - enum settings_arithmetic_opr - { - e_arith_unknown = 0, - e_arith_add, e_arith_sub, e_arith_mul, - e_arith_div, e_arith_mod, e_arith_pow - }; - - enum settings_assignment_opr - { - e_assign_unknown = 0, - e_assign_assign, e_assign_addass, e_assign_subass, - e_assign_mulass, e_assign_divass, e_assign_modass - }; - - enum settings_inequality_opr - { - e_ineq_unknown = 0, - e_ineq_lt, e_ineq_lte, e_ineq_eq, - e_ineq_equal, e_ineq_ne, e_ineq_nequal, - e_ineq_gte, e_ineq_gt - }; - - static const std::size_t compile_all_opts = e_replacer + - e_joiner + - e_numeric_check + - e_bracket_check + - e_sequence_check + - e_commutative_check + - e_strength_reduction; - - settings_store(const std::size_t compile_options = compile_all_opts) - : max_stack_depth_(400), - max_node_depth_(10000) - { - load_compile_options(compile_options); - } - - settings_store& enable_all_base_functions() - { - disabled_func_set_.clear(); - return (*this); - } - - settings_store& enable_all_control_structures() - { - disabled_ctrl_set_.clear(); - return (*this); - } - - settings_store& enable_all_logic_ops() - { - disabled_logic_set_.clear(); - return (*this); - } - - settings_store& enable_all_arithmetic_ops() - { - disabled_arithmetic_set_.clear(); - return (*this); - } - - settings_store& enable_all_assignment_ops() - { - disabled_assignment_set_.clear(); - return (*this); - } - - settings_store& enable_all_inequality_ops() - { - disabled_inequality_set_.clear(); - return (*this); - } - - settings_store& enable_local_vardef() - { - disable_vardef_ = false; - return (*this); - } - - settings_store& disable_all_base_functions() - { - std::copy(details::base_function_list, - details::base_function_list + details::base_function_list_size, - std::insert_iterator - (disabled_func_set_, disabled_func_set_.begin())); - return (*this); - } - - settings_store& disable_all_control_structures() - { - std::copy(details::cntrl_struct_list, - details::cntrl_struct_list + details::cntrl_struct_list_size, - std::insert_iterator - (disabled_ctrl_set_, disabled_ctrl_set_.begin())); - return (*this); - } - - settings_store& disable_all_logic_ops() - { - std::copy(details::logic_ops_list, - details::logic_ops_list + details::logic_ops_list_size, - std::insert_iterator - (disabled_logic_set_, disabled_logic_set_.begin())); - return (*this); - } - - settings_store& disable_all_arithmetic_ops() - { - std::copy(details::arithmetic_ops_list, - details::arithmetic_ops_list + details::arithmetic_ops_list_size, - std::insert_iterator - (disabled_arithmetic_set_, disabled_arithmetic_set_.begin())); - return (*this); - } - - settings_store& disable_all_assignment_ops() - { - std::copy(details::assignment_ops_list, - details::assignment_ops_list + details::assignment_ops_list_size, - std::insert_iterator - (disabled_assignment_set_, disabled_assignment_set_.begin())); - return (*this); - } - - settings_store& disable_all_inequality_ops() - { - std::copy(details::inequality_ops_list, - details::inequality_ops_list + details::inequality_ops_list_size, - std::insert_iterator - (disabled_inequality_set_, disabled_inequality_set_.begin())); - return (*this); - } - - settings_store& disable_local_vardef() - { - disable_vardef_ = true; - return (*this); - } - - bool replacer_enabled () const { return enable_replacer_; } - bool commutative_check_enabled () const { return enable_commutative_check_; } - bool joiner_enabled () const { return enable_joiner_; } - bool numeric_check_enabled () const { return enable_numeric_check_; } - bool bracket_check_enabled () const { return enable_bracket_check_; } - bool sequence_check_enabled () const { return enable_sequence_check_; } - bool strength_reduction_enabled () const { return enable_strength_reduction_; } - bool collect_variables_enabled () const { return enable_collect_vars_; } - bool collect_functions_enabled () const { return enable_collect_funcs_; } - bool collect_assignments_enabled() const { return enable_collect_assings_; } - bool vardef_disabled () const { return disable_vardef_; } - bool rsrvd_sym_usr_disabled () const { return disable_rsrvd_sym_usr_; } - bool zero_return_disabled () const { return disable_zero_return_; } - - bool function_enabled(const std::string& function_name) const - { - if (disabled_func_set_.empty()) - return true; - else - return (disabled_func_set_.end() == disabled_func_set_.find(function_name)); - } - - bool control_struct_enabled(const std::string& control_struct) const - { - if (disabled_ctrl_set_.empty()) - return true; - else - return (disabled_ctrl_set_.end() == disabled_ctrl_set_.find(control_struct)); - } - - bool logic_enabled(const std::string& logic_operation) const - { - if (disabled_logic_set_.empty()) - return true; - else - return (disabled_logic_set_.end() == disabled_logic_set_.find(logic_operation)); - } - - bool arithmetic_enabled(const details::operator_type& arithmetic_operation) const - { - if (disabled_logic_set_.empty()) - return true; - else - return disabled_arithmetic_set_.end() == disabled_arithmetic_set_ - .find(arith_opr_to_string(arithmetic_operation)); - } - - bool assignment_enabled(const details::operator_type& assignment) const - { - if (disabled_assignment_set_.empty()) - return true; - else - return disabled_assignment_set_.end() == disabled_assignment_set_ - .find(assign_opr_to_string(assignment)); - } - - bool inequality_enabled(const details::operator_type& inequality) const - { - if (disabled_inequality_set_.empty()) - return true; - else - return disabled_inequality_set_.end() == disabled_inequality_set_ - .find(inequality_opr_to_string(inequality)); - } - - bool function_disabled(const std::string& function_name) const - { - if (disabled_func_set_.empty()) - return false; - else - return (disabled_func_set_.end() != disabled_func_set_.find(function_name)); - } - - bool control_struct_disabled(const std::string& control_struct) const - { - if (disabled_ctrl_set_.empty()) - return false; - else - return (disabled_ctrl_set_.end() != disabled_ctrl_set_.find(control_struct)); - } - - bool logic_disabled(const std::string& logic_operation) const - { - if (disabled_logic_set_.empty()) - return false; - else - return (disabled_logic_set_.end() != disabled_logic_set_.find(logic_operation)); - } - - bool assignment_disabled(const details::operator_type assignment_operation) const - { - if (disabled_assignment_set_.empty()) - return false; - else - return disabled_assignment_set_.end() != disabled_assignment_set_ - .find(assign_opr_to_string(assignment_operation)); - } - - bool logic_disabled(const details::operator_type logic_operation) const - { - if (disabled_logic_set_.empty()) - return false; - else - return disabled_logic_set_.end() != disabled_logic_set_ - .find(logic_opr_to_string(logic_operation)); - } - - bool arithmetic_disabled(const details::operator_type arithmetic_operation) const - { - if (disabled_arithmetic_set_.empty()) - return false; - else - return disabled_arithmetic_set_.end() != disabled_arithmetic_set_ - .find(arith_opr_to_string(arithmetic_operation)); - } - - bool inequality_disabled(const details::operator_type& inequality) const - { - if (disabled_inequality_set_.empty()) - return false; - else - return disabled_inequality_set_.end() != disabled_inequality_set_ - .find(inequality_opr_to_string(inequality)); - } - - settings_store& disable_base_function(settings_base_funcs bf) - { - if ( - (e_bf_unknown != bf) && - (static_cast(bf) < (details::base_function_list_size + 1)) - ) - { - disabled_func_set_.insert(details::base_function_list[bf - 1]); - } - - return (*this); - } - - settings_store& disable_control_structure(settings_control_structs ctrl_struct) - { - if ( - (e_ctrl_unknown != ctrl_struct) && - (static_cast(ctrl_struct) < (details::cntrl_struct_list_size + 1)) - ) - { - disabled_ctrl_set_.insert(details::cntrl_struct_list[ctrl_struct - 1]); - } - - return (*this); - } - - settings_store& disable_logic_operation(settings_logic_opr logic) - { - if ( - (e_logic_unknown != logic) && - (static_cast(logic) < (details::logic_ops_list_size + 1)) - ) - { - disabled_logic_set_.insert(details::logic_ops_list[logic - 1]); - } - - return (*this); - } - - settings_store& disable_arithmetic_operation(settings_arithmetic_opr arithmetic) - { - if ( - (e_arith_unknown != arithmetic) && - (static_cast(arithmetic) < (details::arithmetic_ops_list_size + 1)) - ) - { - disabled_arithmetic_set_.insert(details::arithmetic_ops_list[arithmetic - 1]); - } - - return (*this); - } - - settings_store& disable_assignment_operation(settings_assignment_opr assignment) - { - if ( - (e_assign_unknown != assignment) && - (static_cast(assignment) < (details::assignment_ops_list_size + 1)) - ) - { - disabled_assignment_set_.insert(details::assignment_ops_list[assignment - 1]); - } - - return (*this); - } - - settings_store& disable_inequality_operation(settings_inequality_opr inequality) - { - if ( - (e_ineq_unknown != inequality) && - (static_cast(inequality) < (details::inequality_ops_list_size + 1)) - ) - { - disabled_inequality_set_.insert(details::inequality_ops_list[inequality - 1]); - } - - return (*this); - } - - settings_store& enable_base_function(settings_base_funcs bf) - { - if ( - (e_bf_unknown != bf) && - (static_cast(bf) < (details::base_function_list_size + 1)) - ) - { - const des_itr_t itr = disabled_func_set_.find(details::base_function_list[bf - 1]); - - if (disabled_func_set_.end() != itr) - { - disabled_func_set_.erase(itr); - } - } - - return (*this); - } - - settings_store& enable_control_structure(settings_control_structs ctrl_struct) - { - if ( - (e_ctrl_unknown != ctrl_struct) && - (static_cast(ctrl_struct) < (details::cntrl_struct_list_size + 1)) - ) - { - const des_itr_t itr = disabled_ctrl_set_.find(details::cntrl_struct_list[ctrl_struct - 1]); - - if (disabled_ctrl_set_.end() != itr) - { - disabled_ctrl_set_.erase(itr); - } - } - - return (*this); - } - - settings_store& enable_logic_operation(settings_logic_opr logic) - { - if ( - (e_logic_unknown != logic) && - (static_cast(logic) < (details::logic_ops_list_size + 1)) - ) - { - const des_itr_t itr = disabled_logic_set_.find(details::logic_ops_list[logic - 1]); - - if (disabled_logic_set_.end() != itr) - { - disabled_logic_set_.erase(itr); - } - } - - return (*this); - } - - settings_store& enable_arithmetic_operation(settings_arithmetic_opr arithmetic) - { - if ( - (e_arith_unknown != arithmetic) && - (static_cast(arithmetic) < (details::arithmetic_ops_list_size + 1)) - ) - { - const des_itr_t itr = disabled_arithmetic_set_.find(details::arithmetic_ops_list[arithmetic - 1]); - - if (disabled_arithmetic_set_.end() != itr) - { - disabled_arithmetic_set_.erase(itr); - } - } - - return (*this); - } - - settings_store& enable_assignment_operation(settings_assignment_opr assignment) - { - if ( - (e_assign_unknown != assignment) && - (static_cast(assignment) < (details::assignment_ops_list_size + 1)) - ) - { - const des_itr_t itr = disabled_assignment_set_.find(details::assignment_ops_list[assignment - 1]); - - if (disabled_assignment_set_.end() != itr) - { - disabled_assignment_set_.erase(itr); - } - } - - return (*this); - } - - settings_store& enable_inequality_operation(settings_inequality_opr inequality) - { - if ( - (e_ineq_unknown != inequality) && - (static_cast(inequality) < (details::inequality_ops_list_size + 1)) - ) - { - const des_itr_t itr = disabled_inequality_set_.find(details::inequality_ops_list[inequality - 1]); - - if (disabled_inequality_set_.end() != itr) - { - disabled_inequality_set_.erase(itr); - } - } - - return (*this); - } - - void set_max_stack_depth(const std::size_t mx_stack_depth) - { - max_stack_depth_ = mx_stack_depth; - } - - void set_max_node_depth(const std::size_t max_node_depth) - { - max_node_depth_ = max_node_depth; - } - - private: - - void load_compile_options(const std::size_t compile_options) - { - enable_replacer_ = (compile_options & e_replacer ) == e_replacer; - enable_joiner_ = (compile_options & e_joiner ) == e_joiner; - enable_numeric_check_ = (compile_options & e_numeric_check ) == e_numeric_check; - enable_bracket_check_ = (compile_options & e_bracket_check ) == e_bracket_check; - enable_sequence_check_ = (compile_options & e_sequence_check ) == e_sequence_check; - enable_commutative_check_ = (compile_options & e_commutative_check ) == e_commutative_check; - enable_strength_reduction_ = (compile_options & e_strength_reduction ) == e_strength_reduction; - enable_collect_vars_ = (compile_options & e_collect_vars ) == e_collect_vars; - enable_collect_funcs_ = (compile_options & e_collect_funcs ) == e_collect_funcs; - enable_collect_assings_ = (compile_options & e_collect_assings ) == e_collect_assings; - disable_vardef_ = (compile_options & e_disable_vardef ) == e_disable_vardef; - disable_rsrvd_sym_usr_ = (compile_options & e_disable_usr_on_rsrvd) == e_disable_usr_on_rsrvd; - disable_zero_return_ = (compile_options & e_disable_zero_return ) == e_disable_zero_return; - } - - std::string assign_opr_to_string(details::operator_type opr) const - { - switch (opr) - { - case details::e_assign : return ":="; - case details::e_addass : return "+="; - case details::e_subass : return "-="; - case details::e_mulass : return "*="; - case details::e_divass : return "/="; - case details::e_modass : return "%="; - default : return ""; - } - } - - std::string arith_opr_to_string(details::operator_type opr) const - { - switch (opr) - { - case details::e_add : return "+"; - case details::e_sub : return "-"; - case details::e_mul : return "*"; - case details::e_div : return "/"; - case details::e_mod : return "%"; - default : return ""; - } - } - - std::string inequality_opr_to_string(details::operator_type opr) const - { - switch (opr) - { - case details::e_lt : return "<"; - case details::e_lte : return "<="; - case details::e_eq : return "=="; - case details::e_equal : return "="; - case details::e_ne : return "!="; - case details::e_nequal: return "<>"; - case details::e_gte : return ">="; - case details::e_gt : return ">"; - default : return ""; - } - } - - std::string logic_opr_to_string(details::operator_type opr) const - { - switch (opr) - { - case details::e_and : return "and" ; - case details::e_or : return "or" ; - case details::e_xor : return "xor" ; - case details::e_nand : return "nand"; - case details::e_nor : return "nor" ; - case details::e_xnor : return "xnor"; - case details::e_notl : return "not" ; - default : return "" ; - } - } - - bool enable_replacer_; - bool enable_joiner_; - bool enable_numeric_check_; - bool enable_bracket_check_; - bool enable_sequence_check_; - bool enable_commutative_check_; - bool enable_strength_reduction_; - bool enable_collect_vars_; - bool enable_collect_funcs_; - bool enable_collect_assings_; - bool disable_vardef_; - bool disable_rsrvd_sym_usr_; - bool disable_zero_return_; - - disabled_entity_set_t disabled_func_set_ ; - disabled_entity_set_t disabled_ctrl_set_ ; - disabled_entity_set_t disabled_logic_set_; - disabled_entity_set_t disabled_arithmetic_set_; - disabled_entity_set_t disabled_assignment_set_; - disabled_entity_set_t disabled_inequality_set_; - - std::size_t max_stack_depth_; - std::size_t max_node_depth_; - - friend class parser; - }; - - typedef settings_store settings_t; - - parser(const settings_t& settings = settings_t()) - : settings_(settings), - resolve_unknown_symbol_(false), - results_context_(0), - unknown_symbol_resolver_(reinterpret_cast(0)), - #ifdef _MSC_VER - #pragma warning(push) - #pragma warning (disable:4355) - #endif - sem_(*this), - #ifdef _MSC_VER - #pragma warning(pop) - #endif - operator_joiner_2_(2), - operator_joiner_3_(3), - loop_runtime_check_(0) - { - init_precompilation(); - - load_operations_map (base_ops_map_ ); - load_unary_operations_map (unary_op_map_ ); - load_binary_operations_map (binary_op_map_ ); - load_inv_binary_operations_map(inv_binary_op_map_); - load_sf3_map (sf3_map_ ); - load_sf4_map (sf4_map_ ); - - expression_generator_.init_synthesize_map(); - expression_generator_.set_parser(*this); - expression_generator_.set_uom(unary_op_map_); - expression_generator_.set_bom(binary_op_map_); - expression_generator_.set_ibom(inv_binary_op_map_); - expression_generator_.set_sf3m(sf3_map_); - expression_generator_.set_sf4m(sf4_map_); - expression_generator_.set_strength_reduction_state(settings_.strength_reduction_enabled()); - } - - ~parser() - {} - - inline void init_precompilation() - { - if (settings_.collect_variables_enabled()) - dec_.collect_variables() = true; - - if (settings_.collect_functions_enabled()) - dec_.collect_functions() = true; - - if (settings_.collect_assignments_enabled()) - dec_.collect_assignments() = true; - - if (settings_.replacer_enabled()) - { - symbol_replacer_.clear(); - symbol_replacer_.add_replace("true" , "1", lexer::token::e_number); - symbol_replacer_.add_replace("false", "0", lexer::token::e_number); - helper_assembly_.token_modifier_list.clear(); - helper_assembly_.register_modifier(&symbol_replacer_); - } - - if (settings_.commutative_check_enabled()) - { - for (std::size_t i = 0; i < details::reserved_words_size; ++i) - { - commutative_inserter_.ignore_symbol(details::reserved_words[i]); - } - - helper_assembly_.token_inserter_list.clear(); - helper_assembly_.register_inserter(&commutative_inserter_); - } - - if (settings_.joiner_enabled()) - { - helper_assembly_.token_joiner_list.clear(); - helper_assembly_.register_joiner(&operator_joiner_2_); - helper_assembly_.register_joiner(&operator_joiner_3_); - } - - if ( - settings_.numeric_check_enabled () || - settings_.bracket_check_enabled () || - settings_.sequence_check_enabled() - ) - { - helper_assembly_.token_scanner_list.clear(); - - if (settings_.numeric_check_enabled()) - { - helper_assembly_.register_scanner(&numeric_checker_); - } - - if (settings_.bracket_check_enabled()) - { - helper_assembly_.register_scanner(&bracket_checker_); - } - - if (settings_.sequence_check_enabled()) - { - helper_assembly_.register_scanner(&sequence_validator_ ); - helper_assembly_.register_scanner(&sequence_validator_3tkns_); - } - } - } - - inline bool compile(const std::string& expression_string, expression& expr) - { - state_ .reset(); - error_list_ .clear(); - brkcnt_list_ .clear(); - synthesis_error_.clear(); - sem_ .cleanup(); - - return_cleanup(); - - expression_generator_.set_allocator(node_allocator_); - - if (expression_string.empty()) - { - set_error( - make_error(parser_error::e_syntax, - "ERR001 - Empty expression!", - exprtk_error_location)); - - return false; - } - - if (!init(expression_string)) - { - process_lexer_errors(); - return false; - } - - if (lexer().empty()) - { - set_error( - make_error(parser_error::e_syntax, - "ERR002 - Empty expression!", - exprtk_error_location)); - - return false; - } - - if (!run_assemblies()) - { - return false; - } - - symtab_store_.symtab_list_ = expr.get_symbol_table_list(); - dec_.clear(); - - lexer().begin(); - - next_token(); - - expression_node_ptr e = parse_corpus(); - - if ((0 != e) && (token_t::e_eof == current_token().type)) - { - bool* retinvk_ptr = 0; - - if (state_.return_stmt_present) - { - dec_.return_present_ = true; - - e = expression_generator_ - .return_envelope(e, results_context_, retinvk_ptr); - } - - expr.set_expression(e); - expr.set_retinvk(retinvk_ptr); - - register_local_vars(expr); - register_return_results(expr); - - return !(!expr); - } - else - { - if (error_list_.empty()) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR003 - Invalid expression encountered", - exprtk_error_location)); - } - - if ((0 != e) && branch_deletable(e)) - { - destroy_node(e); - } - - dec_.clear (); - sem_.cleanup (); - return_cleanup(); - - return false; - } - } - - inline expression_t compile(const std::string& expression_string, symbol_table_t& symtab) - { - expression_t expression; - - expression.register_symbol_table(symtab); - - compile(expression_string,expression); - - return expression; - } - - void process_lexer_errors() - { - for (std::size_t i = 0; i < lexer().size(); ++i) - { - if (lexer()[i].is_error()) - { - std::string diagnostic = "ERR004 - "; - - switch (lexer()[i].type) - { - case lexer::token::e_error : diagnostic += "General token error"; - break; - - case lexer::token::e_err_symbol : diagnostic += "Symbol error"; - break; - - case lexer::token::e_err_number : diagnostic += "Invalid numeric token"; - break; - - case lexer::token::e_err_string : diagnostic += "Invalid string token"; - break; - - case lexer::token::e_err_sfunc : diagnostic += "Invalid special function token"; - break; - - default : diagnostic += "Unknown compiler error"; - } - - set_error( - make_error(parser_error::e_lexer, - lexer()[i], - diagnostic + ": " + lexer()[i].value, - exprtk_error_location)); - } - } - } - - inline bool run_assemblies() - { - if (settings_.commutative_check_enabled()) - { - helper_assembly_.run_inserters(lexer()); - } - - if (settings_.joiner_enabled()) - { - helper_assembly_.run_joiners(lexer()); - } - - if (settings_.replacer_enabled()) - { - helper_assembly_.run_modifiers(lexer()); - } - - if ( - settings_.numeric_check_enabled () || - settings_.bracket_check_enabled () || - settings_.sequence_check_enabled() - ) - { - if (!helper_assembly_.run_scanners(lexer())) - { - if (helper_assembly_.error_token_scanner) - { - lexer::helper::bracket_checker* bracket_checker_ptr = 0; - lexer::helper::numeric_checker* numeric_checker_ptr = 0; - lexer::helper::sequence_validator* sequence_validator_ptr = 0; - lexer::helper::sequence_validator_3tokens* sequence_validator3_ptr = 0; - - if (0 != (bracket_checker_ptr = dynamic_cast(helper_assembly_.error_token_scanner))) - { - set_error( - make_error(parser_error::e_token, - bracket_checker_ptr->error_token(), - "ERR005 - Mismatched brackets: '" + bracket_checker_ptr->error_token().value + "'", - exprtk_error_location)); - } - else if (0 != (numeric_checker_ptr = dynamic_cast(helper_assembly_.error_token_scanner))) - { - for (std::size_t i = 0; i < numeric_checker_ptr->error_count(); ++i) - { - lexer::token error_token = lexer()[numeric_checker_ptr->error_index(i)]; - - set_error( - make_error(parser_error::e_token, - error_token, - "ERR006 - Invalid numeric token: '" + error_token.value + "'", - exprtk_error_location)); - } - - if (numeric_checker_ptr->error_count()) - { - numeric_checker_ptr->clear_errors(); - } - } - else if (0 != (sequence_validator_ptr = dynamic_cast(helper_assembly_.error_token_scanner))) - { - for (std::size_t i = 0; i < sequence_validator_ptr->error_count(); ++i) - { - std::pair error_token = sequence_validator_ptr->error(i); - - set_error( - make_error(parser_error::e_token, - error_token.first, - "ERR007 - Invalid token sequence: '" + - error_token.first.value + "' and '" + - error_token.second.value + "'", - exprtk_error_location)); - } - - if (sequence_validator_ptr->error_count()) - { - sequence_validator_ptr->clear_errors(); - } - } - else if (0 != (sequence_validator3_ptr = dynamic_cast(helper_assembly_.error_token_scanner))) - { - for (std::size_t i = 0; i < sequence_validator3_ptr->error_count(); ++i) - { - std::pair error_token = sequence_validator3_ptr->error(i); - - set_error( - make_error(parser_error::e_token, - error_token.first, - "ERR008 - Invalid token sequence: '" + - error_token.first.value + "' and '" + - error_token.second.value + "'", - exprtk_error_location)); - } - - if (sequence_validator3_ptr->error_count()) - { - sequence_validator3_ptr->clear_errors(); - } - } - } - - return false; - } - } - - return true; - } - - inline settings_store& settings() - { - return settings_; - } - - inline parser_error::type get_error(const std::size_t& index) const - { - if (index < error_list_.size()) - return error_list_[index]; - else - throw std::invalid_argument("parser::get_error() - Invalid error index specificed"); - } - - inline std::string error() const - { - if (!error_list_.empty()) - { - return error_list_[0].diagnostic; - } - else - return std::string("No Error"); - } - - inline std::size_t error_count() const - { - return error_list_.size(); - } - - inline dependent_entity_collector& dec() - { - return dec_; - } - - inline bool replace_symbol(const std::string& old_symbol, const std::string& new_symbol) - { - if (!settings_.replacer_enabled()) - return false; - else if (details::is_reserved_word(old_symbol)) - return false; - else - return symbol_replacer_.add_replace(old_symbol,new_symbol,lexer::token::e_symbol); - } - - inline bool remove_replace_symbol(const std::string& symbol) - { - if (!settings_.replacer_enabled()) - return false; - else if (details::is_reserved_word(symbol)) - return false; - else - return symbol_replacer_.remove(symbol); - } - - inline void enable_unknown_symbol_resolver(unknown_symbol_resolver* usr = reinterpret_cast(0)) - { - resolve_unknown_symbol_ = true; - - if (usr) - unknown_symbol_resolver_ = usr; - else - unknown_symbol_resolver_ = &default_usr_; - } - - inline void enable_unknown_symbol_resolver(unknown_symbol_resolver& usr) - { - enable_unknown_symbol_resolver(&usr); - } - - inline void disable_unknown_symbol_resolver() - { - resolve_unknown_symbol_ = false; - unknown_symbol_resolver_ = &default_usr_; - } - - inline void register_loop_runtime_check(loop_runtime_check& lrtchk) - { - loop_runtime_check_ = &lrtchk; - } - - inline void clear_loop_runtime_check() - { - loop_runtime_check_ = loop_runtime_check_ptr(0); - } - - private: - - inline bool valid_base_operation(const std::string& symbol) const - { - const std::size_t length = symbol.size(); - - if ( - (length < 3) || // Shortest base op symbol length - (length > 9) // Longest base op symbol length - ) - return false; - else - return settings_.function_enabled(symbol) && - (base_ops_map_.end() != base_ops_map_.find(symbol)); - } - - inline bool valid_vararg_operation(const std::string& symbol) const - { - static const std::string s_sum = "sum" ; - static const std::string s_mul = "mul" ; - static const std::string s_avg = "avg" ; - static const std::string s_min = "min" ; - static const std::string s_max = "max" ; - static const std::string s_mand = "mand"; - static const std::string s_mor = "mor" ; - static const std::string s_multi = "~" ; - static const std::string s_mswitch = "[*]" ; - - return - ( - details::imatch(symbol,s_sum ) || - details::imatch(symbol,s_mul ) || - details::imatch(symbol,s_avg ) || - details::imatch(symbol,s_min ) || - details::imatch(symbol,s_max ) || - details::imatch(symbol,s_mand ) || - details::imatch(symbol,s_mor ) || - details::imatch(symbol,s_multi ) || - details::imatch(symbol,s_mswitch) - ) && - settings_.function_enabled(symbol); - } - - bool is_invalid_logic_operation(const details::operator_type operation) const - { - return settings_.logic_disabled(operation); - } - - bool is_invalid_arithmetic_operation(const details::operator_type operation) const - { - return settings_.arithmetic_disabled(operation); - } - - bool is_invalid_assignment_operation(const details::operator_type operation) const - { - return settings_.assignment_disabled(operation); - } - - bool is_invalid_inequality_operation(const details::operator_type operation) const - { - return settings_.inequality_disabled(operation); - } - - #ifdef exprtk_enable_debugging - inline void next_token() - { - const std::string ct_str = current_token().value; - const std::size_t ct_pos = current_token().position; - parser_helper::next_token(); - const std::string depth(2 * state_.scope_depth,' '); - exprtk_debug(("%s" - "prev[%s | %04d] --> curr[%s | %04d] stack_level: %3d\n", - depth.c_str(), - ct_str.c_str(), - static_cast(ct_pos), - current_token().value.c_str(), - static_cast(current_token().position), - static_cast(state_.stack_depth))); - } - #endif - - inline expression_node_ptr parse_corpus() - { - std::vector arg_list; - std::vector side_effect_list; - - scoped_vec_delete sdd((*this),arg_list); - - lexer::token begin_token; - lexer::token end_token; - - for ( ; ; ) - { - state_.side_effect_present = false; - - begin_token = current_token(); - - expression_node_ptr arg = parse_expression(); - - if (0 == arg) - { - if (error_list_.empty()) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR009 - Invalid expression encountered", - exprtk_error_location)); - } - - return error_node(); - } - else - { - arg_list.push_back(arg); - - side_effect_list.push_back(state_.side_effect_present); - - end_token = current_token(); - - const std::string sub_expr = construct_subexpr(begin_token, end_token); - - exprtk_debug(("parse_corpus(%02d) Subexpr: %s\n", - static_cast(arg_list.size() - 1), - sub_expr.c_str())); - - exprtk_debug(("parse_corpus(%02d) - Side effect present: %s\n", - static_cast(arg_list.size() - 1), - state_.side_effect_present ? "true" : "false")); - - exprtk_debug(("-------------------------------------------------\n")); - } - - if (lexer().finished()) - break; - else if (token_is(token_t::e_eof,prsrhlpr_t::e_hold)) - { - if (lexer().finished()) - break; - else - next_token(); - } - } - - if ( - !arg_list.empty() && - is_return_node(arg_list.back()) - ) - { - dec_.final_stmt_return_ = true; - } - - const expression_node_ptr result = simplify(arg_list,side_effect_list); - - sdd.delete_ptr = (0 == result); - - return result; - } - - std::string construct_subexpr(lexer::token& begin_token, lexer::token& end_token) - { - std::string result = lexer().substr(begin_token.position,end_token.position); - - for (std::size_t i = 0; i < result.size(); ++i) - { - if (details::is_whitespace(result[i])) result[i] = ' '; - } - - return result; - } - - static const precedence_level default_precedence = e_level00; - - struct state_t - { - inline void set(const precedence_level& l, - const precedence_level& r, - const details::operator_type& o) - { - left = l; - right = r; - operation = o; - } - - inline void reset() - { - left = e_level00; - right = e_level00; - operation = details::e_default; - } - - precedence_level left; - precedence_level right; - details::operator_type operation; - }; - - inline expression_node_ptr parse_expression(precedence_level precedence = e_level00) - { - stack_limit_handler slh(*this); - - if (!slh) - { - return error_node(); - } - - expression_node_ptr expression = parse_branch(precedence); - - if (0 == expression) - { - return error_node(); - } - - bool break_loop = false; - - state_t current_state; - - for ( ; ; ) - { - current_state.reset(); - - switch (current_token().type) - { - case token_t::e_assign : current_state.set(e_level00,e_level00, details::e_assign); break; - case token_t::e_addass : current_state.set(e_level00,e_level00, details::e_addass); break; - case token_t::e_subass : current_state.set(e_level00,e_level00, details::e_subass); break; - case token_t::e_mulass : current_state.set(e_level00,e_level00, details::e_mulass); break; - case token_t::e_divass : current_state.set(e_level00,e_level00, details::e_divass); break; - case token_t::e_modass : current_state.set(e_level00,e_level00, details::e_modass); break; - case token_t::e_swap : current_state.set(e_level00,e_level00, details::e_swap ); break; - case token_t::e_lt : current_state.set(e_level05,e_level06, details:: e_lt); break; - case token_t::e_lte : current_state.set(e_level05,e_level06, details:: e_lte); break; - case token_t::e_eq : current_state.set(e_level05,e_level06, details:: e_eq); break; - case token_t::e_ne : current_state.set(e_level05,e_level06, details:: e_ne); break; - case token_t::e_gte : current_state.set(e_level05,e_level06, details:: e_gte); break; - case token_t::e_gt : current_state.set(e_level05,e_level06, details:: e_gt); break; - case token_t::e_add : current_state.set(e_level07,e_level08, details:: e_add); break; - case token_t::e_sub : current_state.set(e_level07,e_level08, details:: e_sub); break; - case token_t::e_div : current_state.set(e_level10,e_level11, details:: e_div); break; - case token_t::e_mul : current_state.set(e_level10,e_level11, details:: e_mul); break; - case token_t::e_mod : current_state.set(e_level10,e_level11, details:: e_mod); break; - case token_t::e_pow : current_state.set(e_level12,e_level12, details:: e_pow); break; - default : if (token_t::e_symbol == current_token().type) - { - static const std::string s_and = "and"; - static const std::string s_nand = "nand"; - static const std::string s_or = "or"; - static const std::string s_nor = "nor"; - static const std::string s_xor = "xor"; - static const std::string s_xnor = "xnor"; - static const std::string s_in = "in"; - static const std::string s_like = "like"; - static const std::string s_ilike = "ilike"; - static const std::string s_and1 = "&"; - static const std::string s_or1 = "|"; - static const std::string s_not = "not"; - - if (details::imatch(current_token().value,s_and)) - { - current_state.set(e_level03, e_level04, details::e_and); - break; - } - else if (details::imatch(current_token().value,s_and1)) - { - #ifndef exprtk_disable_sc_andor - current_state.set(e_level03, e_level04, details::e_scand); - #else - current_state.set(e_level03, e_level04, details::e_and); - #endif - break; - } - else if (details::imatch(current_token().value,s_nand)) - { - current_state.set(e_level03, e_level04, details::e_nand); - break; - } - else if (details::imatch(current_token().value,s_or)) - { - current_state.set(e_level01, e_level02, details::e_or); - break; - } - else if (details::imatch(current_token().value,s_or1)) - { - #ifndef exprtk_disable_sc_andor - current_state.set(e_level01, e_level02, details::e_scor); - #else - current_state.set(e_level01, e_level02, details::e_or); - #endif - break; - } - else if (details::imatch(current_token().value,s_nor)) - { - current_state.set(e_level01, e_level02, details::e_nor); - break; - } - else if (details::imatch(current_token().value,s_xor)) - { - current_state.set(e_level01, e_level02, details::e_xor); - break; - } - else if (details::imatch(current_token().value,s_xnor)) - { - current_state.set(e_level01, e_level02, details::e_xnor); - break; - } - else if (details::imatch(current_token().value,s_in)) - { - current_state.set(e_level04, e_level04, details::e_in); - break; - } - else if (details::imatch(current_token().value,s_like)) - { - current_state.set(e_level04, e_level04, details::e_like); - break; - } - else if (details::imatch(current_token().value,s_ilike)) - { - current_state.set(e_level04, e_level04, details::e_ilike); - break; - } - else if (details::imatch(current_token().value,s_not)) - { - break; - } - } - - break_loop = true; - } - - if (break_loop) - { - parse_pending_string_rangesize(expression); - break; - } - else if (current_state.left < precedence) - break; - - const lexer::token prev_token = current_token(); - - next_token(); - - expression_node_ptr right_branch = error_node(); - expression_node_ptr new_expression = error_node(); - - if (is_invalid_logic_operation(current_state.operation)) - { - free_node(node_allocator_,expression); - - set_error( - make_error(parser_error::e_syntax, - prev_token, - "ERR010 - Invalid or disabled logic operation '" + details::to_str(current_state.operation) + "'", - exprtk_error_location)); - - return error_node(); - } - else if (is_invalid_arithmetic_operation(current_state.operation)) - { - free_node(node_allocator_,expression); - - set_error( - make_error(parser_error::e_syntax, - prev_token, - "ERR011 - Invalid or disabled arithmetic operation '" + details::to_str(current_state.operation) + "'", - exprtk_error_location)); - - return error_node(); - } - else if (is_invalid_inequality_operation(current_state.operation)) - { - free_node(node_allocator_,expression); - - set_error( - make_error(parser_error::e_syntax, - prev_token, - "ERR012 - Invalid inequality operation '" + details::to_str(current_state.operation) + "'", - exprtk_error_location)); - - return error_node(); - } - else if (is_invalid_assignment_operation(current_state.operation)) - { - free_node(node_allocator_,expression); - - set_error( - make_error(parser_error::e_syntax, - prev_token, - "ERR013 - Invalid or disabled assignment operation '" + details::to_str(current_state.operation) + "'", - exprtk_error_location)); - - return error_node(); - } - - if (0 != (right_branch = parse_expression(current_state.right))) - { - if ( - details::is_return_node(expression ) || - details::is_return_node(right_branch) - ) - { - free_node(node_allocator_, expression ); - free_node(node_allocator_, right_branch); - - set_error( - make_error(parser_error::e_syntax, - prev_token, - "ERR014 - Return statements cannot be part of sub-expressions", - exprtk_error_location)); - - return error_node(); - } - - new_expression = expression_generator_ - ( - current_state.operation, - expression, - right_branch - ); - } - - if (0 == new_expression) - { - if (error_list_.empty()) - { - set_error( - make_error(parser_error::e_syntax, - prev_token, - !synthesis_error_.empty() ? - synthesis_error_ : - "ERR015 - General parsing error at token: '" + prev_token.value + "'", - exprtk_error_location)); - } - - free_node(node_allocator_, expression ); - free_node(node_allocator_, right_branch); - - return error_node(); - } - else - { - if ( - token_is(token_t::e_ternary,prsrhlpr_t::e_hold) && - (precedence == e_level00) - ) - { - expression = parse_ternary_conditional_statement(new_expression); - } - else - expression = new_expression; - - parse_pending_string_rangesize(expression); - } - } - - if ((0 != expression) && (expression->node_depth() > settings_.max_node_depth_)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR016 - Expression depth of " + details::to_str(static_cast(expression->node_depth())) + - " exceeds maximum allowed expression depth of " + details::to_str(static_cast(settings_.max_node_depth_)), - exprtk_error_location)); - - free_node(node_allocator_,expression); - - return error_node(); - } - - return expression; - } - - bool simplify_unary_negation_branch(expression_node_ptr& node) - { - { - typedef details::unary_branch_node > ubn_t; - ubn_t* n = dynamic_cast(node); - - if (n) - { - expression_node_ptr un_r = n->branch(0); - n->release(); - free_node(node_allocator_,node); - node = un_r; - - return true; - } - } - - { - typedef details::unary_variable_node > uvn_t; - - uvn_t* n = dynamic_cast(node); - - if (n) - { - const T& v = n->v(); - expression_node_ptr return_node = error_node(); - - if ( - (0 != (return_node = symtab_store_.get_variable(v))) || - (0 != (return_node = sem_ .get_variable(v))) - ) - { - free_node(node_allocator_,node); - node = return_node; - - return true; - } - else - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR017 - Failed to find variable node in symbol table", - exprtk_error_location)); - - free_node(node_allocator_,node); - - return false; - } - } - } - - return false; - } - - static inline expression_node_ptr error_node() - { - return reinterpret_cast(0); - } - - struct scoped_expression_delete - { - scoped_expression_delete(parser& pr, expression_node_ptr& expression) - : delete_ptr(true), - parser_(pr), - expression_(expression) - {} - - ~scoped_expression_delete() - { - if (delete_ptr) - { - free_node(parser_.node_allocator_, expression_); - } - } - - bool delete_ptr; - parser& parser_; - expression_node_ptr& expression_; - - private: - - scoped_expression_delete& operator=(const scoped_expression_delete&); - }; - - template - struct scoped_delete - { - typedef Type* ptr_t; - - scoped_delete(parser& pr, ptr_t& p) - : delete_ptr(true), - parser_(pr), - p_(&p) - {} - - scoped_delete(parser& pr, ptr_t (&p)[N]) - : delete_ptr(true), - parser_(pr), - p_(&p[0]) - {} - - ~scoped_delete() - { - if (delete_ptr) - { - for (std::size_t i = 0; i < N; ++i) - { - free_node(parser_.node_allocator_, p_[i]); - } - } - } - - bool delete_ptr; - parser& parser_; - ptr_t* p_; - - private: - - scoped_delete& operator=(const scoped_delete&); - }; - - template - struct scoped_deq_delete - { - typedef Type* ptr_t; - - scoped_deq_delete(parser& pr, std::deque& deq) - : delete_ptr(true), - parser_(pr), - deq_(deq) - {} - - ~scoped_deq_delete() - { - if (delete_ptr && !deq_.empty()) - { - for (std::size_t i = 0; i < deq_.size(); ++i) - { - free_node(parser_.node_allocator_,deq_[i]); - } - - deq_.clear(); - } - } - - bool delete_ptr; - parser& parser_; - std::deque& deq_; - - private: - - scoped_deq_delete& operator=(const scoped_deq_delete&); - }; - - template - struct scoped_vec_delete - { - typedef Type* ptr_t; - - scoped_vec_delete(parser& pr, std::vector& vec) - : delete_ptr(true), - parser_(pr), - vec_(vec) - {} - - ~scoped_vec_delete() - { - if (delete_ptr && !vec_.empty()) - { - for (std::size_t i = 0; i < vec_.size(); ++i) - { - free_node(parser_.node_allocator_,vec_[i]); - } - - vec_.clear(); - } - } - - bool delete_ptr; - parser& parser_; - std::vector& vec_; - - private: - - scoped_vec_delete& operator=(const scoped_vec_delete&); - }; - - struct scoped_bool_negator - { - explicit scoped_bool_negator(bool& bb) - : b(bb) - { b = !b; } - - ~scoped_bool_negator() - { b = !b; } - - bool& b; - }; - - struct scoped_bool_or_restorer - { - explicit scoped_bool_or_restorer(bool& bb) - : b(bb), - original_value_(bb) - {} - - ~scoped_bool_or_restorer() - { - b = b || original_value_; - } - - bool& b; - bool original_value_; - }; - - struct scoped_inc_dec - { - explicit scoped_inc_dec(std::size_t& v) - : v_(v) - { ++v_; } - - ~scoped_inc_dec() - { - assert(v_ > 0); - --v_; - } - - std::size_t& v_; - }; - - inline expression_node_ptr parse_function_invocation(ifunction* function, const std::string& function_name) - { - expression_node_ptr func_node = reinterpret_cast(0); - - switch (function->param_count) - { - case 0 : func_node = parse_function_call_0 (function,function_name); break; - case 1 : func_node = parse_function_call< 1>(function,function_name); break; - case 2 : func_node = parse_function_call< 2>(function,function_name); break; - case 3 : func_node = parse_function_call< 3>(function,function_name); break; - case 4 : func_node = parse_function_call< 4>(function,function_name); break; - case 5 : func_node = parse_function_call< 5>(function,function_name); break; - case 6 : func_node = parse_function_call< 6>(function,function_name); break; - case 7 : func_node = parse_function_call< 7>(function,function_name); break; - case 8 : func_node = parse_function_call< 8>(function,function_name); break; - case 9 : func_node = parse_function_call< 9>(function,function_name); break; - case 10 : func_node = parse_function_call<10>(function,function_name); break; - case 11 : func_node = parse_function_call<11>(function,function_name); break; - case 12 : func_node = parse_function_call<12>(function,function_name); break; - case 13 : func_node = parse_function_call<13>(function,function_name); break; - case 14 : func_node = parse_function_call<14>(function,function_name); break; - case 15 : func_node = parse_function_call<15>(function,function_name); break; - case 16 : func_node = parse_function_call<16>(function,function_name); break; - case 17 : func_node = parse_function_call<17>(function,function_name); break; - case 18 : func_node = parse_function_call<18>(function,function_name); break; - case 19 : func_node = parse_function_call<19>(function,function_name); break; - case 20 : func_node = parse_function_call<20>(function,function_name); break; - default : { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR018 - Invalid number of parameters for function: '" + function_name + "'", - exprtk_error_location)); - - return error_node(); - } - } - - if (func_node) - return func_node; - else - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR019 - Failed to generate call to function: '" + function_name + "'", - exprtk_error_location)); - - return error_node(); - } - } - - template - inline expression_node_ptr parse_function_call(ifunction* function, const std::string& function_name) - { - #ifdef _MSC_VER - #pragma warning(push) - #pragma warning(disable: 4127) - #endif - if (0 == NumberofParameters) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR020 - Expecting ifunction '" + function_name + "' to have non-zero parameter count", - exprtk_error_location)); - - return error_node(); - } - #ifdef _MSC_VER - #pragma warning(pop) - #endif - - expression_node_ptr branch[NumberofParameters]; - expression_node_ptr result = error_node(); - - std::fill_n(branch, NumberofParameters, reinterpret_cast(0)); - - scoped_delete sd((*this),branch); - - next_token(); - - if (!token_is(token_t::e_lbracket)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR021 - Expecting argument list for function: '" + function_name + "'", - exprtk_error_location)); - - return error_node(); - } - - for (int i = 0; i < static_cast(NumberofParameters); ++i) - { - branch[i] = parse_expression(); - - if (0 == branch[i]) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR022 - Failed to parse argument " + details::to_str(i) + " for function: '" + function_name + "'", - exprtk_error_location)); - - return error_node(); - } - else if (i < static_cast(NumberofParameters - 1)) - { - if (!token_is(token_t::e_comma)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR023 - Invalid number of arguments for function: '" + function_name + "'", - exprtk_error_location)); - - return error_node(); - } - } - } - - if (!token_is(token_t::e_rbracket)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR024 - Invalid number of arguments for function: '" + function_name + "'", - exprtk_error_location)); - - return error_node(); - } - else - result = expression_generator_.function(function,branch); - - sd.delete_ptr = (0 == result); - - return result; - } - - inline expression_node_ptr parse_function_call_0(ifunction* function, const std::string& function_name) - { - expression_node_ptr result = expression_generator_.function(function); - - state_.side_effect_present = function->has_side_effects(); - - next_token(); - - if ( - token_is(token_t::e_lbracket) && - !token_is(token_t::e_rbracket) - ) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR025 - Expecting '()' to proceed call to function: '" + function_name + "'", - exprtk_error_location)); - - free_node(node_allocator_,result); - - return error_node(); - } - else - return result; - } - - template - inline std::size_t parse_base_function_call(expression_node_ptr (¶m_list)[MaxNumberofParameters], const std::string& function_name = "") - { - std::fill_n(param_list, MaxNumberofParameters, reinterpret_cast(0)); - - scoped_delete sd((*this),param_list); - - next_token(); - - if (!token_is(token_t::e_lbracket)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR026 - Expected a '(' at start of function call to '" + function_name + - "', instead got: '" + current_token().value + "'", - exprtk_error_location)); - - return 0; - } - - if (token_is(token_t::e_rbracket, e_hold)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR027 - Expected at least one input parameter for function call '" + function_name + "'", - exprtk_error_location)); - - return 0; - } - - std::size_t param_index = 0; - - for (; param_index < MaxNumberofParameters; ++param_index) - { - param_list[param_index] = parse_expression(); - - if (0 == param_list[param_index]) - return 0; - else if (token_is(token_t::e_rbracket)) - { - sd.delete_ptr = false; - break; - } - else if (token_is(token_t::e_comma)) - continue; - else - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR028 - Expected a ',' between function input parameters, instead got: '" + current_token().value + "'", - exprtk_error_location)); - - return 0; - } - } - - if (sd.delete_ptr) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR029 - Invalid number of input parameters passed to function '" + function_name + "'", - exprtk_error_location)); - - return 0; - } - - return (param_index + 1); - } - - inline expression_node_ptr parse_base_operation() - { - typedef std::pair map_range_t; - - const std::string operation_name = current_token().value; - const token_t diagnostic_token = current_token(); - - map_range_t itr_range = base_ops_map_.equal_range(operation_name); - - if (0 == std::distance(itr_range.first,itr_range.second)) - { - set_error( - make_error(parser_error::e_syntax, - diagnostic_token, - "ERR030 - No entry found for base operation: " + operation_name, - exprtk_error_location)); - - return error_node(); - } - - static const std::size_t MaxNumberofParameters = 4; - expression_node_ptr param_list[MaxNumberofParameters] = {0}; - - const std::size_t parameter_count = parse_base_function_call(param_list, operation_name); - - if ((parameter_count > 0) && (parameter_count <= MaxNumberofParameters)) - { - for (base_ops_map_t::iterator itr = itr_range.first; itr != itr_range.second; ++itr) - { - const details::base_operation_t& operation = itr->second; - - if (operation.num_params == parameter_count) - { - switch (parameter_count) - { - #define base_opr_case(N) \ - case N : { \ - expression_node_ptr pl##N[N] = {0}; \ - std::copy(param_list, param_list + N, pl##N); \ - lodge_symbol(operation_name, e_st_function); \ - return expression_generator_(operation.type, pl##N); \ - } \ - - base_opr_case(1) - base_opr_case(2) - base_opr_case(3) - base_opr_case(4) - #undef base_opr_case - } - } - } - } - - for (std::size_t i = 0; i < MaxNumberofParameters; ++i) - { - free_node(node_allocator_, param_list[i]); - } - - set_error( - make_error(parser_error::e_syntax, - diagnostic_token, - "ERR031 - Invalid number of input parameters for call to function: '" + operation_name + "'", - exprtk_error_location)); - - return error_node(); - } - - inline expression_node_ptr parse_conditional_statement_01(expression_node_ptr condition) - { - // Parse: [if][(][condition][,][consequent][,][alternative][)] - - expression_node_ptr consequent = error_node(); - expression_node_ptr alternative = error_node(); - - bool result = true; - - if (!token_is(token_t::e_comma)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR032 - Expected ',' between if-statement condition and consequent", - exprtk_error_location)); - result = false; - } - else if (0 == (consequent = parse_expression())) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR033 - Failed to parse consequent for if-statement", - exprtk_error_location)); - result = false; - } - else if (!token_is(token_t::e_comma)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR034 - Expected ',' between if-statement consequent and alternative", - exprtk_error_location)); - result = false; - } - else if (0 == (alternative = parse_expression())) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR035 - Failed to parse alternative for if-statement", - exprtk_error_location)); - result = false; - } - else if (!token_is(token_t::e_rbracket)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR036 - Expected ')' at the end of if-statement", - exprtk_error_location)); - result = false; - } - - #ifndef exprtk_disable_string_capabilities - if (result) - { - const bool consq_is_str = is_generally_string_node(consequent ); - const bool alter_is_str = is_generally_string_node(alternative); - - if (consq_is_str || alter_is_str) - { - if (consq_is_str && alter_is_str) - { - return expression_generator_ - .conditional_string(condition, consequent, alternative); - } - - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR037 - Return types of ternary if-statement differ", - exprtk_error_location)); - - result = false; - } - } - #endif - - if (!result) - { - free_node(node_allocator_, condition ); - free_node(node_allocator_, consequent ); - free_node(node_allocator_, alternative); - - return error_node(); - } - else - return expression_generator_ - .conditional(condition, consequent, alternative); - } - - inline expression_node_ptr parse_conditional_statement_02(expression_node_ptr condition) - { - expression_node_ptr consequent = error_node(); - expression_node_ptr alternative = error_node(); - - bool result = true; - - if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) - { - if (0 == (consequent = parse_multi_sequence("if-statement-01"))) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR038 - Failed to parse body of consequent for if-statement", - exprtk_error_location)); - - result = false; - } - } - else - { - if ( - settings_.commutative_check_enabled() && - token_is(token_t::e_mul,prsrhlpr_t::e_hold) - ) - { - next_token(); - } - - if (0 != (consequent = parse_expression())) - { - if (!token_is(token_t::e_eof)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR039 - Expected ';' at the end of the consequent for if-statement", - exprtk_error_location)); - - result = false; - } - } - else - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR040 - Failed to parse body of consequent for if-statement", - exprtk_error_location)); - - result = false; - } - } - - if (result) - { - if (details::imatch(current_token().value,"else")) - { - next_token(); - - if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) - { - if (0 == (alternative = parse_multi_sequence("else-statement-01"))) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR041 - Failed to parse body of the 'else' for if-statement", - exprtk_error_location)); - - result = false; - } - } - else if (details::imatch(current_token().value,"if")) - { - if (0 == (alternative = parse_conditional_statement())) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR042 - Failed to parse body of if-else statement", - exprtk_error_location)); - - result = false; - } - } - else if (0 != (alternative = parse_expression())) - { - if (!token_is(token_t::e_eof)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR043 - Expected ';' at the end of the 'else-if' for the if-statement", - exprtk_error_location)); - - result = false; - } - } - else - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR044 - Failed to parse body of the 'else' for if-statement", - exprtk_error_location)); - - result = false; - } - } - } - - #ifndef exprtk_disable_string_capabilities - if (result) - { - const bool consq_is_str = is_generally_string_node(consequent ); - const bool alter_is_str = is_generally_string_node(alternative); - - if (consq_is_str || alter_is_str) - { - if (consq_is_str && alter_is_str) - { - return expression_generator_ - .conditional_string(condition, consequent, alternative); - } - - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR045 - Return types of ternary if-statement differ", - exprtk_error_location)); - - result = false; - } - } - #endif - - if (!result) - { - free_node(node_allocator_, condition ); - free_node(node_allocator_, consequent ); - free_node(node_allocator_, alternative); - - return error_node(); - } - else - return expression_generator_ - .conditional(condition, consequent, alternative); - } - - inline expression_node_ptr parse_conditional_statement() - { - expression_node_ptr condition = error_node(); - - next_token(); - - if (!token_is(token_t::e_lbracket)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR046 - Expected '(' at start of if-statement, instead got: '" + current_token().value + "'", - exprtk_error_location)); - - return error_node(); - } - else if (0 == (condition = parse_expression())) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR047 - Failed to parse condition for if-statement", - exprtk_error_location)); - - return error_node(); - } - else if (token_is(token_t::e_comma,prsrhlpr_t::e_hold)) - { - // if (x,y,z) - return parse_conditional_statement_01(condition); - } - else if (token_is(token_t::e_rbracket)) - { - // 00. if (x) y; - // 01. if (x) y; else z; - // 02. if (x) y; else {z0; ... zn;} - // 03. if (x) y; else if (z) w; - // 04. if (x) y; else if (z) w; else u; - // 05. if (x) y; else if (z) w; else {u0; ... un;} - // 06. if (x) y; else if (z) {w0; ... wn;} - // 07. if (x) {y0; ... yn;} - // 08. if (x) {y0; ... yn;} else z; - // 09. if (x) {y0; ... yn;} else {z0; ... zn;}; - // 10. if (x) {y0; ... yn;} else if (z) w; - // 11. if (x) {y0; ... yn;} else if (z) w; else u; - // 12. if (x) {y0; ... nex;} else if (z) w; else {u0 ... un;} - // 13. if (x) {y0; ... yn;} else if (z) {w0; ... wn;} - return parse_conditional_statement_02(condition); - } - - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR048 - Invalid if-statement", - exprtk_error_location)); - - free_node(node_allocator_,condition); - - return error_node(); - } - - inline expression_node_ptr parse_ternary_conditional_statement(expression_node_ptr condition) - { - // Parse: [condition][?][consequent][:][alternative] - expression_node_ptr consequent = error_node(); - expression_node_ptr alternative = error_node(); - - bool result = true; - - if (0 == condition) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR049 - Encountered invalid condition branch for ternary if-statement", - exprtk_error_location)); - - return error_node(); - } - else if (!token_is(token_t::e_ternary)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR050 - Expected '?' after condition of ternary if-statement", - exprtk_error_location)); - - result = false; - } - else if (0 == (consequent = parse_expression())) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR051 - Failed to parse consequent for ternary if-statement", - exprtk_error_location)); - - result = false; - } - else if (!token_is(token_t::e_colon)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR052 - Expected ':' between ternary if-statement consequent and alternative", - exprtk_error_location)); - - result = false; - } - else if (0 == (alternative = parse_expression())) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR053 - Failed to parse alternative for ternary if-statement", - exprtk_error_location)); - - result = false; - } - - #ifndef exprtk_disable_string_capabilities - if (result) - { - const bool consq_is_str = is_generally_string_node(consequent ); - const bool alter_is_str = is_generally_string_node(alternative); - - if (consq_is_str || alter_is_str) - { - if (consq_is_str && alter_is_str) - { - return expression_generator_ - .conditional_string(condition, consequent, alternative); - } - - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR054 - Return types of ternary if-statement differ", - exprtk_error_location)); - - result = false; - } - } - #endif - - if (!result) - { - free_node(node_allocator_, condition ); - free_node(node_allocator_, consequent ); - free_node(node_allocator_, alternative); - - return error_node(); - } - else - return expression_generator_ - .conditional(condition, consequent, alternative); - } - - inline expression_node_ptr parse_not_statement() - { - if (settings_.logic_disabled("not")) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR055 - Invalid or disabled logic operation 'not'", - exprtk_error_location)); - - return error_node(); - } - - return parse_base_operation(); - } - - inline expression_node_ptr parse_while_loop() - { - // Parse: [while][(][test expr][)][{][expression][}] - expression_node_ptr condition = error_node(); - expression_node_ptr branch = error_node(); - expression_node_ptr result_node = error_node(); - - bool result = true; - - next_token(); - - if (!token_is(token_t::e_lbracket)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR056 - Expected '(' at start of while-loop condition statement", - exprtk_error_location)); - - return error_node(); - } - else if (0 == (condition = parse_expression())) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR057 - Failed to parse condition for while-loop", - exprtk_error_location)); - - return error_node(); - } - else if (!token_is(token_t::e_rbracket)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR058 - Expected ')' at end of while-loop condition statement", - exprtk_error_location)); - - result = false; - } - - brkcnt_list_.push_front(false); - - if (result) - { - scoped_inc_dec sid(state_.parsing_loop_stmt_count); - - if (0 == (branch = parse_multi_sequence("while-loop"))) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR059 - Failed to parse body of while-loop")); - result = false; - } - else if (0 == (result_node = expression_generator_.while_loop(condition, - branch, - brkcnt_list_.front()))) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR060 - Failed to synthesize while-loop", - exprtk_error_location)); - - result = false; - } - } - - if (!result) - { - free_node(node_allocator_, branch ); - free_node(node_allocator_, condition ); - free_node(node_allocator_, result_node); - - brkcnt_list_.pop_front(); - - return error_node(); - } - else - return result_node; - } - - inline expression_node_ptr parse_repeat_until_loop() - { - // Parse: [repeat][{][expression][}][until][(][test expr][)] - expression_node_ptr condition = error_node(); - expression_node_ptr branch = error_node(); - next_token(); - - std::vector arg_list; - std::vector side_effect_list; - - scoped_vec_delete sdd((*this),arg_list); - - brkcnt_list_.push_front(false); - - if (details::imatch(current_token().value,"until")) - { - next_token(); - branch = node_allocator_.allocate >(); - } - else - { - const token_t::token_type seperator = token_t::e_eof; - - scope_handler sh(*this); - - scoped_bool_or_restorer sbr(state_.side_effect_present); - - scoped_inc_dec sid(state_.parsing_loop_stmt_count); - - for ( ; ; ) - { - state_.side_effect_present = false; - - expression_node_ptr arg = parse_expression(); - - if (0 == arg) - return error_node(); - else - { - arg_list.push_back(arg); - side_effect_list.push_back(state_.side_effect_present); - } - - if (details::imatch(current_token().value,"until")) - { - next_token(); - break; - } - - const bool is_next_until = peek_token_is(token_t::e_symbol) && - peek_token_is("until"); - - if (!token_is(seperator) && is_next_until) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR061 - Expected '" + token_t::to_str(seperator) + "' in body of repeat until loop", - exprtk_error_location)); - - return error_node(); - } - - if (details::imatch(current_token().value,"until")) - { - next_token(); - break; - } - } - - branch = simplify(arg_list,side_effect_list); - - sdd.delete_ptr = (0 == branch); - - if (sdd.delete_ptr) - { - brkcnt_list_.pop_front(); - - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR062 - Failed to parse body of repeat until loop", - exprtk_error_location)); - - return error_node(); - } - } - - if (!token_is(token_t::e_lbracket)) - { - brkcnt_list_.pop_front(); - - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR063 - Expected '(' before condition statement of repeat until loop", - exprtk_error_location)); - - free_node(node_allocator_,branch); - - return error_node(); - } - else if (0 == (condition = parse_expression())) - { - brkcnt_list_.pop_front(); - - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR064 - Failed to parse condition for repeat until loop", - exprtk_error_location)); - - free_node(node_allocator_,branch); - - return error_node(); - } - else if (!token_is(token_t::e_rbracket)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR065 - Expected ')' after condition of repeat until loop", - exprtk_error_location)); - - free_node(node_allocator_, branch ); - free_node(node_allocator_, condition); - - brkcnt_list_.pop_front(); - - return error_node(); - } - - expression_node_ptr result; - - result = expression_generator_ - .repeat_until_loop(condition, branch, brkcnt_list_.front()); - - if (0 == result) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR066 - Failed to synthesize repeat until loop", - exprtk_error_location)); - - free_node(node_allocator_,condition); - - brkcnt_list_.pop_front(); - - return error_node(); - } - else - { - brkcnt_list_.pop_front(); - return result; - } - } - - inline expression_node_ptr parse_for_loop() - { - expression_node_ptr initialiser = error_node(); - expression_node_ptr condition = error_node(); - expression_node_ptr incrementor = error_node(); - expression_node_ptr loop_body = error_node(); - - scope_element* se = 0; - bool result = true; - - next_token(); - - scope_handler sh(*this); - - if (!token_is(token_t::e_lbracket)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR067 - Expected '(' at start of for-loop", - exprtk_error_location)); - - return error_node(); - } - - if (!token_is(token_t::e_eof)) - { - if ( - !token_is(token_t::e_symbol,prsrhlpr_t::e_hold) && - details::imatch(current_token().value,"var") - ) - { - next_token(); - - if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR068 - Expected a variable at the start of initialiser section of for-loop", - exprtk_error_location)); - - return error_node(); - } - else if (!peek_token_is(token_t::e_assign)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR069 - Expected variable assignment of initialiser section of for-loop", - exprtk_error_location)); - - return error_node(); - } - - const std::string loop_counter_symbol = current_token().value; - - se = &sem_.get_element(loop_counter_symbol); - - if ((se->name == loop_counter_symbol) && se->active) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR070 - For-loop variable '" + loop_counter_symbol+ "' is being shadowed by a previous declaration", - exprtk_error_location)); - - return error_node(); - } - else if (!symtab_store_.is_variable(loop_counter_symbol)) - { - if ( - !se->active && - (se->name == loop_counter_symbol) && - (se->type == scope_element::e_variable) - ) - { - se->active = true; - se->ref_count++; - } - else - { - scope_element nse; - nse.name = loop_counter_symbol; - nse.active = true; - nse.ref_count = 1; - nse.type = scope_element::e_variable; - nse.depth = state_.scope_depth; - nse.data = new T(T(0)); - nse.var_node = node_allocator_.allocate(*reinterpret_cast(nse.data)); - - if (!sem_.add_element(nse)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR071 - Failed to add new local variable '" + loop_counter_symbol + "' to SEM", - exprtk_error_location)); - - sem_.free_element(nse); - - result = false; - } - else - { - exprtk_debug(("parse_for_loop() - INFO - Added new local variable: %s\n",nse.name.c_str())); - - state_.activate_side_effect("parse_for_loop()"); - } - } - } - } - - if (0 == (initialiser = parse_expression())) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR072 - Failed to parse initialiser of for-loop", - exprtk_error_location)); - - result = false; - } - else if (!token_is(token_t::e_eof)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR073 - Expected ';' after initialiser of for-loop", - exprtk_error_location)); - - result = false; - } - } - - if (!token_is(token_t::e_eof)) - { - if (0 == (condition = parse_expression())) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR074 - Failed to parse condition of for-loop", - exprtk_error_location)); - - result = false; - } - else if (!token_is(token_t::e_eof)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR075 - Expected ';' after condition section of for-loop", - exprtk_error_location)); - - result = false; - } - } - - if (!token_is(token_t::e_rbracket)) - { - if (0 == (incrementor = parse_expression())) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR076 - Failed to parse incrementor of for-loop", - exprtk_error_location)); - - result = false; - } - else if (!token_is(token_t::e_rbracket)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR077 - Expected ')' after incrementor section of for-loop", - exprtk_error_location)); - - result = false; - } - } - - if (result) - { - brkcnt_list_.push_front(false); - - scoped_inc_dec sid(state_.parsing_loop_stmt_count); - - if (0 == (loop_body = parse_multi_sequence("for-loop"))) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR078 - Failed to parse body of for-loop", - exprtk_error_location)); - - result = false; - } - } - - if (!result) - { - if (se) - { - se->ref_count--; - } - - free_node(node_allocator_, initialiser); - free_node(node_allocator_, condition ); - free_node(node_allocator_, incrementor); - free_node(node_allocator_, loop_body ); - - if (!brkcnt_list_.empty()) - { - brkcnt_list_.pop_front(); - } - - return error_node(); - } - else - { - expression_node_ptr result_node = - expression_generator_.for_loop(initialiser, - condition, - incrementor, - loop_body, - brkcnt_list_.front()); - brkcnt_list_.pop_front(); - - return result_node; - } - } - - inline expression_node_ptr parse_switch_statement() - { - std::vector arg_list; - expression_node_ptr result = error_node(); - - if (!details::imatch(current_token().value,"switch")) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR079 - Expected keyword 'switch'", - exprtk_error_location)); - - return error_node(); - } - - scoped_vec_delete svd((*this),arg_list); - - next_token(); - - if (!token_is(token_t::e_lcrlbracket)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR080 - Expected '{' for call to switch statement", - exprtk_error_location)); - - return error_node(); - } - - expression_node_ptr default_statement = error_node(); - - scoped_expression_delete defstmt_delete((*this), default_statement); - - for ( ; ; ) - { - if (details::imatch("case",current_token().value)) - { - next_token(); - - expression_node_ptr condition = parse_expression(); - - if (0 == condition) - return error_node(); - else if (!token_is(token_t::e_colon)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR081 - Expected ':' for case of switch statement", - exprtk_error_location)); - - free_node(node_allocator_, condition); - - return error_node(); - } - - expression_node_ptr consequent = parse_expression(); - - if (0 == consequent) - { - free_node(node_allocator_, condition); - - return error_node(); - } - else if (!token_is(token_t::e_eof)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR082 - Expected ';' at end of case for switch statement", - exprtk_error_location)); - - free_node(node_allocator_, condition ); - free_node(node_allocator_, consequent); - - return error_node(); - } - - // Can we optimise away the case statement? - if (is_constant_node(condition) && is_false(condition)) - { - free_node(node_allocator_, condition ); - free_node(node_allocator_, consequent); - } - else - { - arg_list.push_back(condition ); - arg_list.push_back(consequent); - } - - } - else if (details::imatch("default",current_token().value)) - { - if (0 != default_statement) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR083 - Multiple default cases for switch statement", - exprtk_error_location)); - - return error_node(); - } - - next_token(); - - if (!token_is(token_t::e_colon)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR084 - Expected ':' for default of switch statement", - exprtk_error_location)); - - return error_node(); - } - - if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) - default_statement = parse_multi_sequence("switch-default"); - else - default_statement = parse_expression(); - - if (0 == default_statement) - return error_node(); - else if (!token_is(token_t::e_eof)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR085 - Expected ';' at end of default for switch statement", - exprtk_error_location)); - - return error_node(); - } - } - else if (token_is(token_t::e_rcrlbracket)) - break; - else - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR086 - Expected '}' at end of switch statement", - exprtk_error_location)); - - return error_node(); - } - } - - const bool default_statement_present = (0 != default_statement); - - if (default_statement_present) - { - arg_list.push_back(default_statement); - } - - result = expression_generator_.switch_statement(arg_list, (0 != default_statement)); - - svd.delete_ptr = (0 == result); - defstmt_delete.delete_ptr = (0 == result); - - return result; - } - - inline expression_node_ptr parse_multi_switch_statement() - { - std::vector arg_list; - - if (!details::imatch(current_token().value,"[*]")) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR087 - Expected token '[*]'", - exprtk_error_location)); - - return error_node(); - } - - scoped_vec_delete svd((*this),arg_list); - - next_token(); - - if (!token_is(token_t::e_lcrlbracket)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR088 - Expected '{' for call to [*] statement", - exprtk_error_location)); - - return error_node(); - } - - for ( ; ; ) - { - if (!details::imatch("case",current_token().value)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR089 - Expected a 'case' statement for multi-switch", - exprtk_error_location)); - - return error_node(); - } - - next_token(); - - expression_node_ptr condition = parse_expression(); - - if (0 == condition) - return error_node(); - - if (!token_is(token_t::e_colon)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR090 - Expected ':' for case of [*] statement", - exprtk_error_location)); - - return error_node(); - } - - expression_node_ptr consequent = parse_expression(); - - if (0 == consequent) - return error_node(); - - if (!token_is(token_t::e_eof)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR091 - Expected ';' at end of case for [*] statement", - exprtk_error_location)); - - return error_node(); - } - - // Can we optimise away the case statement? - if (is_constant_node(condition) && is_false(condition)) - { - free_node(node_allocator_, condition ); - free_node(node_allocator_, consequent); - } - else - { - arg_list.push_back(condition ); - arg_list.push_back(consequent); - } - - if (token_is(token_t::e_rcrlbracket,prsrhlpr_t::e_hold)) - { - break; - } - } - - if (!token_is(token_t::e_rcrlbracket)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR092 - Expected '}' at end of [*] statement", - exprtk_error_location)); - - return error_node(); - } - - const expression_node_ptr result = expression_generator_.multi_switch_statement(arg_list); - - svd.delete_ptr = (0 == result); - - return result; - } - - inline expression_node_ptr parse_vararg_function() - { - std::vector arg_list; - - details::operator_type opt_type = details::e_default; - const std::string symbol = current_token().value; - - if (details::imatch(symbol,"~")) - { - next_token(); - return parse_multi_sequence(); - } - else if (details::imatch(symbol,"[*]")) - { - return parse_multi_switch_statement(); - } - else if (details::imatch(symbol, "avg" )) opt_type = details::e_avg ; - else if (details::imatch(symbol, "mand")) opt_type = details::e_mand; - else if (details::imatch(symbol, "max" )) opt_type = details::e_max ; - else if (details::imatch(symbol, "min" )) opt_type = details::e_min ; - else if (details::imatch(symbol, "mor" )) opt_type = details::e_mor ; - else if (details::imatch(symbol, "mul" )) opt_type = details::e_prod; - else if (details::imatch(symbol, "sum" )) opt_type = details::e_sum ; - else - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR093 - Unsupported vararg function: " + symbol, - exprtk_error_location)); - - return error_node(); - } - - scoped_vec_delete sdd((*this),arg_list); - - lodge_symbol(symbol, e_st_function); - - next_token(); - - if (!token_is(token_t::e_lbracket)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR094 - Expected '(' for call to vararg function: " + symbol, - exprtk_error_location)); - - return error_node(); - } - - for ( ; ; ) - { - expression_node_ptr arg = parse_expression(); - - if (0 == arg) - return error_node(); - else - arg_list.push_back(arg); - - if (token_is(token_t::e_rbracket)) - break; - else if (!token_is(token_t::e_comma)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR095 - Expected ',' for call to vararg function: " + symbol, - exprtk_error_location)); - - return error_node(); - } - } - - const expression_node_ptr result = expression_generator_.vararg_function(opt_type,arg_list); - - sdd.delete_ptr = (0 == result); - return result; - } - - #ifndef exprtk_disable_string_capabilities - inline expression_node_ptr parse_string_range_statement(expression_node_ptr& expression) - { - if (!token_is(token_t::e_lsqrbracket)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR096 - Expected '[' as start of string range definition", - exprtk_error_location)); - - free_node(node_allocator_,expression); - - return error_node(); - } - else if (token_is(token_t::e_rsqrbracket)) - { - return node_allocator_.allocate >(expression); - } - - range_t rp; - - if (!parse_range(rp,true)) - { - free_node(node_allocator_,expression); - - return error_node(); - } - - expression_node_ptr result = expression_generator_(expression,rp); - - if (0 == result) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR097 - Failed to generate string range node", - exprtk_error_location)); - - free_node(node_allocator_,expression); - rp.free(); - } - - rp.clear(); - - return result; - } - #else - inline expression_node_ptr parse_string_range_statement(expression_node_ptr&) - { - return error_node(); - } - #endif - - inline void parse_pending_string_rangesize(expression_node_ptr& expression) - { - // Allow no more than 100 range calls, eg: s[][][]...[][] - const std::size_t max_rangesize_parses = 100; - - std::size_t i = 0; - - while - ( - (0 != expression) && - (i++ < max_rangesize_parses) && - error_list_.empty() && - is_generally_string_node(expression) && - token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold) - ) - { - expression = parse_string_range_statement(expression); - } - } - - template class Sequence> - inline expression_node_ptr simplify(Sequence& expression_list, - Sequence& side_effect_list, - const bool specialise_on_final_type = false) - { - if (expression_list.empty()) - return error_node(); - else if (1 == expression_list.size()) - return expression_list[0]; - - Sequence tmp_expression_list; - - bool return_node_present = false; - - for (std::size_t i = 0; i < (expression_list.size() - 1); ++i) - { - if (is_variable_node(expression_list[i])) - continue; - else if ( - is_return_node (expression_list[i]) || - is_break_node (expression_list[i]) || - is_continue_node(expression_list[i]) - ) - { - tmp_expression_list.push_back(expression_list[i]); - - // Remove all subexpressions after first short-circuit - // node has been encountered. - - for (std::size_t j = i + 1; j < expression_list.size(); ++j) - { - free_node(node_allocator_,expression_list[j]); - } - - return_node_present = true; - - break; - } - else if ( - is_constant_node(expression_list[i]) || - is_null_node (expression_list[i]) || - !side_effect_list[i] - ) - { - free_node(node_allocator_,expression_list[i]); - continue; - } - else - tmp_expression_list.push_back(expression_list[i]); - } - - if (!return_node_present) - { - tmp_expression_list.push_back(expression_list.back()); - } - - expression_list.swap(tmp_expression_list); - - if (tmp_expression_list.size() > expression_list.size()) - { - exprtk_debug(("simplify() - Reduced subexpressions from %d to %d\n", - static_cast(tmp_expression_list.size()), - static_cast(expression_list .size()))); - } - - if ( - return_node_present || - side_effect_list.back() || - (expression_list.size() > 1) - ) - state_.activate_side_effect("simplify()"); - - if (1 == expression_list.size()) - return expression_list[0]; - else if (specialise_on_final_type && is_generally_string_node(expression_list.back())) - return expression_generator_.vararg_function(details::e_smulti,expression_list); - else - return expression_generator_.vararg_function(details::e_multi,expression_list); - } - - inline expression_node_ptr parse_multi_sequence(const std::string& source = "") - { - token_t::token_type close_bracket = token_t::e_rcrlbracket; - token_t::token_type seperator = token_t::e_eof; - - if (!token_is(token_t::e_lcrlbracket)) - { - if (token_is(token_t::e_lbracket)) - { - close_bracket = token_t::e_rbracket; - seperator = token_t::e_comma; - } - else - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR098 - Expected '" + token_t::to_str(close_bracket) + "' for call to multi-sequence" + - ((!source.empty()) ? std::string(" section of " + source): ""), - exprtk_error_location)); - - return error_node(); - } - } - else if (token_is(token_t::e_rcrlbracket)) - { - return node_allocator_.allocate >(); - } - - std::vector arg_list; - std::vector side_effect_list; - - expression_node_ptr result = error_node(); - - scoped_vec_delete sdd((*this),arg_list); - - scope_handler sh(*this); - - scoped_bool_or_restorer sbr(state_.side_effect_present); - - for ( ; ; ) - { - state_.side_effect_present = false; - - expression_node_ptr arg = parse_expression(); - - if (0 == arg) - return error_node(); - else - { - arg_list.push_back(arg); - side_effect_list.push_back(state_.side_effect_present); - } - - if (token_is(close_bracket)) - break; - - const bool is_next_close = peek_token_is(close_bracket); - - if (!token_is(seperator) && is_next_close) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR099 - Expected '" + details::to_str(seperator) + "' for call to multi-sequence section of " + source, - exprtk_error_location)); - - return error_node(); - } - - if (token_is(close_bracket)) - break; - } - - result = simplify(arg_list,side_effect_list,source.empty()); - - sdd.delete_ptr = (0 == result); - return result; - } - - inline bool parse_range(range_t& rp, const bool skip_lsqr = false) - { - // Examples of valid ranges: - // 1. [1:5] -> 1..5 - // 2. [ :5] -> 0..5 - // 3. [1: ] -> 1..end - // 4. [x:y] -> x..y where x <= y - // 5. [x+1:y/2] -> x+1..y/2 where x+1 <= y/2 - // 6. [ :y] -> 0..y where 0 <= y - // 7. [x: ] -> x..end where x <= end - - rp.clear(); - - if (!skip_lsqr && !token_is(token_t::e_lsqrbracket)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR100 - Expected '[' for start of range", - exprtk_error_location)); - - return false; - } - - if (token_is(token_t::e_colon)) - { - rp.n0_c.first = true; - rp.n0_c.second = 0; - rp.cache.first = 0; - } - else - { - expression_node_ptr r0 = parse_expression(); - - if (0 == r0) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR101 - Failed parse begin section of range", - exprtk_error_location)); - - return false; - } - else if (is_constant_node(r0)) - { - const T r0_value = r0->value(); - - if (r0_value >= T(0)) - { - rp.n0_c.first = true; - rp.n0_c.second = static_cast(details::numeric::to_int64(r0_value)); - rp.cache.first = rp.n0_c.second; - } - - free_node(node_allocator_,r0); - - if (r0_value < T(0)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR102 - Range lower bound less than zero! Constraint: r0 >= 0", - exprtk_error_location)); - - return false; - } - } - else - { - rp.n0_e.first = true; - rp.n0_e.second = r0; - } - - if (!token_is(token_t::e_colon)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR103 - Expected ':' for break in range", - exprtk_error_location)); - - rp.free(); - - return false; - } - } - - if (token_is(token_t::e_rsqrbracket)) - { - rp.n1_c.first = true; - rp.n1_c.second = std::numeric_limits::max(); - } - else - { - expression_node_ptr r1 = parse_expression(); - - if (0 == r1) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR104 - Failed parse end section of range", - exprtk_error_location)); - - rp.free(); - - return false; - } - else if (is_constant_node(r1)) - { - const T r1_value = r1->value(); - - if (r1_value >= T(0)) - { - rp.n1_c.first = true; - rp.n1_c.second = static_cast(details::numeric::to_int64(r1_value)); - rp.cache.second = rp.n1_c.second; - } - - free_node(node_allocator_,r1); - - if (r1_value < T(0)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR105 - Range upper bound less than zero! Constraint: r1 >= 0", - exprtk_error_location)); - - rp.free(); - - return false; - } - } - else - { - rp.n1_e.first = true; - rp.n1_e.second = r1; - } - - if (!token_is(token_t::e_rsqrbracket)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR106 - Expected ']' for start of range", - exprtk_error_location)); - - rp.free(); - - return false; - } - } - - if (rp.const_range()) - { - std::size_t r0 = 0; - std::size_t r1 = 0; - - bool rp_result = false; - - try - { - rp_result = rp(r0, r1); - } - catch (std::runtime_error&) - {} - - if (!rp_result || (r0 > r1)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR107 - Invalid range, Constraint: r0 <= r1", - exprtk_error_location)); - - return false; - } - } - - return true; - } - - inline void lodge_symbol(const std::string& symbol, - const symbol_type st) - { - dec_.add_symbol(symbol,st); - } - - #ifndef exprtk_disable_string_capabilities - inline expression_node_ptr parse_string() - { - const std::string symbol = current_token().value; - - typedef details::stringvar_node* strvar_node_t; - - expression_node_ptr result = error_node(); - strvar_node_t const_str_node = static_cast(0); - - scope_element& se = sem_.get_active_element(symbol); - - if (scope_element::e_string == se.type) - { - se.active = true; - result = se.str_node; - lodge_symbol(symbol, e_st_local_string); - } - else - { - if (!symtab_store_.is_conststr_stringvar(symbol)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR108 - Unknown string symbol", - exprtk_error_location)); - - return error_node(); - } - - result = symtab_store_.get_stringvar(symbol); - - if (symtab_store_.is_constant_string(symbol)) - { - const_str_node = static_cast(result); - result = expression_generator_(const_str_node->str()); - } - - lodge_symbol(symbol, e_st_string); - } - - if (peek_token_is(token_t::e_lsqrbracket)) - { - next_token(); - - if (peek_token_is(token_t::e_rsqrbracket)) - { - next_token(); - next_token(); - - if (const_str_node) - { - free_node(node_allocator_,result); - - return expression_generator_(T(const_str_node->size())); - } - else - return node_allocator_.allocate > - (static_cast*>(result)->ref()); - } - - range_t rp; - - if (!parse_range(rp)) - { - free_node(node_allocator_,result); - - return error_node(); - } - else if (const_str_node) - { - free_node(node_allocator_,result); - result = expression_generator_(const_str_node->ref(),rp); - } - else - result = expression_generator_(static_cast*> - (result)->ref(), rp); - - if (result) - rp.clear(); - } - else - next_token(); - - return result; - } - #else - inline expression_node_ptr parse_string() - { - return error_node(); - } - #endif - - #ifndef exprtk_disable_string_capabilities - inline expression_node_ptr parse_const_string() - { - const std::string const_str = current_token().value; - expression_node_ptr result = expression_generator_(const_str); - - if (peek_token_is(token_t::e_lsqrbracket)) - { - next_token(); - - if (peek_token_is(token_t::e_rsqrbracket)) - { - next_token(); - next_token(); - - free_node(node_allocator_,result); - - return expression_generator_(T(const_str.size())); - } - - range_t rp; - - if (!parse_range(rp)) - { - free_node(node_allocator_,result); - rp.free(); - - return error_node(); - } - - free_node(node_allocator_,result); - - if (rp.n1_c.first && (rp.n1_c.second == std::numeric_limits::max())) - { - rp.n1_c.second = const_str.size() - 1; - rp.cache.second = rp.n1_c.second; - } - - if ( - (rp.n0_c.first && (rp.n0_c.second >= const_str.size())) || - (rp.n1_c.first && (rp.n1_c.second >= const_str.size())) - ) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR109 - Overflow in range for string: '" + const_str + "'[" + - (rp.n0_c.first ? details::to_str(static_cast(rp.n0_c.second)) : "?") + ":" + - (rp.n1_c.first ? details::to_str(static_cast(rp.n1_c.second)) : "?") + "]", - exprtk_error_location)); - - rp.free(); - - return error_node(); - } - - result = expression_generator_(const_str,rp); - - if (result) - rp.clear(); - } - else - next_token(); - - return result; - } - #else - inline expression_node_ptr parse_const_string() - { - return error_node(); - } - #endif - - inline expression_node_ptr parse_vector() - { - const std::string symbol = current_token().value; - - vector_holder_ptr vec = vector_holder_ptr(0); - - const scope_element& se = sem_.get_active_element(symbol); - - if ( - !details::imatch(se.name, symbol) || - (se.depth > state_.scope_depth) || - (scope_element::e_vector != se.type) - ) - { - if (0 == (vec = symtab_store_.get_vector(symbol))) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR110 - Symbol '" + symbol+ " not a vector", - exprtk_error_location)); - - return error_node(); - } - } - else - vec = se.vec_node; - - expression_node_ptr index_expr = error_node(); - - next_token(); - - if (!token_is(token_t::e_lsqrbracket)) - { - return node_allocator_.allocate(vec); - } - else if (token_is(token_t::e_rsqrbracket)) - { - return expression_generator_(T(vec->size())); - } - else if (0 == (index_expr = parse_expression())) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR111 - Failed to parse index for vector: '" + symbol + "'", - exprtk_error_location)); - - return error_node(); - } - else if (!token_is(token_t::e_rsqrbracket)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR112 - Expected ']' for index of vector: '" + symbol + "'", - exprtk_error_location)); - - free_node(node_allocator_,index_expr); - - return error_node(); - } - - // Perform compile-time range check - if (details::is_constant_node(index_expr)) - { - const std::size_t index = static_cast(details::numeric::to_int32(index_expr->value())); - const std::size_t vec_size = vec->size(); - - if (index >= vec_size) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR113 - Index of " + details::to_str(index) + " out of range for " - "vector '" + symbol + "' of size " + details::to_str(vec_size), - exprtk_error_location)); - - free_node(node_allocator_,index_expr); - - return error_node(); - } - } - - return expression_generator_.vector_element(symbol, vec, index_expr); - } - - inline expression_node_ptr parse_vararg_function_call(ivararg_function* vararg_function, const std::string& vararg_function_name) - { - std::vector arg_list; - - expression_node_ptr result = error_node(); - - scoped_vec_delete sdd((*this),arg_list); - - next_token(); - - if (token_is(token_t::e_lbracket)) - { - if (token_is(token_t::e_rbracket)) - { - if (!vararg_function->allow_zero_parameters()) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR114 - Zero parameter call to vararg function: " - + vararg_function_name + " not allowed", - exprtk_error_location)); - - return error_node(); - } - } - else - { - for ( ; ; ) - { - expression_node_ptr arg = parse_expression(); - - if (0 == arg) - return error_node(); - else - arg_list.push_back(arg); - - if (token_is(token_t::e_rbracket)) - break; - else if (!token_is(token_t::e_comma)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR115 - Expected ',' for call to vararg function: " - + vararg_function_name, - exprtk_error_location)); - - return error_node(); - } - } - } - } - else if (!vararg_function->allow_zero_parameters()) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR116 - Zero parameter call to vararg function: " - + vararg_function_name + " not allowed", - exprtk_error_location)); - - return error_node(); - } - - if (arg_list.size() < vararg_function->min_num_args()) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR117 - Invalid number of parameters to call to vararg function: " - + vararg_function_name + ", require at least " - + details::to_str(static_cast(vararg_function->min_num_args())) + " parameters", - exprtk_error_location)); - - return error_node(); - } - else if (arg_list.size() > vararg_function->max_num_args()) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR118 - Invalid number of parameters to call to vararg function: " - + vararg_function_name + ", require no more than " - + details::to_str(static_cast(vararg_function->max_num_args())) + " parameters", - exprtk_error_location)); - - return error_node(); - } - - result = expression_generator_.vararg_function_call(vararg_function,arg_list); - - sdd.delete_ptr = (0 == result); - - return result; - } - - class type_checker - { - public: - - enum return_type_t - { - e_overload = ' ', - e_numeric = 'T', - e_string = 'S' - }; - - struct function_prototype_t - { - return_type_t return_type; - std::string param_seq; - }; - - typedef parser parser_t; - typedef std::vector function_definition_list_t; - - type_checker(parser_t& p, - const std::string& func_name, - const std::string& func_prototypes, - const return_type_t default_return_type) - : invalid_state_(true), - parser_(p), - function_name_(func_name), - default_return_type_(default_return_type) - { - parse_function_prototypes(func_prototypes); - } - - bool verify(const std::string& param_seq, std::size_t& pseq_index) - { - if (function_definition_list_.empty()) - return true; - - std::vector > error_list; - - for (std::size_t i = 0; i < function_definition_list_.size(); ++i) - { - details::char_t diff_value = 0; - std::size_t diff_index = 0; - - const bool result = details::sequence_match(function_definition_list_[i].param_seq, - param_seq, - diff_index, diff_value); - - if (result) - { - pseq_index = i; - return true; - } - else - error_list.push_back(std::make_pair(diff_index, diff_value)); - } - - if (1 == error_list.size()) - { - parser_. - set_error( - make_error(parser_error::e_syntax, - parser_.current_token(), - "ERR119 - Failed parameter type check for function '" + function_name_ + "', " - "Expected '" + function_definition_list_[0].param_seq + - "' call set: '" + param_seq + "'", - exprtk_error_location)); - } - else - { - // find first with largest diff_index; - std::size_t max_diff_index = 0; - - for (std::size_t i = 1; i < error_list.size(); ++i) - { - if (error_list[i].first > error_list[max_diff_index].first) - { - max_diff_index = i; - } - } - - parser_. - set_error( - make_error(parser_error::e_syntax, - parser_.current_token(), - "ERR120 - Failed parameter type check for function '" + function_name_ + "', " - "Best match: '" + function_definition_list_[max_diff_index].param_seq + - "' call set: '" + param_seq + "'", - exprtk_error_location)); - } - - return false; - } - - std::size_t paramseq_count() const - { - return function_definition_list_.size(); - } - - std::string paramseq(const std::size_t& index) const - { - return function_definition_list_[index].param_seq; - } - - return_type_t return_type(const std::size_t& index) const - { - return function_definition_list_[index].return_type; - } - - bool invalid() const - { - return !invalid_state_; - } - - bool allow_zero_parameters() const - { - - for (std::size_t i = 0; i < function_definition_list_.size(); ++i) - { - if (std::string::npos != function_definition_list_[i].param_seq.find("Z")) - { - return true; - } - } - - return false; - } - - private: - - std::vector split_param_seq(const std::string& param_seq, const details::char_t delimiter = '|') const - { - std::string::const_iterator current_begin = param_seq.begin(); - std::string::const_iterator iter = param_seq.begin(); - - std::vector result; - - while (iter != param_seq.end()) - { - if (*iter == delimiter) - { - result.push_back(std::string(current_begin, iter)); - current_begin = ++iter; - } - else - ++iter; - } - - if (current_begin != iter) - { - result.push_back(std::string(current_begin, iter)); - } - - return result; - } - - inline bool is_valid_token(std::string param_seq, - function_prototype_t& funcproto) const - { - // Determine return type - funcproto.return_type = default_return_type_; - - if (param_seq.size() > 2) - { - if (':' == param_seq[1]) - { - // Note: Only overloaded igeneric functions can have return - // type definitions. - if (type_checker::e_overload != default_return_type_) - return false; - - switch (param_seq[0]) - { - case 'T' : funcproto.return_type = type_checker::e_numeric; - break; - - case 'S' : funcproto.return_type = type_checker::e_string; - break; - - default : return false; - } - - param_seq.erase(0,2); - } - } - - if ( - (std::string::npos != param_seq.find("?*")) || - (std::string::npos != param_seq.find("**")) - ) - { - return false; - } - else if ( - (std::string::npos == param_seq.find_first_not_of("STV*?|")) || - ("Z" == param_seq) - ) - { - funcproto.param_seq = param_seq; - return true; - } - - return false; - } - - void parse_function_prototypes(const std::string& func_prototypes) - { - if (func_prototypes.empty()) - return; - - std::vector param_seq_list = split_param_seq(func_prototypes); - - typedef std::map param_seq_map_t; - param_seq_map_t param_seq_map; - - for (std::size_t i = 0; i < param_seq_list.size(); ++i) - { - function_prototype_t func_proto; - - if (!is_valid_token(param_seq_list[i], func_proto)) - { - invalid_state_ = false; - - parser_. - set_error( - make_error(parser_error::e_syntax, - parser_.current_token(), - "ERR121 - Invalid parameter sequence of '" + param_seq_list[i] + - "' for function: " + function_name_, - exprtk_error_location)); - return; - } - - param_seq_map_t::const_iterator seq_itr = param_seq_map.find(param_seq_list[i]); - - if (param_seq_map.end() != seq_itr) - { - invalid_state_ = false; - - parser_. - set_error( - make_error(parser_error::e_syntax, - parser_.current_token(), - "ERR122 - Function '" + function_name_ + "' has a parameter sequence conflict between " + - "pseq_idx[" + details::to_str(seq_itr->second) + "] and" + - "pseq_idx[" + details::to_str(i) + "] " + - "param seq: " + param_seq_list[i], - exprtk_error_location)); - return; - } - - function_definition_list_.push_back(func_proto); - } - } - - type_checker(const type_checker&); - type_checker& operator=(const type_checker&); - - bool invalid_state_; - parser_t& parser_; - std::string function_name_; - const return_type_t default_return_type_; - function_definition_list_t function_definition_list_; - }; - - inline expression_node_ptr parse_generic_function_call(igeneric_function* function, const std::string& function_name) - { - std::vector arg_list; - - scoped_vec_delete sdd((*this),arg_list); - - next_token(); - - std::string param_type_list; - - type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_string); - - if (tc.invalid()) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR123 - Type checker instantiation failure for generic function: " + function_name, - exprtk_error_location)); - - return error_node(); - } - - if (token_is(token_t::e_lbracket)) - { - if (token_is(token_t::e_rbracket)) - { - if ( - !function->allow_zero_parameters() && - !tc .allow_zero_parameters() - ) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR124 - Zero parameter call to generic function: " - + function_name + " not allowed", - exprtk_error_location)); - - return error_node(); - } - } - else - { - for ( ; ; ) - { - expression_node_ptr arg = parse_expression(); - - if (0 == arg) - return error_node(); - - if (is_ivector_node(arg)) - param_type_list += 'V'; - else if (is_generally_string_node(arg)) - param_type_list += 'S'; - else // Everything else is assumed to be a scalar returning expression - param_type_list += 'T'; - - arg_list.push_back(arg); - - if (token_is(token_t::e_rbracket)) - break; - else if (!token_is(token_t::e_comma)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR125 - Expected ',' for call to generic function: " + function_name, - exprtk_error_location)); - - return error_node(); - } - } - } - } - else if ( - !function->parameter_sequence.empty() && - function->allow_zero_parameters () && - !tc .allow_zero_parameters () - ) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR126 - Zero parameter call to generic function: " - + function_name + " not allowed", - exprtk_error_location)); - - return error_node(); - } - - std::size_t param_seq_index = 0; - - if ( - state_.type_check_enabled && - !tc.verify(param_type_list, param_seq_index) - ) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR127 - Invalid input parameter sequence for call to generic function: " + function_name, - exprtk_error_location)); - - return error_node(); - } - - expression_node_ptr result = error_node(); - - if (tc.paramseq_count() <= 1) - result = expression_generator_ - .generic_function_call(function, arg_list); - else - result = expression_generator_ - .generic_function_call(function, arg_list, param_seq_index); - - sdd.delete_ptr = (0 == result); - - return result; - } - - inline bool parse_igeneric_function_params(std::string& param_type_list, - std::vector& arg_list, - const std::string& function_name, - igeneric_function* function, - const type_checker& tc) - { - if (token_is(token_t::e_lbracket)) - { - if (token_is(token_t::e_rbracket)) - { - if ( - !function->allow_zero_parameters() && - !tc .allow_zero_parameters() - ) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR128 - Zero parameter call to generic function: " - + function_name + " not allowed", - exprtk_error_location)); - - return false; - } - } - else - { - for ( ; ; ) - { - expression_node_ptr arg = parse_expression(); - - if (0 == arg) - return false; - - if (is_ivector_node(arg)) - param_type_list += 'V'; - else if (is_generally_string_node(arg)) - param_type_list += 'S'; - else // Everything else is a scalar returning expression - param_type_list += 'T'; - - arg_list.push_back(arg); - - if (token_is(token_t::e_rbracket)) - break; - else if (!token_is(token_t::e_comma)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR129 - Expected ',' for call to string function: " + function_name, - exprtk_error_location)); - - return false; - } - } - } - - return true; - } - else - return false; - } - - #ifndef exprtk_disable_string_capabilities - inline expression_node_ptr parse_string_function_call(igeneric_function* function, const std::string& function_name) - { - // Move pass the function name - next_token(); - - std::string param_type_list; - - type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_string); - - if ( - (!function->parameter_sequence.empty()) && - (0 == tc.paramseq_count()) - ) - { - return error_node(); - } - - std::vector arg_list; - scoped_vec_delete sdd((*this),arg_list); - - if (!parse_igeneric_function_params(param_type_list, arg_list, function_name, function, tc)) - { - return error_node(); - } - - std::size_t param_seq_index = 0; - - if (!tc.verify(param_type_list, param_seq_index)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR130 - Invalid input parameter sequence for call to string function: " + function_name, - exprtk_error_location)); - - return error_node(); - } - - expression_node_ptr result = error_node(); - - if (tc.paramseq_count() <= 1) - result = expression_generator_ - .string_function_call(function, arg_list); - else - result = expression_generator_ - .string_function_call(function, arg_list, param_seq_index); - - sdd.delete_ptr = (0 == result); - - return result; - } - - inline expression_node_ptr parse_overload_function_call(igeneric_function* function, const std::string& function_name) - { - // Move pass the function name - next_token(); - - std::string param_type_list; - - type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_overload); - - if ( - (!function->parameter_sequence.empty()) && - (0 == tc.paramseq_count()) - ) - { - return error_node(); - } - - std::vector arg_list; - scoped_vec_delete sdd((*this),arg_list); - - if (!parse_igeneric_function_params(param_type_list, arg_list, function_name, function, tc)) - { - return error_node(); - } - - std::size_t param_seq_index = 0; - - if (!tc.verify(param_type_list, param_seq_index)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR131 - Invalid input parameter sequence for call to overloaded function: " + function_name, - exprtk_error_location)); - - return error_node(); - } - - expression_node_ptr result = error_node(); - - if (type_checker::e_numeric == tc.return_type(param_seq_index)) - { - if (tc.paramseq_count() <= 1) - result = expression_generator_ - .generic_function_call(function, arg_list); - else - result = expression_generator_ - .generic_function_call(function, arg_list, param_seq_index); - } - else if (type_checker::e_string == tc.return_type(param_seq_index)) - { - if (tc.paramseq_count() <= 1) - result = expression_generator_ - .string_function_call(function, arg_list); - else - result = expression_generator_ - .string_function_call(function, arg_list, param_seq_index); - } - else - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR132 - Invalid return type for call to overloaded function: " + function_name, - exprtk_error_location)); - } - - sdd.delete_ptr = (0 == result); - return result; - } - #endif - - template - struct parse_special_function_impl - { - static inline expression_node_ptr process(parser& p, const details::operator_type opt_type, const std::string& sf_name) - { - expression_node_ptr branch[NumberOfParameters]; - expression_node_ptr result = error_node(); - - std::fill_n(branch, NumberOfParameters, reinterpret_cast(0)); - - scoped_delete sd(p,branch); - - p.next_token(); - - if (!p.token_is(token_t::e_lbracket)) - { - p.set_error( - make_error(parser_error::e_syntax, - p.current_token(), - "ERR133 - Expected '(' for special function '" + sf_name + "'", - exprtk_error_location)); - - return error_node(); - } - - for (std::size_t i = 0; i < NumberOfParameters; ++i) - { - branch[i] = p.parse_expression(); - - if (0 == branch[i]) - { - return p.error_node(); - } - else if (i < (NumberOfParameters - 1)) - { - if (!p.token_is(token_t::e_comma)) - { - p.set_error( - make_error(parser_error::e_syntax, - p.current_token(), - "ERR134 - Expected ',' before next parameter of special function '" + sf_name + "'", - exprtk_error_location)); - - return p.error_node(); - } - } - } - - if (!p.token_is(token_t::e_rbracket)) - { - p.set_error( - make_error(parser_error::e_syntax, - p.current_token(), - "ERR135 - Invalid number of parameters for special function '" + sf_name + "'", - exprtk_error_location)); - - return p.error_node(); - } - else - result = p.expression_generator_.special_function(opt_type,branch); - - sd.delete_ptr = (0 == result); - - return result; - } - }; - - inline expression_node_ptr parse_special_function() - { - const std::string sf_name = current_token().value; - - // Expect: $fDD(expr0,expr1,expr2) or $fDD(expr0,expr1,expr2,expr3) - if ( - !details::is_digit(sf_name[2]) || - !details::is_digit(sf_name[3]) - ) - { - set_error( - make_error(parser_error::e_token, - current_token(), - "ERR136 - Invalid special function[1]: " + sf_name, - exprtk_error_location)); - - return error_node(); - } - - const int id = (sf_name[2] - '0') * 10 + - (sf_name[3] - '0'); - - if (id >= details::e_sffinal) - { - set_error( - make_error(parser_error::e_token, - current_token(), - "ERR137 - Invalid special function[2]: " + sf_name, - exprtk_error_location)); - - return error_node(); - } - - const int sf_3_to_4 = details::e_sf48; - const details::operator_type opt_type = details::operator_type(id + 1000); - const std::size_t NumberOfParameters = (id < (sf_3_to_4 - 1000)) ? 3U : 4U; - - switch (NumberOfParameters) - { - case 3 : return parse_special_function_impl::process((*this), opt_type, sf_name); - case 4 : return parse_special_function_impl::process((*this), opt_type, sf_name); - default : return error_node(); - } - } - - inline expression_node_ptr parse_null_statement() - { - next_token(); - return node_allocator_.allocate >(); - } - - #ifndef exprtk_disable_break_continue - inline expression_node_ptr parse_break_statement() - { - if (state_.parsing_break_stmt) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR138 - Invoking 'break' within a break call is not allowed", - exprtk_error_location)); - - return error_node(); - } - else if (0 == state_.parsing_loop_stmt_count) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR139 - Invalid use of 'break', allowed only in the scope of a loop", - exprtk_error_location)); - - return error_node(); - } - - scoped_bool_negator sbn(state_.parsing_break_stmt); - - if (!brkcnt_list_.empty()) - { - next_token(); - - brkcnt_list_.front() = true; - - expression_node_ptr return_expr = error_node(); - - if (token_is(token_t::e_lsqrbracket)) - { - if (0 == (return_expr = parse_expression())) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR140 - Failed to parse return expression for 'break' statement", - exprtk_error_location)); - - return error_node(); - } - else if (!token_is(token_t::e_rsqrbracket)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR141 - Expected ']' at the completion of break's return expression", - exprtk_error_location)); - - free_node(node_allocator_,return_expr); - - return error_node(); - } - } - - state_.activate_side_effect("parse_break_statement()"); - - return node_allocator_.allocate >(return_expr); - } - else - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR142 - Invalid use of 'break', allowed only in the scope of a loop", - exprtk_error_location)); - } - - return error_node(); - } - - inline expression_node_ptr parse_continue_statement() - { - if (0 == state_.parsing_loop_stmt_count) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR143 - Invalid use of 'continue', allowed only in the scope of a loop", - exprtk_error_location)); - - return error_node(); - } - else - { - next_token(); - - brkcnt_list_.front() = true; - state_.activate_side_effect("parse_continue_statement()"); - - return node_allocator_.allocate >(); - } - } - #endif - - inline expression_node_ptr parse_define_vector_statement(const std::string& vec_name) - { - expression_node_ptr size_expr = error_node(); - - if (!token_is(token_t::e_lsqrbracket)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR144 - Expected '[' as part of vector size definition", - exprtk_error_location)); - - return error_node(); - } - else if (0 == (size_expr = parse_expression())) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR145 - Failed to determine size of vector '" + vec_name + "'", - exprtk_error_location)); - - return error_node(); - } - else if (!is_constant_node(size_expr)) - { - free_node(node_allocator_,size_expr); - - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR146 - Expected a literal number as size of vector '" + vec_name + "'", - exprtk_error_location)); - - return error_node(); - } - - const T vector_size = size_expr->value(); - - free_node(node_allocator_,size_expr); - - const T max_vector_size = T(2000000000.0); - - if ( - (vector_size <= T(0)) || - std::not_equal_to() - (T(0),vector_size - details::numeric::trunc(vector_size)) || - (vector_size > max_vector_size) - ) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR147 - Invalid vector size. Must be an integer in the range [0,2e9], size: " + - details::to_str(details::numeric::to_int32(vector_size)), - exprtk_error_location)); - - return error_node(); - } - - std::vector vec_initilizer_list; - - scoped_vec_delete svd((*this),vec_initilizer_list); - - bool single_value_initialiser = false; - bool vec_to_vec_initialiser = false; - bool null_initialisation = false; - - if (!token_is(token_t::e_rsqrbracket)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR148 - Expected ']' as part of vector size definition", - exprtk_error_location)); - - return error_node(); - } - else if (!token_is(token_t::e_eof)) - { - if (!token_is(token_t::e_assign)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR149 - Expected ':=' as part of vector definition", - exprtk_error_location)); - - return error_node(); - } - else if (token_is(token_t::e_lsqrbracket)) - { - expression_node_ptr initialiser = parse_expression(); - - if (0 == initialiser) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR150 - Failed to parse single vector initialiser", - exprtk_error_location)); - - return error_node(); - } - - vec_initilizer_list.push_back(initialiser); - - if (!token_is(token_t::e_rsqrbracket)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR151 - Expected ']' to close single value vector initialiser", - exprtk_error_location)); - - return error_node(); - } - - single_value_initialiser = true; - } - else if (!token_is(token_t::e_lcrlbracket)) - { - expression_node_ptr initialiser = error_node(); - - // Is this a vector to vector assignment and initialisation? - if (token_t::e_symbol == current_token().type) - { - // Is it a locally defined vector? - const scope_element& se = sem_.get_active_element(current_token().value); - - if (scope_element::e_vector == se.type) - { - if (0 != (initialiser = parse_expression())) - vec_initilizer_list.push_back(initialiser); - else - return error_node(); - } - // Are we dealing with a user defined vector? - else if (symtab_store_.is_vector(current_token().value)) - { - lodge_symbol(current_token().value, e_st_vector); - - if (0 != (initialiser = parse_expression())) - vec_initilizer_list.push_back(initialiser); - else - return error_node(); - } - // Are we dealing with a null initialisation vector definition? - else if (token_is(token_t::e_symbol,"null")) - null_initialisation = true; - } - - if (!null_initialisation) - { - if (0 == initialiser) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR152 - Expected '{' as part of vector initialiser list", - exprtk_error_location)); - - return error_node(); - } - else - vec_to_vec_initialiser = true; - } - } - else if (!token_is(token_t::e_rcrlbracket)) - { - for ( ; ; ) - { - expression_node_ptr initialiser = parse_expression(); - - if (0 == initialiser) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR153 - Expected '{' as part of vector initialiser list", - exprtk_error_location)); - - return error_node(); - } - else - vec_initilizer_list.push_back(initialiser); - - if (token_is(token_t::e_rcrlbracket)) - break; - - const bool is_next_close = peek_token_is(token_t::e_rcrlbracket); - - if (!token_is(token_t::e_comma) && is_next_close) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR154 - Expected ',' between vector initialisers", - exprtk_error_location)); - - return error_node(); - } - - if (token_is(token_t::e_rcrlbracket)) - break; - } - } - - if ( - !token_is(token_t::e_rbracket , prsrhlpr_t::e_hold) && - !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) && - !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold) - ) - { - if (!token_is(token_t::e_eof)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR155 - Expected ';' at end of vector definition", - exprtk_error_location)); - - return error_node(); - } - } - - if (vec_initilizer_list.size() > vector_size) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR156 - Initialiser list larger than the number of elements in the vector: '" + vec_name + "'", - exprtk_error_location)); - - return error_node(); - } - } - - typename symbol_table_t::vector_holder_ptr vec_holder = typename symbol_table_t::vector_holder_ptr(0); - - const std::size_t vec_size = static_cast(details::numeric::to_int32(vector_size)); - - scope_element& se = sem_.get_element(vec_name); - - if (se.name == vec_name) - { - if (se.active) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR157 - Illegal redefinition of local vector: '" + vec_name + "'", - exprtk_error_location)); - - return error_node(); - } - else if ( - (se.size == vec_size) && - (scope_element::e_vector == se.type) - ) - { - vec_holder = se.vec_node; - se.active = true; - se.depth = state_.scope_depth; - se.ref_count++; - } - } - - if (0 == vec_holder) - { - scope_element nse; - nse.name = vec_name; - nse.active = true; - nse.ref_count = 1; - nse.type = scope_element::e_vector; - nse.depth = state_.scope_depth; - nse.size = vec_size; - nse.data = new T[vec_size]; - nse.vec_node = new typename scope_element::vector_holder_t(reinterpret_cast(nse.data),nse.size); - - if (!sem_.add_element(nse)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR158 - Failed to add new local vector '" + vec_name + "' to SEM", - exprtk_error_location)); - - sem_.free_element(nse); - - return error_node(); - } - - vec_holder = nse.vec_node; - - exprtk_debug(("parse_define_vector_statement() - INFO - Added new local vector: %s[%d]\n", - nse.name.c_str(), - static_cast(nse.size))); - } - - state_.activate_side_effect("parse_define_vector_statement()"); - - lodge_symbol(vec_name, e_st_local_vector); - - expression_node_ptr result = error_node(); - - if (null_initialisation) - result = expression_generator_(T(0.0)); - else if (vec_to_vec_initialiser) - { - expression_node_ptr vec_node = node_allocator_.allocate(vec_holder); - - result = expression_generator_( - details::e_assign, - vec_node, - vec_initilizer_list[0]); - } - else - result = node_allocator_ - .allocate >( - (*vec_holder)[0], - vec_size, - vec_initilizer_list, - single_value_initialiser); - - svd.delete_ptr = (0 == result); - - return result; - } - - #ifndef exprtk_disable_string_capabilities - inline expression_node_ptr parse_define_string_statement(const std::string& str_name, expression_node_ptr initialisation_expression) - { - stringvar_node_t* str_node = reinterpret_cast(0); - - scope_element& se = sem_.get_element(str_name); - - if (se.name == str_name) - { - if (se.active) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR159 - Illegal redefinition of local variable: '" + str_name + "'", - exprtk_error_location)); - - free_node(node_allocator_,initialisation_expression); - - return error_node(); - } - else if (scope_element::e_string == se.type) - { - str_node = se.str_node; - se.active = true; - se.depth = state_.scope_depth; - se.ref_count++; - } - } - - if (0 == str_node) - { - scope_element nse; - nse.name = str_name; - nse.active = true; - nse.ref_count = 1; - nse.type = scope_element::e_string; - nse.depth = state_.scope_depth; - nse.data = new std::string; - nse.str_node = new stringvar_node_t(*reinterpret_cast(nse.data)); - - if (!sem_.add_element(nse)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR160 - Failed to add new local string variable '" + str_name + "' to SEM", - exprtk_error_location)); - - free_node(node_allocator_,initialisation_expression); - - sem_.free_element(nse); - - return error_node(); - } - - str_node = nse.str_node; - - exprtk_debug(("parse_define_string_statement() - INFO - Added new local string variable: %s\n",nse.name.c_str())); - } - - lodge_symbol(str_name, e_st_local_string); - - state_.activate_side_effect("parse_define_string_statement()"); - - expression_node_ptr branch[2] = {0}; - - branch[0] = str_node; - branch[1] = initialisation_expression; - - return expression_generator_(details::e_assign,branch); - } - #else - inline expression_node_ptr parse_define_string_statement(const std::string&, expression_node_ptr) - { - return error_node(); - } - #endif - - inline bool local_variable_is_shadowed(const std::string& symbol) - { - const scope_element& se = sem_.get_element(symbol); - return (se.name == symbol) && se.active; - } - - inline expression_node_ptr parse_define_var_statement() - { - if (settings_.vardef_disabled()) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR161 - Illegal variable definition", - exprtk_error_location)); - - return error_node(); - } - else if (!details::imatch(current_token().value,"var")) - { - return error_node(); - } - else - next_token(); - - const std::string var_name = current_token().value; - - expression_node_ptr initialisation_expression = error_node(); - - if (!token_is(token_t::e_symbol)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR162 - Expected a symbol for variable definition", - exprtk_error_location)); - - return error_node(); - } - else if (details::is_reserved_symbol(var_name)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR163 - Illegal redefinition of reserved keyword: '" + var_name + "'", - exprtk_error_location)); - - return error_node(); - } - else if (symtab_store_.symbol_exists(var_name)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR164 - Illegal redefinition of variable '" + var_name + "'", - exprtk_error_location)); - - return error_node(); - } - else if (local_variable_is_shadowed(var_name)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR165 - Illegal redefinition of local variable: '" + var_name + "'", - exprtk_error_location)); - - return error_node(); - } - else if (token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold)) - { - return parse_define_vector_statement(var_name); - } - else if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) - { - return parse_uninitialised_var_statement(var_name); - } - else if (token_is(token_t::e_assign)) - { - if (0 == (initialisation_expression = parse_expression())) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR166 - Failed to parse initialisation expression", - exprtk_error_location)); - - return error_node(); - } - } - - if ( - !token_is(token_t::e_rbracket , prsrhlpr_t::e_hold) && - !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) && - !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold) - ) - { - if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR167 - Expected ';' after variable definition", - exprtk_error_location)); - - free_node(node_allocator_,initialisation_expression); - - return error_node(); - } - } - - if ( - (0 != initialisation_expression) && - details::is_generally_string_node(initialisation_expression) - ) - { - return parse_define_string_statement(var_name,initialisation_expression); - } - - expression_node_ptr var_node = reinterpret_cast(0); - - scope_element& se = sem_.get_element(var_name); - - if (se.name == var_name) - { - if (se.active) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR168 - Illegal redefinition of local variable: '" + var_name + "'", - exprtk_error_location)); - - free_node(node_allocator_, initialisation_expression); - - return error_node(); - } - else if (scope_element::e_variable == se.type) - { - var_node = se.var_node; - se.active = true; - se.depth = state_.scope_depth; - se.ref_count++; - } - } - - if (0 == var_node) - { - scope_element nse; - nse.name = var_name; - nse.active = true; - nse.ref_count = 1; - nse.type = scope_element::e_variable; - nse.depth = state_.scope_depth; - nse.data = new T(T(0)); - nse.var_node = node_allocator_.allocate(*reinterpret_cast(nse.data)); - - if (!sem_.add_element(nse)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR169 - Failed to add new local variable '" + var_name + "' to SEM", - exprtk_error_location)); - - free_node(node_allocator_, initialisation_expression); - - sem_.free_element(nse); - - return error_node(); - } - - var_node = nse.var_node; - - exprtk_debug(("parse_define_var_statement() - INFO - Added new local variable: %s\n",nse.name.c_str())); - } - - state_.activate_side_effect("parse_define_var_statement()"); - - lodge_symbol(var_name, e_st_local_variable); - - expression_node_ptr branch[2] = {0}; - - branch[0] = var_node; - branch[1] = initialisation_expression ? initialisation_expression : expression_generator_(T(0)); - - return expression_generator_(details::e_assign,branch); - } - - inline expression_node_ptr parse_uninitialised_var_statement(const std::string& var_name) - { - if ( - !token_is(token_t::e_lcrlbracket) || - !token_is(token_t::e_rcrlbracket) - ) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR170 - Expected a '{}' for uninitialised var definition", - exprtk_error_location)); - - return error_node(); - } - else if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR171 - Expected ';' after uninitialised variable definition", - exprtk_error_location)); - - return error_node(); - } - - expression_node_ptr var_node = reinterpret_cast(0); - - scope_element& se = sem_.get_element(var_name); - - if (se.name == var_name) - { - if (se.active) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR172 - Illegal redefinition of local variable: '" + var_name + "'", - exprtk_error_location)); - - return error_node(); - } - else if (scope_element::e_variable == se.type) - { - var_node = se.var_node; - se.active = true; - se.ref_count++; - } - } - - if (0 == var_node) - { - scope_element nse; - nse.name = var_name; - nse.active = true; - nse.ref_count = 1; - nse.type = scope_element::e_variable; - nse.depth = state_.scope_depth; - nse.ip_index = sem_.next_ip_index(); - nse.data = new T(T(0)); - nse.var_node = node_allocator_.allocate(*reinterpret_cast(nse.data)); - - if (!sem_.add_element(nse)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR173 - Failed to add new local variable '" + var_name + "' to SEM", - exprtk_error_location)); - - sem_.free_element(nse); - - return error_node(); - } - - exprtk_debug(("parse_uninitialised_var_statement() - INFO - Added new local variable: %s\n", - nse.name.c_str())); - } - - lodge_symbol(var_name, e_st_local_variable); - - state_.activate_side_effect("parse_uninitialised_var_statement()"); - - return expression_generator_(T(0)); - } - - inline expression_node_ptr parse_swap_statement() - { - if (!details::imatch(current_token().value,"swap")) - { - return error_node(); - } - else - next_token(); - - if (!token_is(token_t::e_lbracket)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR174 - Expected '(' at start of swap statement", - exprtk_error_location)); - - return error_node(); - } - - expression_node_ptr variable0 = error_node(); - expression_node_ptr variable1 = error_node(); - - bool variable0_generated = false; - bool variable1_generated = false; - - const std::string var0_name = current_token().value; - - if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR175 - Expected a symbol for variable or vector element definition", - exprtk_error_location)); - - return error_node(); - } - else if (peek_token_is(token_t::e_lsqrbracket)) - { - if (0 == (variable0 = parse_vector())) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR176 - First parameter to swap is an invalid vector element: '" + var0_name + "'", - exprtk_error_location)); - - return error_node(); - } - - variable0_generated = true; - } - else - { - if (symtab_store_.is_variable(var0_name)) - { - variable0 = symtab_store_.get_variable(var0_name); - } - - const scope_element& se = sem_.get_element(var0_name); - - if ( - (se.active) && - (se.name == var0_name) && - (scope_element::e_variable == se.type) - ) - { - variable0 = se.var_node; - } - - lodge_symbol(var0_name, e_st_variable); - - if (0 == variable0) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR177 - First parameter to swap is an invalid variable: '" + var0_name + "'", - exprtk_error_location)); - - return error_node(); - } - else - next_token(); - } - - if (!token_is(token_t::e_comma)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR178 - Expected ',' between parameters to swap", - exprtk_error_location)); - - if (variable0_generated) - { - free_node(node_allocator_,variable0); - } - - return error_node(); - } - - const std::string var1_name = current_token().value; - - if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR179 - Expected a symbol for variable or vector element definition", - exprtk_error_location)); - - if (variable0_generated) - { - free_node(node_allocator_,variable0); - } - - return error_node(); - } - else if (peek_token_is(token_t::e_lsqrbracket)) - { - if (0 == (variable1 = parse_vector())) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR180 - Second parameter to swap is an invalid vector element: '" + var1_name + "'", - exprtk_error_location)); - - if (variable0_generated) - { - free_node(node_allocator_,variable0); - } - - return error_node(); - } - - variable1_generated = true; - } - else - { - if (symtab_store_.is_variable(var1_name)) - { - variable1 = symtab_store_.get_variable(var1_name); - } - - const scope_element& se = sem_.get_element(var1_name); - - if ( - (se.active) && - (se.name == var1_name) && - (scope_element::e_variable == se.type) - ) - { - variable1 = se.var_node; - } - - lodge_symbol(var1_name, e_st_variable); - - if (0 == variable1) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR181 - Second parameter to swap is an invalid variable: '" + var1_name + "'", - exprtk_error_location)); - - if (variable0_generated) - { - free_node(node_allocator_,variable0); - } - - return error_node(); - } - else - next_token(); - } - - if (!token_is(token_t::e_rbracket)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR182 - Expected ')' at end of swap statement", - exprtk_error_location)); - - if (variable0_generated) - { - free_node(node_allocator_,variable0); - } - - if (variable1_generated) - { - free_node(node_allocator_,variable1); - } - - return error_node(); - } - - typedef details::variable_node* variable_node_ptr; - - variable_node_ptr v0 = variable_node_ptr(0); - variable_node_ptr v1 = variable_node_ptr(0); - - expression_node_ptr result = error_node(); - - if ( - (0 != (v0 = dynamic_cast(variable0))) && - (0 != (v1 = dynamic_cast(variable1))) - ) - { - result = node_allocator_.allocate >(v0, v1); - - if (variable0_generated) - { - free_node(node_allocator_,variable0); - } - - if (variable1_generated) - { - free_node(node_allocator_,variable1); - } - } - else - result = node_allocator_.allocate > - (variable0, variable1); - - state_.activate_side_effect("parse_swap_statement()"); - - return result; - } - - #ifndef exprtk_disable_return_statement - inline expression_node_ptr parse_return_statement() - { - if (state_.parsing_return_stmt) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR183 - Return call within a return call is not allowed", - exprtk_error_location)); - - return error_node(); - } - - scoped_bool_negator sbn(state_.parsing_return_stmt); - - std::vector arg_list; - - scoped_vec_delete sdd((*this),arg_list); - - if (!details::imatch(current_token().value,"return")) - { - return error_node(); - } - else - next_token(); - - if (!token_is(token_t::e_lsqrbracket)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR184 - Expected '[' at start of return statement", - exprtk_error_location)); - - return error_node(); - } - else if (!token_is(token_t::e_rsqrbracket)) - { - for ( ; ; ) - { - expression_node_ptr arg = parse_expression(); - - if (0 == arg) - return error_node(); - - arg_list.push_back(arg); - - if (token_is(token_t::e_rsqrbracket)) - break; - else if (!token_is(token_t::e_comma)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR185 - Expected ',' between values during call to return", - exprtk_error_location)); - - return error_node(); - } - } - } - else if (settings_.zero_return_disabled()) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR186 - Zero parameter return statement not allowed", - exprtk_error_location)); - - return error_node(); - } - - const lexer::token prev_token = current_token(); - - if (token_is(token_t::e_rsqrbracket)) - { - if (!arg_list.empty()) - { - set_error( - make_error(parser_error::e_syntax, - prev_token, - "ERR187 - Invalid ']' found during return call", - exprtk_error_location)); - - return error_node(); - } - } - - std::string ret_param_type_list; - - for (std::size_t i = 0; i < arg_list.size(); ++i) - { - if (0 == arg_list[i]) - return error_node(); - else if (is_ivector_node(arg_list[i])) - ret_param_type_list += 'V'; - else if (is_generally_string_node(arg_list[i])) - ret_param_type_list += 'S'; - else - ret_param_type_list += 'T'; - } - - dec_.retparam_list_.push_back(ret_param_type_list); - - expression_node_ptr result = expression_generator_.return_call(arg_list); - - sdd.delete_ptr = (0 == result); - - state_.return_stmt_present = true; - - state_.activate_side_effect("parse_return_statement()"); - - return result; - } - #else - inline expression_node_ptr parse_return_statement() - { - return error_node(); - } - #endif - - inline bool post_variable_process(const std::string& symbol) - { - if ( - peek_token_is(token_t::e_lbracket ) || - peek_token_is(token_t::e_lcrlbracket) || - peek_token_is(token_t::e_lsqrbracket) - ) - { - if (!settings_.commutative_check_enabled()) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR188 - Invalid sequence of variable '"+ symbol + "' and bracket", - exprtk_error_location)); - - return false; - } - - lexer().insert_front(token_t::e_mul); - } - - return true; - } - - inline bool post_bracket_process(const typename token_t::token_type& token, expression_node_ptr& branch) - { - bool implied_mul = false; - - if (is_generally_string_node(branch)) - return true; - - const lexer::parser_helper::token_advance_mode hold = prsrhlpr_t::e_hold; - - switch (token) - { - case token_t::e_lcrlbracket : implied_mul = token_is(token_t::e_lbracket ,hold) || - token_is(token_t::e_lcrlbracket,hold) || - token_is(token_t::e_lsqrbracket,hold) ; - break; - - case token_t::e_lbracket : implied_mul = token_is(token_t::e_lbracket ,hold) || - token_is(token_t::e_lcrlbracket,hold) || - token_is(token_t::e_lsqrbracket,hold) ; - break; - - case token_t::e_lsqrbracket : implied_mul = token_is(token_t::e_lbracket ,hold) || - token_is(token_t::e_lcrlbracket,hold) || - token_is(token_t::e_lsqrbracket,hold) ; - break; - - default : return true; - } - - if (implied_mul) - { - if (!settings_.commutative_check_enabled()) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR189 - Invalid sequence of brackets", - exprtk_error_location)); - - return false; - } - else if (token_t::e_eof != current_token().type) - { - lexer().insert_front(current_token().type); - lexer().insert_front(token_t::e_mul); - next_token(); - } - } - - return true; - } - - inline expression_node_ptr parse_symtab_symbol() - { - const std::string symbol = current_token().value; - - // Are we dealing with a variable or a special constant? - expression_node_ptr variable = symtab_store_.get_variable(symbol); - - if (variable) - { - if (symtab_store_.is_constant_node(symbol)) - { - variable = expression_generator_(variable->value()); - } - - if (!post_variable_process(symbol)) - return error_node(); - - lodge_symbol(symbol, e_st_variable); - next_token(); - - return variable; - } - - // Are we dealing with a locally defined variable, vector or string? - if (!sem_.empty()) - { - scope_element& se = sem_.get_active_element(symbol); - - if (se.active && details::imatch(se.name, symbol)) - { - if (scope_element::e_variable == se.type) - { - se.active = true; - lodge_symbol(symbol, e_st_local_variable); - - if (!post_variable_process(symbol)) - return error_node(); - - next_token(); - - return se.var_node; - } - else if (scope_element::e_vector == se.type) - { - return parse_vector(); - } - #ifndef exprtk_disable_string_capabilities - else if (scope_element::e_string == se.type) - { - return parse_string(); - } - #endif - } - } - - #ifndef exprtk_disable_string_capabilities - // Are we dealing with a string variable? - if (symtab_store_.is_stringvar(symbol)) - { - return parse_string(); - } - #endif - - { - // Are we dealing with a function? - ifunction* function = symtab_store_.get_function(symbol); - - if (function) - { - lodge_symbol(symbol, e_st_function); - - expression_node_ptr func_node = - parse_function_invocation(function,symbol); - - if (func_node) - return func_node; - else - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR190 - Failed to generate node for function: '" + symbol + "'", - exprtk_error_location)); - - return error_node(); - } - } - } - - { - // Are we dealing with a vararg function? - ivararg_function* vararg_function = symtab_store_.get_vararg_function(symbol); - - if (vararg_function) - { - lodge_symbol(symbol, e_st_function); - - expression_node_ptr vararg_func_node = - parse_vararg_function_call(vararg_function, symbol); - - if (vararg_func_node) - return vararg_func_node; - else - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR191 - Failed to generate node for vararg function: '" + symbol + "'", - exprtk_error_location)); - - return error_node(); - } - } - } - - { - // Are we dealing with a vararg generic function? - igeneric_function* generic_function = symtab_store_.get_generic_function(symbol); - - if (generic_function) - { - lodge_symbol(symbol, e_st_function); - - expression_node_ptr genericfunc_node = - parse_generic_function_call(generic_function, symbol); - - if (genericfunc_node) - return genericfunc_node; - else - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR192 - Failed to generate node for generic function: '" + symbol + "'", - exprtk_error_location)); - - return error_node(); - } - } - } - - #ifndef exprtk_disable_string_capabilities - { - // Are we dealing with a vararg string returning function? - igeneric_function* string_function = symtab_store_.get_string_function(symbol); - - if (string_function) - { - lodge_symbol(symbol, e_st_function); - - expression_node_ptr stringfunc_node = - parse_string_function_call(string_function, symbol); - - if (stringfunc_node) - return stringfunc_node; - else - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR193 - Failed to generate node for string function: '" + symbol + "'", - exprtk_error_location)); - - return error_node(); - } - } - } - - { - // Are we dealing with a vararg overloaded scalar/string returning function? - igeneric_function* overload_function = symtab_store_.get_overload_function(symbol); - - if (overload_function) - { - lodge_symbol(symbol, e_st_function); - - expression_node_ptr overloadfunc_node = - parse_overload_function_call(overload_function, symbol); - - if (overloadfunc_node) - return overloadfunc_node; - else - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR194 - Failed to generate node for overload function: '" + symbol + "'", - exprtk_error_location)); - - return error_node(); - } - } - } - #endif - - // Are we dealing with a vector? - if (symtab_store_.is_vector(symbol)) - { - lodge_symbol(symbol, e_st_vector); - return parse_vector(); - } - - if (details::is_reserved_symbol(symbol)) - { - if ( - settings_.function_enabled(symbol) || - !details::is_base_function(symbol) - ) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR195 - Invalid use of reserved symbol '" + symbol + "'", - exprtk_error_location)); - - return error_node(); - } - } - - // Should we handle unknown symbols? - if (resolve_unknown_symbol_ && unknown_symbol_resolver_) - { - if (!(settings_.rsrvd_sym_usr_disabled() && details::is_reserved_symbol(symbol))) - { - symbol_table_t& symtab = symtab_store_.get_symbol_table(); - - std::string error_message; - - if (unknown_symbol_resolver::e_usrmode_default == unknown_symbol_resolver_->mode) - { - T default_value = T(0); - - typename unknown_symbol_resolver::usr_symbol_type usr_symbol_type = unknown_symbol_resolver::e_usr_unknown_type; - - if (unknown_symbol_resolver_->process(symbol, usr_symbol_type, default_value, error_message)) - { - bool create_result = false; - - switch (usr_symbol_type) - { - case unknown_symbol_resolver::e_usr_variable_type : create_result = symtab.create_variable(symbol, default_value); - break; - - case unknown_symbol_resolver::e_usr_constant_type : create_result = symtab.add_constant(symbol, default_value); - break; - - default : create_result = false; - } - - if (create_result) - { - expression_node_ptr var = symtab_store_.get_variable(symbol); - - if (var) - { - if (symtab_store_.is_constant_node(symbol)) - { - var = expression_generator_(var->value()); - } - - lodge_symbol(symbol, e_st_variable); - - if (!post_variable_process(symbol)) - return error_node(); - - next_token(); - - return var; - } - } - } - - set_error( - make_error(parser_error::e_symtab, - current_token(), - "ERR196 - Failed to create variable: '" + symbol + "'" + - (error_message.empty() ? "" : " - " + error_message), - exprtk_error_location)); - - } - else if (unknown_symbol_resolver::e_usrmode_extended == unknown_symbol_resolver_->mode) - { - if (unknown_symbol_resolver_->process(symbol, symtab, error_message)) - { - expression_node_ptr result = parse_symtab_symbol(); - - if (result) - { - return result; - } - } - - set_error( - make_error(parser_error::e_symtab, - current_token(), - "ERR197 - Failed to resolve symbol: '" + symbol + "'" + - (error_message.empty() ? "" : " - " + error_message), - exprtk_error_location)); - } - - return error_node(); - } - } - - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR198 - Undefined symbol: '" + symbol + "'", - exprtk_error_location)); - - return error_node(); - } - - inline expression_node_ptr parse_symbol() - { - static const std::string symbol_if = "if" ; - static const std::string symbol_while = "while" ; - static const std::string symbol_repeat = "repeat" ; - static const std::string symbol_for = "for" ; - static const std::string symbol_switch = "switch" ; - static const std::string symbol_null = "null" ; - static const std::string symbol_break = "break" ; - static const std::string symbol_continue = "continue"; - static const std::string symbol_var = "var" ; - static const std::string symbol_swap = "swap" ; - static const std::string symbol_return = "return" ; - static const std::string symbol_not = "not" ; - - if (valid_vararg_operation(current_token().value)) - { - return parse_vararg_function(); - } - else if (details::imatch(current_token().value, symbol_not)) - { - return parse_not_statement(); - } - else if (valid_base_operation(current_token().value)) - { - return parse_base_operation(); - } - else if ( - details::imatch(current_token().value, symbol_if) && - settings_.control_struct_enabled(current_token().value) - ) - { - return parse_conditional_statement(); - } - else if ( - details::imatch(current_token().value, symbol_while) && - settings_.control_struct_enabled(current_token().value) - ) - { - return parse_while_loop(); - } - else if ( - details::imatch(current_token().value, symbol_repeat) && - settings_.control_struct_enabled(current_token().value) - ) - { - return parse_repeat_until_loop(); - } - else if ( - details::imatch(current_token().value, symbol_for) && - settings_.control_struct_enabled(current_token().value) - ) - { - return parse_for_loop(); - } - else if ( - details::imatch(current_token().value, symbol_switch) && - settings_.control_struct_enabled(current_token().value) - ) - { - return parse_switch_statement(); - } - else if (details::is_valid_sf_symbol(current_token().value)) - { - return parse_special_function(); - } - else if (details::imatch(current_token().value, symbol_null)) - { - return parse_null_statement(); - } - #ifndef exprtk_disable_break_continue - else if (details::imatch(current_token().value, symbol_break)) - { - return parse_break_statement(); - } - else if (details::imatch(current_token().value, symbol_continue)) - { - return parse_continue_statement(); - } - #endif - else if (details::imatch(current_token().value, symbol_var)) - { - return parse_define_var_statement(); - } - else if (details::imatch(current_token().value, symbol_swap)) - { - return parse_swap_statement(); - } - #ifndef exprtk_disable_return_statement - else if ( - details::imatch(current_token().value, symbol_return) && - settings_.control_struct_enabled(current_token().value) - ) - { - return parse_return_statement(); - } - #endif - else if (symtab_store_.valid() || !sem_.empty()) - { - return parse_symtab_symbol(); - } - else - { - set_error( - make_error(parser_error::e_symtab, - current_token(), - "ERR199 - Variable or function detected, yet symbol-table is invalid, Symbol: " + current_token().value, - exprtk_error_location)); - - return error_node(); - } - } - - inline expression_node_ptr parse_branch(precedence_level precedence = e_level00) - { - stack_limit_handler slh(*this); - - if (!slh) - { - return error_node(); - } - - expression_node_ptr branch = error_node(); - - if (token_t::e_number == current_token().type) - { - T numeric_value = T(0); - - if (details::string_to_real(current_token().value, numeric_value)) - { - expression_node_ptr literal_exp = expression_generator_(numeric_value); - - if (0 == literal_exp) - { - set_error( - make_error(parser_error::e_numeric, - current_token(), - "ERR200 - Failed generate node for scalar: '" + current_token().value + "'", - exprtk_error_location)); - - return error_node(); - } - - next_token(); - branch = literal_exp; - } - else - { - set_error( - make_error(parser_error::e_numeric, - current_token(), - "ERR201 - Failed to convert '" + current_token().value + "' to a number", - exprtk_error_location)); - - return error_node(); - } - } - else if (token_t::e_symbol == current_token().type) - { - branch = parse_symbol(); - } - #ifndef exprtk_disable_string_capabilities - else if (token_t::e_string == current_token().type) - { - branch = parse_const_string(); - } - #endif - else if (token_t::e_lbracket == current_token().type) - { - next_token(); - - if (0 == (branch = parse_expression())) - return error_node(); - else if (!token_is(token_t::e_rbracket)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR202 - Expected ')' instead of: '" + current_token().value + "'", - exprtk_error_location)); - - free_node(node_allocator_,branch); - - return error_node(); - } - else if (!post_bracket_process(token_t::e_lbracket,branch)) - { - free_node(node_allocator_,branch); - - return error_node(); - } - } - else if (token_t::e_lsqrbracket == current_token().type) - { - next_token(); - - if (0 == (branch = parse_expression())) - return error_node(); - else if (!token_is(token_t::e_rsqrbracket)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR203 - Expected ']' instead of: '" + current_token().value + "'", - exprtk_error_location)); - - free_node(node_allocator_,branch); - - return error_node(); - } - else if (!post_bracket_process(token_t::e_lsqrbracket,branch)) - { - free_node(node_allocator_,branch); - - return error_node(); - } - } - else if (token_t::e_lcrlbracket == current_token().type) - { - next_token(); - - if (0 == (branch = parse_expression())) - return error_node(); - else if (!token_is(token_t::e_rcrlbracket)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR204 - Expected '}' instead of: '" + current_token().value + "'", - exprtk_error_location)); - - free_node(node_allocator_,branch); - - return error_node(); - } - else if (!post_bracket_process(token_t::e_lcrlbracket,branch)) - { - free_node(node_allocator_,branch); - - return error_node(); - } - } - else if (token_t::e_sub == current_token().type) - { - next_token(); - branch = parse_expression(e_level11); - - if ( - branch && - !( - details::is_neg_unary_node (branch) && - simplify_unary_negation_branch(branch) - ) - ) - { - expression_node_ptr result = expression_generator_(details::e_neg,branch); - - if (0 == result) - { - free_node(node_allocator_,branch); - - return error_node(); - } - else - branch = result; - } - } - else if (token_t::e_add == current_token().type) - { - next_token(); - branch = parse_expression(e_level13); - } - else if (token_t::e_eof == current_token().type) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR205 - Premature end of expression[1]", - exprtk_error_location)); - - return error_node(); - } - else - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR206 - Premature end of expression[2]", - exprtk_error_location)); - - return error_node(); - } - - if ( - branch && - (e_level00 == precedence) && - token_is(token_t::e_ternary,prsrhlpr_t::e_hold) - ) - { - branch = parse_ternary_conditional_statement(branch); - } - - parse_pending_string_rangesize(branch); - - return branch; - } - - template - class expression_generator - { - public: - - typedef details::expression_node* expression_node_ptr; - typedef expression_node_ptr (*synthesize_functor_t)(expression_generator&, const details::operator_type& operation, expression_node_ptr (&branch)[2]); - typedef std::map synthesize_map_t; - typedef typename exprtk::parser parser_t; - typedef const Type& vtype; - typedef const Type ctype; - - inline void init_synthesize_map() - { - #ifndef exprtk_disable_enhanced_features - synthesize_map_["(v)o(v)"] = synthesize_vov_expression::process; - synthesize_map_["(c)o(v)"] = synthesize_cov_expression::process; - synthesize_map_["(v)o(c)"] = synthesize_voc_expression::process; - - #define register_synthezier(S) \ - synthesize_map_[S ::node_type::id()] = S ::process; \ - - register_synthezier(synthesize_vovov_expression0) - register_synthezier(synthesize_vovov_expression1) - register_synthezier(synthesize_vovoc_expression0) - register_synthezier(synthesize_vovoc_expression1) - register_synthezier(synthesize_vocov_expression0) - register_synthezier(synthesize_vocov_expression1) - register_synthezier(synthesize_covov_expression0) - register_synthezier(synthesize_covov_expression1) - register_synthezier(synthesize_covoc_expression0) - register_synthezier(synthesize_covoc_expression1) - register_synthezier(synthesize_cocov_expression1) - register_synthezier(synthesize_vococ_expression0) - - register_synthezier(synthesize_vovovov_expression0) - register_synthezier(synthesize_vovovoc_expression0) - register_synthezier(synthesize_vovocov_expression0) - register_synthezier(synthesize_vocovov_expression0) - register_synthezier(synthesize_covovov_expression0) - register_synthezier(synthesize_covocov_expression0) - register_synthezier(synthesize_vocovoc_expression0) - register_synthezier(synthesize_covovoc_expression0) - register_synthezier(synthesize_vococov_expression0) - - register_synthezier(synthesize_vovovov_expression1) - register_synthezier(synthesize_vovovoc_expression1) - register_synthezier(synthesize_vovocov_expression1) - register_synthezier(synthesize_vocovov_expression1) - register_synthezier(synthesize_covovov_expression1) - register_synthezier(synthesize_covocov_expression1) - register_synthezier(synthesize_vocovoc_expression1) - register_synthezier(synthesize_covovoc_expression1) - register_synthezier(synthesize_vococov_expression1) - - register_synthezier(synthesize_vovovov_expression2) - register_synthezier(synthesize_vovovoc_expression2) - register_synthezier(synthesize_vovocov_expression2) - register_synthezier(synthesize_vocovov_expression2) - register_synthezier(synthesize_covovov_expression2) - register_synthezier(synthesize_covocov_expression2) - register_synthezier(synthesize_vocovoc_expression2) - register_synthezier(synthesize_covovoc_expression2) - - register_synthezier(synthesize_vovovov_expression3) - register_synthezier(synthesize_vovovoc_expression3) - register_synthezier(synthesize_vovocov_expression3) - register_synthezier(synthesize_vocovov_expression3) - register_synthezier(synthesize_covovov_expression3) - register_synthezier(synthesize_covocov_expression3) - register_synthezier(synthesize_vocovoc_expression3) - register_synthezier(synthesize_covovoc_expression3) - register_synthezier(synthesize_vococov_expression3) - - register_synthezier(synthesize_vovovov_expression4) - register_synthezier(synthesize_vovovoc_expression4) - register_synthezier(synthesize_vovocov_expression4) - register_synthezier(synthesize_vocovov_expression4) - register_synthezier(synthesize_covovov_expression4) - register_synthezier(synthesize_covocov_expression4) - register_synthezier(synthesize_vocovoc_expression4) - register_synthezier(synthesize_covovoc_expression4) - #endif - } - - inline void set_parser(parser_t& p) - { - parser_ = &p; - } - - inline void set_uom(unary_op_map_t& unary_op_map) - { - unary_op_map_ = &unary_op_map; - } - - inline void set_bom(binary_op_map_t& binary_op_map) - { - binary_op_map_ = &binary_op_map; - } - - inline void set_ibom(inv_binary_op_map_t& inv_binary_op_map) - { - inv_binary_op_map_ = &inv_binary_op_map; - } - - inline void set_sf3m(sf3_map_t& sf3_map) - { - sf3_map_ = &sf3_map; - } - - inline void set_sf4m(sf4_map_t& sf4_map) - { - sf4_map_ = &sf4_map; - } - - inline void set_allocator(details::node_allocator& na) - { - node_allocator_ = &na; - } - - inline void set_strength_reduction_state(const bool enabled) - { - strength_reduction_enabled_ = enabled; - } - - inline bool strength_reduction_enabled() const - { - return strength_reduction_enabled_; - } - - inline bool valid_operator(const details::operator_type& operation, binary_functor_t& bop) - { - typename binary_op_map_t::iterator bop_itr = binary_op_map_->find(operation); - - if ((*binary_op_map_).end() == bop_itr) - return false; - - bop = bop_itr->second; - - return true; - } - - inline bool valid_operator(const details::operator_type& operation, unary_functor_t& uop) - { - typename unary_op_map_t::iterator uop_itr = unary_op_map_->find(operation); - - if ((*unary_op_map_).end() == uop_itr) - return false; - - uop = uop_itr->second; - - return true; - } - - inline details::operator_type get_operator(const binary_functor_t& bop) const - { - return (*inv_binary_op_map_).find(bop)->second; - } - - inline expression_node_ptr operator() (const Type& v) const - { - return node_allocator_->allocate(v); - } - - #ifndef exprtk_disable_string_capabilities - inline expression_node_ptr operator() (const std::string& s) const - { - return node_allocator_->allocate(s); - } - - inline expression_node_ptr operator() (std::string& s, range_t& rp) const - { - return node_allocator_->allocate_rr(s,rp); - } - - inline expression_node_ptr operator() (const std::string& s, range_t& rp) const - { - return node_allocator_->allocate_tt(s,rp); - } - - inline expression_node_ptr operator() (expression_node_ptr branch, range_t& rp) const - { - if (is_generally_string_node(branch)) - return node_allocator_->allocate_tt(branch,rp); - else - return error_node(); - } - #endif - - inline bool unary_optimisable(const details::operator_type& operation) const - { - return (details::e_abs == operation) || (details::e_acos == operation) || - (details::e_acosh == operation) || (details::e_asin == operation) || - (details::e_asinh == operation) || (details::e_atan == operation) || - (details::e_atanh == operation) || (details::e_ceil == operation) || - (details::e_cos == operation) || (details::e_cosh == operation) || - (details::e_exp == operation) || (details::e_expm1 == operation) || - (details::e_floor == operation) || (details::e_log == operation) || - (details::e_log10 == operation) || (details::e_log2 == operation) || - (details::e_log1p == operation) || (details::e_neg == operation) || - (details::e_pos == operation) || (details::e_round == operation) || - (details::e_sin == operation) || (details::e_sinc == operation) || - (details::e_sinh == operation) || (details::e_sqrt == operation) || - (details::e_tan == operation) || (details::e_tanh == operation) || - (details::e_cot == operation) || (details::e_sec == operation) || - (details::e_csc == operation) || (details::e_r2d == operation) || - (details::e_d2r == operation) || (details::e_d2g == operation) || - (details::e_g2d == operation) || (details::e_notl == operation) || - (details::e_sgn == operation) || (details::e_erf == operation) || - (details::e_erfc == operation) || (details::e_ncdf == operation) || - (details::e_frac == operation) || (details::e_trunc == operation) ; - } - - inline bool sf3_optimisable(const std::string& sf3id, trinary_functor_t& tfunc) const - { - typename sf3_map_t::const_iterator itr = sf3_map_->find(sf3id); - - if (sf3_map_->end() == itr) - return false; - else - tfunc = itr->second.first; - - return true; - } - - inline bool sf4_optimisable(const std::string& sf4id, quaternary_functor_t& qfunc) const - { - typename sf4_map_t::const_iterator itr = sf4_map_->find(sf4id); - - if (sf4_map_->end() == itr) - return false; - else - qfunc = itr->second.first; - - return true; - } - - inline bool sf3_optimisable(const std::string& sf3id, details::operator_type& operation) const - { - typename sf3_map_t::const_iterator itr = sf3_map_->find(sf3id); - - if (sf3_map_->end() == itr) - return false; - else - operation = itr->second.second; - - return true; - } - - inline bool sf4_optimisable(const std::string& sf4id, details::operator_type& operation) const - { - typename sf4_map_t::const_iterator itr = sf4_map_->find(sf4id); - - if (sf4_map_->end() == itr) - return false; - else - operation = itr->second.second; - - return true; - } - - inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[1]) - { - if (0 == branch[0]) - { - return error_node(); - } - else if (details::is_null_node(branch[0])) - { - return branch[0]; - } - else if (details::is_break_node(branch[0])) - { - return error_node(); - } - else if (details::is_continue_node(branch[0])) - { - return error_node(); - } - else if (details::is_constant_node(branch[0])) - { - return synthesize_expression(operation,branch); - } - else if (unary_optimisable(operation) && details::is_variable_node(branch[0])) - { - return synthesize_uv_expression(operation,branch); - } - else if (unary_optimisable(operation) && details::is_ivector_node(branch[0])) - { - return synthesize_uvec_expression(operation,branch); - } - else - return synthesize_unary_expression(operation,branch); - } - - inline bool is_assignment_operation(const details::operator_type& operation) const - { - return ( - (details::e_addass == operation) || - (details::e_subass == operation) || - (details::e_mulass == operation) || - (details::e_divass == operation) || - (details::e_modass == operation) - ) && - parser_->settings_.assignment_enabled(operation); - } - - #ifndef exprtk_disable_string_capabilities - inline bool valid_string_operation(const details::operator_type& operation) const - { - return (details::e_add == operation) || - (details::e_lt == operation) || - (details::e_lte == operation) || - (details::e_gt == operation) || - (details::e_gte == operation) || - (details::e_eq == operation) || - (details::e_ne == operation) || - (details::e_in == operation) || - (details::e_like == operation) || - (details::e_ilike == operation) || - (details::e_assign == operation) || - (details::e_addass == operation) || - (details::e_swap == operation) ; - } - #else - inline bool valid_string_operation(const details::operator_type&) const - { - return false; - } - #endif - - inline std::string to_str(const details::operator_type& operation) const - { - switch (operation) - { - case details::e_add : return "+" ; - case details::e_sub : return "-" ; - case details::e_mul : return "*" ; - case details::e_div : return "/" ; - case details::e_mod : return "%" ; - case details::e_pow : return "^" ; - case details::e_lt : return "<" ; - case details::e_lte : return "<=" ; - case details::e_gt : return ">" ; - case details::e_gte : return ">=" ; - case details::e_eq : return "==" ; - case details::e_ne : return "!=" ; - case details::e_and : return "and" ; - case details::e_nand : return "nand" ; - case details::e_or : return "or" ; - case details::e_nor : return "nor" ; - case details::e_xor : return "xor" ; - case details::e_xnor : return "xnor" ; - default : return "UNKNOWN"; - } - } - - inline bool operation_optimisable(const details::operator_type& operation) const - { - return (details::e_add == operation) || - (details::e_sub == operation) || - (details::e_mul == operation) || - (details::e_div == operation) || - (details::e_mod == operation) || - (details::e_pow == operation) || - (details::e_lt == operation) || - (details::e_lte == operation) || - (details::e_gt == operation) || - (details::e_gte == operation) || - (details::e_eq == operation) || - (details::e_ne == operation) || - (details::e_and == operation) || - (details::e_nand == operation) || - (details::e_or == operation) || - (details::e_nor == operation) || - (details::e_xor == operation) || - (details::e_xnor == operation) ; - } - - inline std::string branch_to_id(expression_node_ptr branch) const - { - static const std::string null_str ("(null)" ); - static const std::string const_str ("(c)" ); - static const std::string var_str ("(v)" ); - static const std::string vov_str ("(vov)" ); - static const std::string cov_str ("(cov)" ); - static const std::string voc_str ("(voc)" ); - static const std::string str_str ("(s)" ); - static const std::string strrng_str ("(rngs)" ); - static const std::string cs_str ("(cs)" ); - static const std::string cstrrng_str("(crngs)"); - - if (details::is_null_node(branch)) - return null_str; - else if (details::is_constant_node(branch)) - return const_str; - else if (details::is_variable_node(branch)) - return var_str; - else if (details::is_vov_node(branch)) - return vov_str; - else if (details::is_cov_node(branch)) - return cov_str; - else if (details::is_voc_node(branch)) - return voc_str; - else if (details::is_string_node(branch)) - return str_str; - else if (details::is_const_string_node(branch)) - return cs_str; - else if (details::is_string_range_node(branch)) - return strrng_str; - else if (details::is_const_string_range_node(branch)) - return cstrrng_str; - else if (details::is_t0ot1ot2_node(branch)) - return "(" + dynamic_cast*>(branch)->type_id() + ")"; - else if (details::is_t0ot1ot2ot3_node(branch)) - return "(" + dynamic_cast*>(branch)->type_id() + ")"; - else - return "ERROR"; - } - - inline std::string branch_to_id(expression_node_ptr (&branch)[2]) const - { - return branch_to_id(branch[0]) + std::string("o") + branch_to_id(branch[1]); - } - - inline bool cov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const - { - if (!operation_optimisable(operation)) - return false; - else - return details::is_constant_node(branch[0]) && - details::is_variable_node(branch[1]) ; - } - - inline bool voc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const - { - if (!operation_optimisable(operation)) - return false; - else - return details::is_variable_node(branch[0]) && - details::is_constant_node(branch[1]) ; - } - - inline bool vov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const - { - if (!operation_optimisable(operation)) - return false; - else - return details::is_variable_node(branch[0]) && - details::is_variable_node(branch[1]) ; - } - - inline bool cob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const - { - if (!operation_optimisable(operation)) - return false; - else - return details::is_constant_node(branch[0]) && - !details::is_constant_node(branch[1]) ; - } - - inline bool boc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const - { - if (!operation_optimisable(operation)) - return false; - else - return !details::is_constant_node(branch[0]) && - details::is_constant_node(branch[1]) ; - } - - inline bool cocob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const - { - if ( - (details::e_add == operation) || - (details::e_sub == operation) || - (details::e_mul == operation) || - (details::e_div == operation) - ) - { - return (details::is_constant_node(branch[0]) && details::is_cob_node(branch[1])) || - (details::is_constant_node(branch[1]) && details::is_cob_node(branch[0])) ; - } - else - return false; - } - - inline bool coboc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const - { - if ( - (details::e_add == operation) || - (details::e_sub == operation) || - (details::e_mul == operation) || - (details::e_div == operation) - ) - { - return (details::is_constant_node(branch[0]) && details::is_boc_node(branch[1])) || - (details::is_constant_node(branch[1]) && details::is_boc_node(branch[0])) ; - } - else - return false; - } - - inline bool uvouv_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const - { - if (!operation_optimisable(operation)) - return false; - else - return details::is_uv_node(branch[0]) && - details::is_uv_node(branch[1]) ; - } - - inline bool vob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const - { - if (!operation_optimisable(operation)) - return false; - else - return details::is_variable_node(branch[0]) && - !details::is_variable_node(branch[1]) ; - } - - inline bool bov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const - { - if (!operation_optimisable(operation)) - return false; - else - return !details::is_variable_node(branch[0]) && - details::is_variable_node(branch[1]) ; - } - - inline bool binext_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const - { - if (!operation_optimisable(operation)) - return false; - else - return !details::is_constant_node(branch[0]) || - !details::is_constant_node(branch[1]) ; - } - - inline bool is_invalid_assignment_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const - { - if (is_assignment_operation(operation)) - { - const bool b1_is_genstring = details::is_generally_string_node(branch[1]); - - if (details::is_string_node(branch[0])) - return !b1_is_genstring; - else - return ( - !details::is_variable_node (branch[0]) && - !details::is_vector_elem_node (branch[0]) && - !details::is_rebasevector_elem_node (branch[0]) && - !details::is_rebasevector_celem_node(branch[0]) && - !details::is_vector_node (branch[0]) - ) - || b1_is_genstring; - } - else - return false; - } - - inline bool is_constpow_operation(const details::operator_type& operation, expression_node_ptr(&branch)[2]) const - { - if ( - !details::is_constant_node(branch[1]) || - details::is_constant_node(branch[0]) || - details::is_variable_node(branch[0]) || - details::is_vector_node (branch[0]) || - details::is_generally_string_node(branch[0]) - ) - return false; - - const Type c = static_cast*>(branch[1])->value(); - - return cardinal_pow_optimisable(operation, c); - } - - inline bool is_invalid_break_continue_op(expression_node_ptr (&branch)[2]) const - { - return ( - details::is_break_node (branch[0]) || - details::is_break_node (branch[1]) || - details::is_continue_node(branch[0]) || - details::is_continue_node(branch[1]) - ); - } - - inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const - { - const bool b0_string = is_generally_string_node(branch[0]); - const bool b1_string = is_generally_string_node(branch[1]); - - bool result = false; - - if (b0_string != b1_string) - result = true; - else if (!valid_string_operation(operation) && b0_string && b1_string) - result = true; - - if (result) - { - parser_->set_synthesis_error("Invalid string operation"); - } - - return result; - } - - inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[3]) const - { - const bool b0_string = is_generally_string_node(branch[0]); - const bool b1_string = is_generally_string_node(branch[1]); - const bool b2_string = is_generally_string_node(branch[2]); - - bool result = false; - - if ((b0_string != b1_string) || (b1_string != b2_string)) - result = true; - else if ((details::e_inrange != operation) && b0_string && b1_string && b2_string) - result = true; - - if (result) - { - parser_->set_synthesis_error("Invalid string operation"); - } - - return result; - } - - inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const - { - const bool b0_string = is_generally_string_node(branch[0]); - const bool b1_string = is_generally_string_node(branch[1]); - - return (b0_string && b1_string && valid_string_operation(operation)); - } - - inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[3]) const - { - const bool b0_string = is_generally_string_node(branch[0]); - const bool b1_string = is_generally_string_node(branch[1]); - const bool b2_string = is_generally_string_node(branch[2]); - - return (b0_string && b1_string && b2_string && (details::e_inrange == operation)); - } - - #ifndef exprtk_disable_sc_andor - inline bool is_shortcircuit_expression(const details::operator_type& operation) const - { - return ( - (details::e_scand == operation) || - (details::e_scor == operation) - ); - } - #else - inline bool is_shortcircuit_expression(const details::operator_type&) const - { - return false; - } - #endif - - inline bool is_null_present(expression_node_ptr (&branch)[2]) const - { - return ( - details::is_null_node(branch[0]) || - details::is_null_node(branch[1]) - ); - } - - inline bool is_vector_eqineq_logic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const - { - if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1])) - return false; - else - return ( - (details::e_lt == operation) || - (details::e_lte == operation) || - (details::e_gt == operation) || - (details::e_gte == operation) || - (details::e_eq == operation) || - (details::e_ne == operation) || - (details::e_equal == operation) || - (details::e_and == operation) || - (details::e_nand == operation) || - (details:: e_or == operation) || - (details:: e_nor == operation) || - (details:: e_xor == operation) || - (details::e_xnor == operation) - ); - } - - inline bool is_vector_arithmetic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const - { - if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1])) - return false; - else - return ( - (details::e_add == operation) || - (details::e_sub == operation) || - (details::e_mul == operation) || - (details::e_div == operation) || - (details::e_pow == operation) - ); - } - - inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[2]) - { - if ((0 == branch[0]) || (0 == branch[1])) - { - return error_node(); - } - else if (is_invalid_string_op(operation,branch)) - { - return error_node(); - } - else if (is_invalid_assignment_op(operation,branch)) - { - return error_node(); - } - else if (is_invalid_break_continue_op(branch)) - { - return error_node(); - } - else if (details::e_assign == operation) - { - return synthesize_assignment_expression(operation, branch); - } - else if (details::e_swap == operation) - { - return synthesize_swap_expression(branch); - } - else if (is_assignment_operation(operation)) - { - return synthesize_assignment_operation_expression(operation, branch); - } - else if (is_vector_eqineq_logic_operation(operation, branch)) - { - return synthesize_veceqineqlogic_operation_expression(operation, branch); - } - else if (is_vector_arithmetic_operation(operation, branch)) - { - return synthesize_vecarithmetic_operation_expression(operation, branch); - } - else if (is_shortcircuit_expression(operation)) - { - return synthesize_shortcircuit_expression(operation, branch); - } - else if (is_string_operation(operation, branch)) - { - return synthesize_string_expression(operation, branch); - } - else if (is_null_present(branch)) - { - return synthesize_null_expression(operation, branch); - } - #ifndef exprtk_disable_cardinal_pow_optimisation - else if (is_constpow_operation(operation, branch)) - { - return cardinal_pow_optimisation(branch); - } - #endif - - expression_node_ptr result = error_node(); - - #ifndef exprtk_disable_enhanced_features - if (synthesize_expression(operation, branch, result)) - { - return result; - } - else - #endif - - { - /* - Possible reductions: - 1. c o cob -> cob - 2. cob o c -> cob - 3. c o boc -> boc - 4. boc o c -> boc - */ - result = error_node(); - - if (cocob_optimisable(operation, branch)) - { - result = synthesize_cocob_expression::process((*this), operation, branch); - } - else if (coboc_optimisable(operation, branch) && (0 == result)) - { - result = synthesize_coboc_expression::process((*this), operation, branch); - } - - if (result) - return result; - } - - if (uvouv_optimisable(operation, branch)) - { - return synthesize_uvouv_expression(operation, branch); - } - else if (vob_optimisable(operation, branch)) - { - return synthesize_vob_expression::process((*this), operation, branch); - } - else if (bov_optimisable(operation, branch)) - { - return synthesize_bov_expression::process((*this), operation, branch); - } - else if (cob_optimisable(operation, branch)) - { - return synthesize_cob_expression::process((*this), operation, branch); - } - else if (boc_optimisable(operation, branch)) - { - return synthesize_boc_expression::process((*this), operation, branch); - } - #ifndef exprtk_disable_enhanced_features - else if (cov_optimisable(operation, branch)) - { - return synthesize_cov_expression::process((*this), operation, branch); - } - #endif - else if (binext_optimisable(operation, branch)) - { - return synthesize_binary_ext_expression::process((*this), operation, branch); - } - else - return synthesize_expression(operation, branch); - } - - inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[3]) - { - if ( - (0 == branch[0]) || - (0 == branch[1]) || - (0 == branch[2]) - ) - { - details::free_all_nodes(*node_allocator_,branch); - - return error_node(); - } - else if (is_invalid_string_op(operation, branch)) - { - return error_node(); - } - else if (is_string_operation(operation, branch)) - { - return synthesize_string_expression(operation, branch); - } - else - return synthesize_expression(operation, branch); - } - - inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[4]) - { - return synthesize_expression(operation,branch); - } - - inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr b0) - { - expression_node_ptr branch[1] = { b0 }; - return (*this)(operation,branch); - } - - inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr& b0, expression_node_ptr& b1) - { - expression_node_ptr result = error_node(); - - if ((0 != b0) && (0 != b1)) - { - expression_node_ptr branch[2] = { b0, b1 }; - result = expression_generator::operator()(operation, branch); - b0 = branch[0]; - b1 = branch[1]; - } - - return result; - } - - inline expression_node_ptr conditional(expression_node_ptr condition, - expression_node_ptr consequent, - expression_node_ptr alternative) const - { - if ((0 == condition) || (0 == consequent)) - { - free_node(*node_allocator_, condition ); - free_node(*node_allocator_, consequent ); - free_node(*node_allocator_, alternative); - - return error_node(); - } - // Can the condition be immediately evaluated? if so optimise. - else if (details::is_constant_node(condition)) - { - // True branch - if (details::is_true(condition)) - { - free_node(*node_allocator_, condition ); - free_node(*node_allocator_, alternative); - - return consequent; - } - // False branch - else - { - free_node(*node_allocator_, condition ); - free_node(*node_allocator_, consequent); - - if (alternative) - return alternative; - else - return node_allocator_->allocate >(); - } - } - else if ((0 != consequent) && (0 != alternative)) - { - return node_allocator_-> - allocate(condition, consequent, alternative); - } - else - return node_allocator_-> - allocate(condition, consequent); - } - - #ifndef exprtk_disable_string_capabilities - inline expression_node_ptr conditional_string(expression_node_ptr condition, - expression_node_ptr consequent, - expression_node_ptr alternative) const - { - if ((0 == condition) || (0 == consequent)) - { - free_node(*node_allocator_, condition ); - free_node(*node_allocator_, consequent ); - free_node(*node_allocator_, alternative); - - return error_node(); - } - // Can the condition be immediately evaluated? if so optimise. - else if (details::is_constant_node(condition)) - { - // True branch - if (details::is_true(condition)) - { - free_node(*node_allocator_, condition ); - free_node(*node_allocator_, alternative); - - return consequent; - } - // False branch - else - { - free_node(*node_allocator_, condition ); - free_node(*node_allocator_, consequent); - - if (alternative) - return alternative; - else - return node_allocator_-> - allocate_c >(""); - } - } - else if ((0 != consequent) && (0 != alternative)) - return node_allocator_-> - allocate(condition, consequent, alternative); - else - return error_node(); - } - #else - inline expression_node_ptr conditional_string(expression_node_ptr, - expression_node_ptr, - expression_node_ptr) const - { - return error_node(); - } - #endif - - inline loop_runtime_check_ptr get_loop_runtime_check(const loop_runtime_check::loop_types loop_type) const - { - if ( - parser_->loop_runtime_check_ && - (loop_type == (parser_->loop_runtime_check_->loop_set & loop_type)) - ) - { - return parser_->loop_runtime_check_; - } - - return loop_runtime_check_ptr(0); - } - - inline expression_node_ptr while_loop(expression_node_ptr& condition, - expression_node_ptr& branch, - const bool brkcont = false) const - { - if (!brkcont && details::is_constant_node(condition)) - { - expression_node_ptr result = error_node(); - if (details::is_true(condition)) - // Infinite loops are not allowed. - result = error_node(); - else - result = node_allocator_->allocate >(); - - free_node(*node_allocator_, condition); - free_node(*node_allocator_, branch ); - - return result; - } - else if (details::is_null_node(condition)) - { - free_node(*node_allocator_,condition); - - return branch; - } - else if (!brkcont) - return node_allocator_->allocate - ( - condition, - branch, - get_loop_runtime_check(loop_runtime_check::e_while_loop) - ); - #ifndef exprtk_disable_break_continue - else - return node_allocator_->allocate - ( - condition, - branch, - get_loop_runtime_check(loop_runtime_check::e_while_loop) - ); - #else - return error_node(); - #endif - } - - inline expression_node_ptr repeat_until_loop(expression_node_ptr& condition, - expression_node_ptr& branch, - const bool brkcont = false) const - { - if (!brkcont && details::is_constant_node(condition)) - { - if ( - details::is_true(condition) && - details::is_constant_node(branch) - ) - { - free_node(*node_allocator_,condition); - - return branch; - } - - free_node(*node_allocator_, condition); - free_node(*node_allocator_, branch ); - - return error_node(); - } - else if (details::is_null_node(condition)) - { - free_node(*node_allocator_,condition); - - return branch; - } - else if (!brkcont) - return node_allocator_->allocate - ( - condition, - branch, - get_loop_runtime_check(loop_runtime_check::e_repeat_until_loop) - ); - #ifndef exprtk_disable_break_continue - else - return node_allocator_->allocate - ( - condition, - branch, - get_loop_runtime_check(loop_runtime_check::e_repeat_until_loop) - ); - #else - return error_node(); - #endif - } - - inline expression_node_ptr for_loop(expression_node_ptr& initialiser, - expression_node_ptr& condition, - expression_node_ptr& incrementor, - expression_node_ptr& loop_body, - bool brkcont = false) const - { - if (!brkcont && details::is_constant_node(condition)) - { - expression_node_ptr result = error_node(); - - if (details::is_true(condition)) - // Infinite loops are not allowed. - result = error_node(); - else - result = node_allocator_->allocate >(); - - free_node(*node_allocator_, initialiser); - free_node(*node_allocator_, condition ); - free_node(*node_allocator_, incrementor); - free_node(*node_allocator_, loop_body ); - - return result; - } - else if (details::is_null_node(condition) || (0 == condition)) - { - free_node(*node_allocator_, initialiser); - free_node(*node_allocator_, condition ); - free_node(*node_allocator_, incrementor); - - return loop_body; - } - else if (!brkcont) - return node_allocator_->allocate - ( - initialiser, - condition, - incrementor, - loop_body, - get_loop_runtime_check(loop_runtime_check::e_for_loop) - ); - - #ifndef exprtk_disable_break_continue - else - return node_allocator_->allocate - ( - initialiser, - condition, - incrementor, - loop_body, - get_loop_runtime_check(loop_runtime_check::e_for_loop) - ); - #else - return error_node(); - #endif - } - - template class Sequence> - inline expression_node_ptr const_optimise_switch(Sequence& arg_list) - { - expression_node_ptr result = error_node(); - - for (std::size_t i = 0; i < (arg_list.size() / 2); ++i) - { - expression_node_ptr condition = arg_list[(2 * i) ]; - expression_node_ptr consequent = arg_list[(2 * i) + 1]; - - if ((0 == result) && details::is_true(condition)) - { - result = consequent; - break; - } - } - - if (0 == result) - { - result = arg_list.back(); - } - - for (std::size_t i = 0; i < arg_list.size(); ++i) - { - expression_node_ptr current_expr = arg_list[i]; - - if (current_expr && (current_expr != result)) - { - free_node(*node_allocator_,current_expr); - } - } - - return result; - } - - template class Sequence> - inline expression_node_ptr const_optimise_mswitch(Sequence& arg_list) - { - expression_node_ptr result = error_node(); - - for (std::size_t i = 0; i < (arg_list.size() / 2); ++i) - { - expression_node_ptr condition = arg_list[(2 * i) ]; - expression_node_ptr consequent = arg_list[(2 * i) + 1]; - - if (details::is_true(condition)) - { - result = consequent; - } - } - - if (0 == result) - { - T zero = T(0); - result = node_allocator_->allocate(zero); - } - - for (std::size_t i = 0; i < arg_list.size(); ++i) - { - expression_node_ptr& current_expr = arg_list[i]; - - if (current_expr && (current_expr != result)) - { - free_node(*node_allocator_,current_expr); - } - } - - return result; - } - - struct switch_nodes - { - typedef std::vector > arg_list_t; - - #define case_stmt(N) \ - if (is_true(arg[(2 * N)].first)) { return arg[(2 * N) + 1].first->value(); } \ - - struct switch_impl_1 - { - static inline T process(const arg_list_t& arg) - { - case_stmt(0) - - assert(arg.size() == ((2 * 1) + 1)); - - return arg.back().first->value(); - } - }; - - struct switch_impl_2 - { - static inline T process(const arg_list_t& arg) - { - case_stmt(0) case_stmt(1) - - assert(arg.size() == ((2 * 2) + 1)); - - return arg.back().first->value(); - } - }; - - struct switch_impl_3 - { - static inline T process(const arg_list_t& arg) - { - case_stmt(0) case_stmt(1) - case_stmt(2) - - assert(arg.size() == ((2 * 3) + 1)); - - return arg.back().first->value(); - } - }; - - struct switch_impl_4 - { - static inline T process(const arg_list_t& arg) - { - case_stmt(0) case_stmt(1) - case_stmt(2) case_stmt(3) - - assert(arg.size() == ((2 * 4) + 1)); - - return arg.back().first->value(); - } - }; - - struct switch_impl_5 - { - static inline T process(const arg_list_t& arg) - { - case_stmt(0) case_stmt(1) - case_stmt(2) case_stmt(3) - case_stmt(4) - - assert(arg.size() == ((2 * 5) + 1)); - - return arg.back().first->value(); - } - }; - - struct switch_impl_6 - { - static inline T process(const arg_list_t& arg) - { - case_stmt(0) case_stmt(1) - case_stmt(2) case_stmt(3) - case_stmt(4) case_stmt(5) - - assert(arg.size() == ((2 * 6) + 1)); - - return arg.back().first->value(); - } - }; - - struct switch_impl_7 - { - static inline T process(const arg_list_t& arg) - { - case_stmt(0) case_stmt(1) - case_stmt(2) case_stmt(3) - case_stmt(4) case_stmt(5) - case_stmt(6) - - assert(arg.size() == ((2 * 7) + 1)); - - return arg.back().first->value(); - } - }; - - #undef case_stmt - }; - - template class Sequence> - inline expression_node_ptr switch_statement(Sequence& arg_list, const bool default_statement_present) - { - if (arg_list.empty()) - return error_node(); - else if ( - !all_nodes_valid(arg_list) || - (!default_statement_present && (arg_list.size() < 2)) - ) - { - details::free_all_nodes(*node_allocator_,arg_list); - - return error_node(); - } - else if (is_constant_foldable(arg_list)) - return const_optimise_switch(arg_list); - - switch ((arg_list.size() - 1) / 2) - { - #define case_stmt(N) \ - case N : \ - return node_allocator_-> \ - allocate >(arg_list); \ - - case_stmt(1) - case_stmt(2) - case_stmt(3) - case_stmt(4) - case_stmt(5) - case_stmt(6) - case_stmt(7) - #undef case_stmt - - default : return node_allocator_->allocate >(arg_list); - } - } - - template class Sequence> - inline expression_node_ptr multi_switch_statement(Sequence& arg_list) - { - if (!all_nodes_valid(arg_list)) - { - details::free_all_nodes(*node_allocator_,arg_list); - - return error_node(); - } - else if (is_constant_foldable(arg_list)) - return const_optimise_mswitch(arg_list); - else - return node_allocator_->allocate >(arg_list); - } - - #define unary_opr_switch_statements \ - case_stmt(details::e_abs , details::abs_op ) \ - case_stmt(details::e_acos , details::acos_op ) \ - case_stmt(details::e_acosh , details::acosh_op) \ - case_stmt(details::e_asin , details::asin_op ) \ - case_stmt(details::e_asinh , details::asinh_op) \ - case_stmt(details::e_atan , details::atan_op ) \ - case_stmt(details::e_atanh , details::atanh_op) \ - case_stmt(details::e_ceil , details::ceil_op ) \ - case_stmt(details::e_cos , details::cos_op ) \ - case_stmt(details::e_cosh , details::cosh_op ) \ - case_stmt(details::e_exp , details::exp_op ) \ - case_stmt(details::e_expm1 , details::expm1_op) \ - case_stmt(details::e_floor , details::floor_op) \ - case_stmt(details::e_log , details::log_op ) \ - case_stmt(details::e_log10 , details::log10_op) \ - case_stmt(details::e_log2 , details::log2_op ) \ - case_stmt(details::e_log1p , details::log1p_op) \ - case_stmt(details::e_neg , details::neg_op ) \ - case_stmt(details::e_pos , details::pos_op ) \ - case_stmt(details::e_round , details::round_op) \ - case_stmt(details::e_sin , details::sin_op ) \ - case_stmt(details::e_sinc , details::sinc_op ) \ - case_stmt(details::e_sinh , details::sinh_op ) \ - case_stmt(details::e_sqrt , details::sqrt_op ) \ - case_stmt(details::e_tan , details::tan_op ) \ - case_stmt(details::e_tanh , details::tanh_op ) \ - case_stmt(details::e_cot , details::cot_op ) \ - case_stmt(details::e_sec , details::sec_op ) \ - case_stmt(details::e_csc , details::csc_op ) \ - case_stmt(details::e_r2d , details::r2d_op ) \ - case_stmt(details::e_d2r , details::d2r_op ) \ - case_stmt(details::e_d2g , details::d2g_op ) \ - case_stmt(details::e_g2d , details::g2d_op ) \ - case_stmt(details::e_notl , details::notl_op ) \ - case_stmt(details::e_sgn , details::sgn_op ) \ - case_stmt(details::e_erf , details::erf_op ) \ - case_stmt(details::e_erfc , details::erfc_op ) \ - case_stmt(details::e_ncdf , details::ncdf_op ) \ - case_stmt(details::e_frac , details::frac_op ) \ - case_stmt(details::e_trunc , details::trunc_op) \ - - inline expression_node_ptr synthesize_uv_expression(const details::operator_type& operation, - expression_node_ptr (&branch)[1]) - { - T& v = static_cast*>(branch[0])->ref(); - - switch (operation) - { - #define case_stmt(op0,op1) \ - case op0 : return node_allocator_-> \ - allocate > >(v); \ - - unary_opr_switch_statements - #undef case_stmt - default : return error_node(); - } - } - - inline expression_node_ptr synthesize_uvec_expression(const details::operator_type& operation, - expression_node_ptr (&branch)[1]) - { - switch (operation) - { - #define case_stmt(op0,op1) \ - case op0 : return node_allocator_-> \ - allocate > > \ - (operation, branch[0]); \ - - unary_opr_switch_statements - #undef case_stmt - default : return error_node(); - } - } - - inline expression_node_ptr synthesize_unary_expression(const details::operator_type& operation, - expression_node_ptr (&branch)[1]) - { - switch (operation) - { - #define case_stmt(op0,op1) \ - case op0 : return node_allocator_-> \ - allocate > >(branch[0]); \ - - unary_opr_switch_statements - #undef case_stmt - default : return error_node(); - } - } - - inline expression_node_ptr const_optimise_sf3(const details::operator_type& operation, - expression_node_ptr (&branch)[3]) - { - expression_node_ptr temp_node = error_node(); - - switch (operation) - { - #define case_stmt(op) \ - case details::e_sf##op : temp_node = node_allocator_-> \ - allocate > > \ - (operation, branch); \ - break; \ - - case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03) - case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07) - case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11) - case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15) - case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19) - case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23) - case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27) - case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31) - case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35) - case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39) - case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43) - case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47) - #undef case_stmt - default : return error_node(); - } - - const T v = temp_node->value(); - - details::free_node(*node_allocator_,temp_node); - - return node_allocator_->allocate(v); - } - - inline expression_node_ptr varnode_optimise_sf3(const details::operator_type& operation, expression_node_ptr (&branch)[3]) - { - typedef details::variable_node* variable_ptr; - - const Type& v0 = static_cast(branch[0])->ref(); - const Type& v1 = static_cast(branch[1])->ref(); - const Type& v2 = static_cast(branch[2])->ref(); - - switch (operation) - { - #define case_stmt(op) \ - case details::e_sf##op : return node_allocator_-> \ - allocate_rrr > > \ - (v0, v1, v2); \ - - case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03) - case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07) - case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11) - case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15) - case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19) - case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23) - case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27) - case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31) - case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35) - case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39) - case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43) - case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47) - #undef case_stmt - default : return error_node(); - } - } - - inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[3]) - { - if (!all_nodes_valid(branch)) - return error_node(); - else if (is_constant_foldable(branch)) - return const_optimise_sf3(operation,branch); - else if (all_nodes_variables(branch)) - return varnode_optimise_sf3(operation,branch); - else - { - switch (operation) - { - #define case_stmt(op) \ - case details::e_sf##op : return node_allocator_-> \ - allocate > > \ - (operation, branch); \ - - case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03) - case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07) - case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11) - case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15) - case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19) - case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23) - case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27) - case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31) - case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35) - case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39) - case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43) - case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47) - #undef case_stmt - default : return error_node(); - } - } - } - - inline expression_node_ptr const_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4]) - { - expression_node_ptr temp_node = error_node(); - - switch (operation) - { - #define case_stmt(op) \ - case details::e_sf##op : temp_node = node_allocator_-> \ - allocate > > \ - (operation, branch); \ - break; \ - - case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51) - case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55) - case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59) - case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63) - case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67) - case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71) - case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75) - case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79) - case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83) - case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87) - case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91) - case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95) - case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99) - #undef case_stmt - default : return error_node(); - } - - const T v = temp_node->value(); - - details::free_node(*node_allocator_,temp_node); - - return node_allocator_->allocate(v); - } - - inline expression_node_ptr varnode_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4]) - { - typedef details::variable_node* variable_ptr; - - const Type& v0 = static_cast(branch[0])->ref(); - const Type& v1 = static_cast(branch[1])->ref(); - const Type& v2 = static_cast(branch[2])->ref(); - const Type& v3 = static_cast(branch[3])->ref(); - - switch (operation) - { - #define case_stmt(op) \ - case details::e_sf##op : return node_allocator_-> \ - allocate_rrrr > > \ - (v0, v1, v2, v3); \ - - case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51) - case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55) - case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59) - case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63) - case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67) - case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71) - case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75) - case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79) - case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83) - case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87) - case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91) - case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95) - case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99) - #undef case_stmt - default : return error_node(); - } - } - - inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[4]) - { - if (!all_nodes_valid(branch)) - return error_node(); - else if (is_constant_foldable(branch)) - return const_optimise_sf4(operation,branch); - else if (all_nodes_variables(branch)) - return varnode_optimise_sf4(operation,branch); - switch (operation) - { - #define case_stmt(op) \ - case details::e_sf##op : return node_allocator_-> \ - allocate > > \ - (operation, branch); \ - - case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51) - case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55) - case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59) - case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63) - case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67) - case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71) - case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75) - case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79) - case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83) - case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87) - case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91) - case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95) - case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99) - #undef case_stmt - default : return error_node(); - } - } - - template class Sequence> - inline expression_node_ptr const_optimise_varargfunc(const details::operator_type& operation, Sequence& arg_list) - { - expression_node_ptr temp_node = error_node(); - - switch (operation) - { - #define case_stmt(op0,op1) \ - case op0 : temp_node = node_allocator_-> \ - allocate > > \ - (arg_list); \ - break; \ - - case_stmt(details::e_sum , details::vararg_add_op ) - case_stmt(details::e_prod , details::vararg_mul_op ) - case_stmt(details::e_avg , details::vararg_avg_op ) - case_stmt(details::e_min , details::vararg_min_op ) - case_stmt(details::e_max , details::vararg_max_op ) - case_stmt(details::e_mand , details::vararg_mand_op ) - case_stmt(details::e_mor , details::vararg_mor_op ) - case_stmt(details::e_multi , details::vararg_multi_op) - #undef case_stmt - default : return error_node(); - } - - const T v = temp_node->value(); - - details::free_node(*node_allocator_,temp_node); - - return node_allocator_->allocate(v); - } - - inline bool special_one_parameter_vararg(const details::operator_type& operation) const - { - return ( - (details::e_sum == operation) || - (details::e_prod == operation) || - (details::e_avg == operation) || - (details::e_min == operation) || - (details::e_max == operation) - ); - } - - template class Sequence> - inline expression_node_ptr varnode_optimise_varargfunc(const details::operator_type& operation, Sequence& arg_list) - { - switch (operation) - { - #define case_stmt(op0,op1) \ - case op0 : return node_allocator_-> \ - allocate > >(arg_list); \ - - case_stmt(details::e_sum , details::vararg_add_op ) - case_stmt(details::e_prod , details::vararg_mul_op ) - case_stmt(details::e_avg , details::vararg_avg_op ) - case_stmt(details::e_min , details::vararg_min_op ) - case_stmt(details::e_max , details::vararg_max_op ) - case_stmt(details::e_mand , details::vararg_mand_op ) - case_stmt(details::e_mor , details::vararg_mor_op ) - case_stmt(details::e_multi , details::vararg_multi_op) - #undef case_stmt - default : return error_node(); - } - } - - template class Sequence> - inline expression_node_ptr vectorize_func(const details::operator_type& operation, Sequence& arg_list) - { - if (1 == arg_list.size()) - { - switch (operation) - { - #define case_stmt(op0,op1) \ - case op0 : return node_allocator_-> \ - allocate > >(arg_list[0]); \ - - case_stmt(details::e_sum , details::vec_add_op) - case_stmt(details::e_prod , details::vec_mul_op) - case_stmt(details::e_avg , details::vec_avg_op) - case_stmt(details::e_min , details::vec_min_op) - case_stmt(details::e_max , details::vec_max_op) - #undef case_stmt - default : return error_node(); - } - } - else - return error_node(); - } - - template class Sequence> - inline expression_node_ptr vararg_function(const details::operator_type& operation, Sequence& arg_list) - { - if (!all_nodes_valid(arg_list)) - { - details::free_all_nodes(*node_allocator_,arg_list); - - return error_node(); - } - else if (is_constant_foldable(arg_list)) - return const_optimise_varargfunc(operation,arg_list); - else if ((arg_list.size() == 1) && details::is_ivector_node(arg_list[0])) - return vectorize_func(operation,arg_list); - else if ((arg_list.size() == 1) && special_one_parameter_vararg(operation)) - return arg_list[0]; - else if (all_nodes_variables(arg_list)) - return varnode_optimise_varargfunc(operation,arg_list); - - #ifndef exprtk_disable_string_capabilities - if (details::e_smulti == operation) - { - return node_allocator_-> - allocate > >(arg_list); - } - else - #endif - { - switch (operation) - { - #define case_stmt(op0,op1) \ - case op0 : return node_allocator_-> \ - allocate > >(arg_list); \ - - case_stmt(details::e_sum , details::vararg_add_op ) - case_stmt(details::e_prod , details::vararg_mul_op ) - case_stmt(details::e_avg , details::vararg_avg_op ) - case_stmt(details::e_min , details::vararg_min_op ) - case_stmt(details::e_max , details::vararg_max_op ) - case_stmt(details::e_mand , details::vararg_mand_op ) - case_stmt(details::e_mor , details::vararg_mor_op ) - case_stmt(details::e_multi , details::vararg_multi_op) - #undef case_stmt - default : return error_node(); - } - } - } - - template - inline expression_node_ptr function(ifunction_t* f, expression_node_ptr (&b)[N]) - { - typedef typename details::function_N_node function_N_node_t; - expression_node_ptr result = synthesize_expression(f,b); - - if (0 == result) - return error_node(); - else - { - // Can the function call be completely optimised? - if (details::is_constant_node(result)) - return result; - else if (!all_nodes_valid(b)) - { - details::free_node(*node_allocator_,result); - std::fill_n(b, N, reinterpret_cast(0)); - - return error_node(); - } - else if (N != f->param_count) - { - details::free_node(*node_allocator_,result); - std::fill_n(b, N, reinterpret_cast(0)); - - return error_node(); - } - - function_N_node_t* func_node_ptr = reinterpret_cast(result); - - if (!func_node_ptr->init_branches(b)) - { - details::free_node(*node_allocator_,result); - std::fill_n(b, N, reinterpret_cast(0)); - - return error_node(); - } - - return result; - } - } - - inline expression_node_ptr function(ifunction_t* f) - { - typedef typename details::function_N_node function_N_node_t; - return node_allocator_->allocate(f); - } - - inline expression_node_ptr vararg_function_call(ivararg_function_t* vaf, - std::vector& arg_list) - { - if (!all_nodes_valid(arg_list)) - { - details::free_all_nodes(*node_allocator_,arg_list); - - return error_node(); - } - - typedef details::vararg_function_node alloc_type; - - expression_node_ptr result = node_allocator_->allocate(vaf,arg_list); - - if ( - !arg_list.empty() && - !vaf->has_side_effects() && - is_constant_foldable(arg_list) - ) - { - const Type v = result->value(); - details::free_node(*node_allocator_,result); - result = node_allocator_->allocate(v); - } - - parser_->state_.activate_side_effect("vararg_function_call()"); - - return result; - } - - inline expression_node_ptr generic_function_call(igeneric_function_t* gf, - std::vector& arg_list, - const std::size_t& param_seq_index = std::numeric_limits::max()) - { - if (!all_nodes_valid(arg_list)) - { - details::free_all_nodes(*node_allocator_,arg_list); - return error_node(); - } - - typedef details::generic_function_node alloc_type1; - typedef details::multimode_genfunction_node alloc_type2; - - const std::size_t no_psi = std::numeric_limits::max(); - - expression_node_ptr result = error_node(); - - if (no_psi == param_seq_index) - result = node_allocator_->allocate(arg_list,gf); - else - result = node_allocator_->allocate(gf, param_seq_index, arg_list); - - alloc_type1* genfunc_node_ptr = static_cast(result); - - if ( - !arg_list.empty() && - !gf->has_side_effects() && - parser_->state_.type_check_enabled && - is_constant_foldable(arg_list) - ) - { - genfunc_node_ptr->init_branches(); - - const Type v = result->value(); - - details::free_node(*node_allocator_,result); - - return node_allocator_->allocate(v); - } - else if (genfunc_node_ptr->init_branches()) - { - parser_->state_.activate_side_effect("generic_function_call()"); - - return result; - } - else - { - details::free_node(*node_allocator_, result); - details::free_all_nodes(*node_allocator_, arg_list); - - return error_node(); - } - } - - #ifndef exprtk_disable_string_capabilities - inline expression_node_ptr string_function_call(igeneric_function_t* gf, - std::vector& arg_list, - const std::size_t& param_seq_index = std::numeric_limits::max()) - { - if (!all_nodes_valid(arg_list)) - { - details::free_all_nodes(*node_allocator_,arg_list); - return error_node(); - } - - typedef details::string_function_node alloc_type1; - typedef details::multimode_strfunction_node alloc_type2; - - const std::size_t no_psi = std::numeric_limits::max(); - - expression_node_ptr result = error_node(); - - if (no_psi == param_seq_index) - result = node_allocator_->allocate(gf,arg_list); - else - result = node_allocator_->allocate(gf, param_seq_index, arg_list); - - alloc_type1* strfunc_node_ptr = static_cast(result); - - if ( - !arg_list.empty() && - !gf->has_side_effects() && - is_constant_foldable(arg_list) - ) - { - strfunc_node_ptr->init_branches(); - - const Type v = result->value(); - - details::free_node(*node_allocator_,result); - - return node_allocator_->allocate(v); - } - else if (strfunc_node_ptr->init_branches()) - { - parser_->state_.activate_side_effect("string_function_call()"); - - return result; - } - else - { - details::free_node (*node_allocator_,result ); - details::free_all_nodes(*node_allocator_,arg_list); - - return error_node(); - } - } - #endif - - #ifndef exprtk_disable_return_statement - inline expression_node_ptr return_call(std::vector& arg_list) - { - if (!all_nodes_valid(arg_list)) - { - details::free_all_nodes(*node_allocator_,arg_list); - return error_node(); - } - - typedef details::return_node alloc_type; - - expression_node_ptr result = node_allocator_-> - allocate_rr(arg_list,parser_->results_ctx()); - - alloc_type* return_node_ptr = static_cast(result); - - if (return_node_ptr->init_branches()) - { - parser_->state_.activate_side_effect("return_call()"); - - return result; - } - else - { - details::free_node (*node_allocator_,result ); - details::free_all_nodes(*node_allocator_,arg_list); - - return error_node(); - } - } - - inline expression_node_ptr return_envelope(expression_node_ptr body, - results_context_t* rc, - bool*& return_invoked) - { - typedef details::return_envelope_node alloc_type; - - expression_node_ptr result = node_allocator_-> - allocate_cr(body,(*rc)); - - return_invoked = static_cast(result)->retinvk_ptr(); - - return result; - } - #else - inline expression_node_ptr return_call(std::vector&) - { - return error_node(); - } - - inline expression_node_ptr return_envelope(expression_node_ptr, - results_context_t*, - bool*&) - { - return error_node(); - } - #endif - - inline expression_node_ptr vector_element(const std::string& symbol, - vector_holder_ptr vector_base, - expression_node_ptr index) - { - expression_node_ptr result = error_node(); - - if (details::is_constant_node(index)) - { - std::size_t i = static_cast(details::numeric::to_int64(index->value())); - - details::free_node(*node_allocator_,index); - - if (vector_base->rebaseable()) - { - return node_allocator_->allocate(i,vector_base); - } - - const scope_element& se = parser_->sem_.get_element(symbol,i); - - if (se.index == i) - { - result = se.var_node; - } - else - { - scope_element nse; - nse.name = symbol; - nse.active = true; - nse.ref_count = 1; - nse.type = scope_element::e_vecelem; - nse.index = i; - nse.depth = parser_->state_.scope_depth; - nse.data = 0; - nse.var_node = node_allocator_->allocate((*(*vector_base)[i])); - - if (!parser_->sem_.add_element(nse)) - { - parser_->set_synthesis_error("Failed to add new local vector element to SEM [1]"); - - parser_->sem_.free_element(nse); - - result = error_node(); - } - - exprtk_debug(("vector_element() - INFO - Added new local vector element: %s\n",nse.name.c_str())); - - parser_->state_.activate_side_effect("vector_element()"); - - result = nse.var_node; - } - } - else if (vector_base->rebaseable()) - result = node_allocator_->allocate(index,vector_base); - else - result = node_allocator_->allocate(index,vector_base); - - return result; - } - - private: - - template - inline bool is_constant_foldable(NodePtr (&b)[N]) const - { - for (std::size_t i = 0; i < N; ++i) - { - if (0 == b[i]) - return false; - else if (!details::is_constant_node(b[i])) - return false; - } - - return true; - } - - template class Sequence> - inline bool is_constant_foldable(const Sequence& b) const - { - for (std::size_t i = 0; i < b.size(); ++i) - { - if (0 == b[i]) - return false; - else if (!details::is_constant_node(b[i])) - return false; - } - - return true; - } - - void lodge_assignment(symbol_type cst, expression_node_ptr node) - { - parser_->state_.activate_side_effect("lodge_assignment()"); - - if (!parser_->dec_.collect_assignments()) - return; - - std::string symbol_name; - - switch (cst) - { - case e_st_variable : symbol_name = parser_->symtab_store_ - .get_variable_name(node); - break; - - #ifndef exprtk_disable_string_capabilities - case e_st_string : symbol_name = parser_->symtab_store_ - .get_stringvar_name(node); - break; - #endif - - case e_st_vector : { - typedef details::vector_holder vector_holder_t; - - vector_holder_t& vh = static_cast(node)->vec_holder(); - - symbol_name = parser_->symtab_store_.get_vector_name(&vh); - } - break; - - case e_st_vecelem : { - typedef details::vector_holder vector_holder_t; - - vector_holder_t& vh = static_cast(node)->vec_holder(); - - symbol_name = parser_->symtab_store_.get_vector_name(&vh); - - cst = e_st_vector; - } - break; - - default : return; - } - - if (!symbol_name.empty()) - { - parser_->dec_.add_assignment(symbol_name,cst); - } - } - - inline expression_node_ptr synthesize_assignment_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) - { - if (details::is_variable_node(branch[0])) - { - lodge_assignment(e_st_variable,branch[0]); - - return synthesize_expression(operation,branch); - } - else if (details::is_vector_elem_node(branch[0])) - { - lodge_assignment(e_st_vecelem,branch[0]); - - return synthesize_expression(operation, branch); - } - else if (details::is_rebasevector_elem_node(branch[0])) - { - lodge_assignment(e_st_vecelem,branch[0]); - - return synthesize_expression(operation, branch); - } - else if (details::is_rebasevector_celem_node(branch[0])) - { - lodge_assignment(e_st_vecelem,branch[0]); - - return synthesize_expression(operation, branch); - } - #ifndef exprtk_disable_string_capabilities - else if (details::is_string_node(branch[0])) - { - lodge_assignment(e_st_string,branch[0]); - - return synthesize_expression(operation, branch); - } - else if (details::is_string_range_node(branch[0])) - { - lodge_assignment(e_st_string,branch[0]); - - return synthesize_expression(operation, branch); - } - #endif - else if (details::is_vector_node(branch[0])) - { - lodge_assignment(e_st_vector,branch[0]); - - if (details::is_ivector_node(branch[1])) - return synthesize_expression(operation, branch); - else - return synthesize_expression(operation, branch); - } - else - { - parser_->set_synthesis_error("Invalid assignment operation.[1]"); - - return error_node(); - } - } - - inline expression_node_ptr synthesize_assignment_operation_expression(const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - if (details::is_variable_node(branch[0])) - { - lodge_assignment(e_st_variable,branch[0]); - - switch (operation) - { - #define case_stmt(op0,op1) \ - case op0 : return node_allocator_-> \ - template allocate_rrr > > \ - (operation, branch[0], branch[1]); \ - - case_stmt(details::e_addass , details::add_op) - case_stmt(details::e_subass , details::sub_op) - case_stmt(details::e_mulass , details::mul_op) - case_stmt(details::e_divass , details::div_op) - case_stmt(details::e_modass , details::mod_op) - #undef case_stmt - default : return error_node(); - } - } - else if (details::is_vector_elem_node(branch[0])) - { - lodge_assignment(e_st_vecelem,branch[0]); - - switch (operation) - { - #define case_stmt(op0,op1) \ - case op0 : return node_allocator_-> \ - template allocate_rrr > > \ - (operation, branch[0], branch[1]); \ - - case_stmt(details::e_addass , details::add_op) - case_stmt(details::e_subass , details::sub_op) - case_stmt(details::e_mulass , details::mul_op) - case_stmt(details::e_divass , details::div_op) - case_stmt(details::e_modass , details::mod_op) - #undef case_stmt - default : return error_node(); - } - } - else if (details::is_rebasevector_elem_node(branch[0])) - { - lodge_assignment(e_st_vecelem,branch[0]); - - switch (operation) - { - #define case_stmt(op0,op1) \ - case op0 : return node_allocator_-> \ - template allocate_rrr > > \ - (operation, branch[0], branch[1]); \ - - case_stmt(details::e_addass , details::add_op) - case_stmt(details::e_subass , details::sub_op) - case_stmt(details::e_mulass , details::mul_op) - case_stmt(details::e_divass , details::div_op) - case_stmt(details::e_modass , details::mod_op) - #undef case_stmt - default : return error_node(); - } - } - else if (details::is_rebasevector_celem_node(branch[0])) - { - lodge_assignment(e_st_vecelem,branch[0]); - - switch (operation) - { - #define case_stmt(op0,op1) \ - case op0 : return node_allocator_-> \ - template allocate_rrr > > \ - (operation, branch[0], branch[1]); \ - - case_stmt(details::e_addass , details::add_op) - case_stmt(details::e_subass , details::sub_op) - case_stmt(details::e_mulass , details::mul_op) - case_stmt(details::e_divass , details::div_op) - case_stmt(details::e_modass , details::mod_op) - #undef case_stmt - default : return error_node(); - } - } - else if (details::is_vector_node(branch[0])) - { - lodge_assignment(e_st_vector,branch[0]); - - if (details::is_ivector_node(branch[1])) - { - switch (operation) - { - #define case_stmt(op0,op1) \ - case op0 : return node_allocator_-> \ - template allocate_rrr > > \ - (operation, branch[0], branch[1]); \ - - case_stmt(details::e_addass , details::add_op) - case_stmt(details::e_subass , details::sub_op) - case_stmt(details::e_mulass , details::mul_op) - case_stmt(details::e_divass , details::div_op) - case_stmt(details::e_modass , details::mod_op) - #undef case_stmt - default : return error_node(); - } - } - else - { - switch (operation) - { - #define case_stmt(op0,op1) \ - case op0 : return node_allocator_-> \ - template allocate_rrr > > \ - (operation, branch[0], branch[1]); \ - - case_stmt(details::e_addass , details::add_op) - case_stmt(details::e_subass , details::sub_op) - case_stmt(details::e_mulass , details::mul_op) - case_stmt(details::e_divass , details::div_op) - case_stmt(details::e_modass , details::mod_op) - #undef case_stmt - default : return error_node(); - } - } - } - #ifndef exprtk_disable_string_capabilities - else if ( - (details::e_addass == operation) && - details::is_string_node(branch[0]) - ) - { - typedef details::assignment_string_node addass_t; - - lodge_assignment(e_st_string,branch[0]); - - return synthesize_expression(operation,branch); - } - #endif - else - { - parser_->set_synthesis_error("Invalid assignment operation[2]"); - - return error_node(); - } - } - - inline expression_node_ptr synthesize_veceqineqlogic_operation_expression(const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - const bool is_b0_ivec = details::is_ivector_node(branch[0]); - const bool is_b1_ivec = details::is_ivector_node(branch[1]); - - #define batch_eqineq_logic_case \ - case_stmt(details::e_lt , details::lt_op ) \ - case_stmt(details::e_lte , details::lte_op ) \ - case_stmt(details::e_gt , details::gt_op ) \ - case_stmt(details::e_gte , details::gte_op ) \ - case_stmt(details::e_eq , details::eq_op ) \ - case_stmt(details::e_ne , details::ne_op ) \ - case_stmt(details::e_equal, details::equal_op) \ - case_stmt(details::e_and , details::and_op ) \ - case_stmt(details::e_nand , details::nand_op ) \ - case_stmt(details::e_or , details::or_op ) \ - case_stmt(details::e_nor , details::nor_op ) \ - case_stmt(details::e_xor , details::xor_op ) \ - case_stmt(details::e_xnor , details::xnor_op ) \ - - if (is_b0_ivec && is_b1_ivec) - { - switch (operation) - { - #define case_stmt(op0,op1) \ - case op0 : return node_allocator_-> \ - template allocate_rrr > > \ - (operation, branch[0], branch[1]); \ - - batch_eqineq_logic_case - #undef case_stmt - default : return error_node(); - } - } - else if (is_b0_ivec && !is_b1_ivec) - { - switch (operation) - { - #define case_stmt(op0,op1) \ - case op0 : return node_allocator_-> \ - template allocate_rrr > > \ - (operation, branch[0], branch[1]); \ - - batch_eqineq_logic_case - #undef case_stmt - default : return error_node(); - } - } - else if (!is_b0_ivec && is_b1_ivec) - { - switch (operation) - { - #define case_stmt(op0,op1) \ - case op0 : return node_allocator_-> \ - template allocate_rrr > > \ - (operation, branch[0], branch[1]); \ - - batch_eqineq_logic_case - #undef case_stmt - default : return error_node(); - } - } - else - return error_node(); - - #undef batch_eqineq_logic_case - } - - inline expression_node_ptr synthesize_vecarithmetic_operation_expression(const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - const bool is_b0_ivec = details::is_ivector_node(branch[0]); - const bool is_b1_ivec = details::is_ivector_node(branch[1]); - - #define vector_ops \ - case_stmt(details::e_add , details::add_op) \ - case_stmt(details::e_sub , details::sub_op) \ - case_stmt(details::e_mul , details::mul_op) \ - case_stmt(details::e_div , details::div_op) \ - case_stmt(details::e_mod , details::mod_op) \ - - if (is_b0_ivec && is_b1_ivec) - { - switch (operation) - { - #define case_stmt(op0,op1) \ - case op0 : return node_allocator_-> \ - template allocate_rrr > > \ - (operation, branch[0], branch[1]); \ - - vector_ops - case_stmt(details::e_pow,details:: pow_op) - #undef case_stmt - default : return error_node(); - } - } - else if (is_b0_ivec && !is_b1_ivec) - { - switch (operation) - { - #define case_stmt(op0,op1) \ - case op0 : return node_allocator_-> \ - template allocate_rrr > > \ - (operation, branch[0], branch[1]); \ - - vector_ops - case_stmt(details::e_pow,details:: pow_op) - #undef case_stmt - default : return error_node(); - } - } - else if (!is_b0_ivec && is_b1_ivec) - { - switch (operation) - { - #define case_stmt(op0,op1) \ - case op0 : return node_allocator_-> \ - template allocate_rrr > > \ - (operation, branch[0], branch[1]); \ - - vector_ops - #undef case_stmt - default : return error_node(); - } - } - else - return error_node(); - - #undef vector_ops - } - - inline expression_node_ptr synthesize_swap_expression(expression_node_ptr (&branch)[2]) - { - const bool v0_is_ivar = details::is_ivariable_node(branch[0]); - const bool v1_is_ivar = details::is_ivariable_node(branch[1]); - - const bool v0_is_ivec = details::is_ivector_node (branch[0]); - const bool v1_is_ivec = details::is_ivector_node (branch[1]); - - #ifndef exprtk_disable_string_capabilities - const bool v0_is_str = details::is_generally_string_node(branch[0]); - const bool v1_is_str = details::is_generally_string_node(branch[1]); - #endif - - expression_node_ptr result = error_node(); - - if (v0_is_ivar && v1_is_ivar) - { - typedef details::variable_node* variable_node_ptr; - - variable_node_ptr v0 = variable_node_ptr(0); - variable_node_ptr v1 = variable_node_ptr(0); - - if ( - (0 != (v0 = dynamic_cast(branch[0]))) && - (0 != (v1 = dynamic_cast(branch[1]))) - ) - { - result = node_allocator_->allocate >(v0,v1); - } - else - result = node_allocator_->allocate >(branch[0],branch[1]); - } - else if (v0_is_ivec && v1_is_ivec) - { - result = node_allocator_->allocate >(branch[0],branch[1]); - } - #ifndef exprtk_disable_string_capabilities - else if (v0_is_str && v1_is_str) - { - if (is_string_node(branch[0]) && is_string_node(branch[1])) - result = node_allocator_->allocate > - (branch[0], branch[1]); - else - result = node_allocator_->allocate > - (branch[0], branch[1]); - } - #endif - else - { - parser_->set_synthesis_error("Only variables, strings, vectors or vector elements can be swapped"); - - return error_node(); - } - - parser_->state_.activate_side_effect("synthesize_swap_expression()"); - - return result; - } - - #ifndef exprtk_disable_sc_andor - inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) - { - expression_node_ptr result = error_node(); - - if (details::is_constant_node(branch[0])) - { - if ( - (details::e_scand == operation) && - std::equal_to()(T(0),branch[0]->value()) - ) - result = node_allocator_->allocate_c(T(0)); - else if ( - (details::e_scor == operation) && - std::not_equal_to()(T(0),branch[0]->value()) - ) - result = node_allocator_->allocate_c(T(1)); - } - - if (details::is_constant_node(branch[1]) && (0 == result)) - { - if ( - (details::e_scand == operation) && - std::equal_to()(T(0),branch[1]->value()) - ) - result = node_allocator_->allocate_c(T(0)); - else if ( - (details::e_scor == operation) && - std::not_equal_to()(T(0),branch[1]->value()) - ) - result = node_allocator_->allocate_c(T(1)); - } - - if (result) - { - free_node(*node_allocator_, branch[0]); - free_node(*node_allocator_, branch[1]); - - return result; - } - else if (details::e_scand == operation) - { - return synthesize_expression(operation, branch); - } - else if (details::e_scor == operation) - { - return synthesize_expression(operation, branch); - } - else - return error_node(); - } - #else - inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type&, expression_node_ptr (&)[2]) - { - return error_node(); - } - #endif - - #define basic_opr_switch_statements \ - case_stmt(details::e_add , details::add_op) \ - case_stmt(details::e_sub , details::sub_op) \ - case_stmt(details::e_mul , details::mul_op) \ - case_stmt(details::e_div , details::div_op) \ - case_stmt(details::e_mod , details::mod_op) \ - case_stmt(details::e_pow , details::pow_op) \ - - #define extended_opr_switch_statements \ - case_stmt(details::e_lt , details::lt_op ) \ - case_stmt(details::e_lte , details::lte_op ) \ - case_stmt(details::e_gt , details::gt_op ) \ - case_stmt(details::e_gte , details::gte_op ) \ - case_stmt(details::e_eq , details::eq_op ) \ - case_stmt(details::e_ne , details::ne_op ) \ - case_stmt(details::e_and , details::and_op ) \ - case_stmt(details::e_nand, details::nand_op) \ - case_stmt(details::e_or , details::or_op ) \ - case_stmt(details::e_nor , details::nor_op ) \ - case_stmt(details::e_xor , details::xor_op ) \ - case_stmt(details::e_xnor, details::xnor_op) \ - - #ifndef exprtk_disable_cardinal_pow_optimisation - template class IPowNode> - inline expression_node_ptr cardinal_pow_optimisation_impl(const TType& v, const unsigned int& p) - { - switch (p) - { - #define case_stmt(cp) \ - case cp : return node_allocator_-> \ - allocate > >(v); \ - - case_stmt( 1) case_stmt( 2) case_stmt( 3) case_stmt( 4) - case_stmt( 5) case_stmt( 6) case_stmt( 7) case_stmt( 8) - case_stmt( 9) case_stmt(10) case_stmt(11) case_stmt(12) - case_stmt(13) case_stmt(14) case_stmt(15) case_stmt(16) - case_stmt(17) case_stmt(18) case_stmt(19) case_stmt(20) - case_stmt(21) case_stmt(22) case_stmt(23) case_stmt(24) - case_stmt(25) case_stmt(26) case_stmt(27) case_stmt(28) - case_stmt(29) case_stmt(30) case_stmt(31) case_stmt(32) - case_stmt(33) case_stmt(34) case_stmt(35) case_stmt(36) - case_stmt(37) case_stmt(38) case_stmt(39) case_stmt(40) - case_stmt(41) case_stmt(42) case_stmt(43) case_stmt(44) - case_stmt(45) case_stmt(46) case_stmt(47) case_stmt(48) - case_stmt(49) case_stmt(50) case_stmt(51) case_stmt(52) - case_stmt(53) case_stmt(54) case_stmt(55) case_stmt(56) - case_stmt(57) case_stmt(58) case_stmt(59) case_stmt(60) - #undef case_stmt - default : return error_node(); - } - } - - inline expression_node_ptr cardinal_pow_optimisation(const T& v, const T& c) - { - const bool not_recipricol = (c >= T(0)); - const unsigned int p = static_cast(details::numeric::to_int32(details::numeric::abs(c))); - - if (0 == p) - return node_allocator_->allocate_c(T(1)); - else if (std::equal_to()(T(2),c)) - { - return node_allocator_-> - template allocate_rr > >(v,v); - } - else - { - if (not_recipricol) - return cardinal_pow_optimisation_impl(v,p); - else - return cardinal_pow_optimisation_impl(v,p); - } - } - - inline bool cardinal_pow_optimisable(const details::operator_type& operation, const T& c) const - { - return (details::e_pow == operation) && (details::numeric::abs(c) <= T(60)) && details::numeric::is_integer(c); - } - - inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr (&branch)[2]) - { - const Type c = static_cast*>(branch[1])->value(); - const bool not_recipricol = (c >= T(0)); - const unsigned int p = static_cast(details::numeric::to_int32(details::numeric::abs(c))); - - node_allocator_->free(branch[1]); - - if (0 == p) - { - details::free_all_nodes(*node_allocator_, branch); - - return node_allocator_->allocate_c(T(1)); - } - else if (not_recipricol) - return cardinal_pow_optimisation_impl(branch[0],p); - else - return cardinal_pow_optimisation_impl(branch[0],p); - } - #else - inline expression_node_ptr cardinal_pow_optimisation(T&, const T&) - { - return error_node(); - } - - inline bool cardinal_pow_optimisable(const details::operator_type&, const T&) - { - return false; - } - - inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr(&)[2]) - { - return error_node(); - } - #endif - - struct synthesize_binary_ext_expression - { - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - const bool left_neg = is_neg_unary_node(branch[0]); - const bool right_neg = is_neg_unary_node(branch[1]); - - if (left_neg && right_neg) - { - if ( - (details::e_add == operation) || - (details::e_sub == operation) || - (details::e_mul == operation) || - (details::e_div == operation) - ) - { - if ( - !expr_gen.parser_->simplify_unary_negation_branch(branch[0]) || - !expr_gen.parser_->simplify_unary_negation_branch(branch[1]) - ) - { - details::free_all_nodes(*expr_gen.node_allocator_,branch); - - return error_node(); - } - } - - switch (operation) - { - // -f(x + 1) + -g(y + 1) --> -(f(x + 1) + g(y + 1)) - case details::e_add : return expr_gen(details::e_neg, - expr_gen.node_allocator_-> - template allocate > > - (branch[0],branch[1])); - - // -f(x + 1) - -g(y + 1) --> g(y + 1) - f(x + 1) - case details::e_sub : return expr_gen.node_allocator_-> - template allocate > > - (branch[1],branch[0]); - - default : break; - } - } - else if (left_neg && !right_neg) - { - if ( - (details::e_add == operation) || - (details::e_sub == operation) || - (details::e_mul == operation) || - (details::e_div == operation) - ) - { - if (!expr_gen.parser_->simplify_unary_negation_branch(branch[0])) - { - details::free_all_nodes(*expr_gen.node_allocator_,branch); - - return error_node(); - } - - switch (operation) - { - // -f(x + 1) + g(y + 1) --> g(y + 1) - f(x + 1) - case details::e_add : return expr_gen.node_allocator_-> - template allocate > > - (branch[1], branch[0]); - - // -f(x + 1) - g(y + 1) --> -(f(x + 1) + g(y + 1)) - case details::e_sub : return expr_gen(details::e_neg, - expr_gen.node_allocator_-> - template allocate > > - (branch[0], branch[1])); - - // -f(x + 1) * g(y + 1) --> -(f(x + 1) * g(y + 1)) - case details::e_mul : return expr_gen(details::e_neg, - expr_gen.node_allocator_-> - template allocate > > - (branch[0], branch[1])); - - // -f(x + 1) / g(y + 1) --> -(f(x + 1) / g(y + 1)) - case details::e_div : return expr_gen(details::e_neg, - expr_gen.node_allocator_-> - template allocate > > - (branch[0], branch[1])); - - default : return error_node(); - } - } - } - else if (!left_neg && right_neg) - { - if ( - (details::e_add == operation) || - (details::e_sub == operation) || - (details::e_mul == operation) || - (details::e_div == operation) - ) - { - if (!expr_gen.parser_->simplify_unary_negation_branch(branch[1])) - { - details::free_all_nodes(*expr_gen.node_allocator_,branch); - - return error_node(); - } - - switch (operation) - { - // f(x + 1) + -g(y + 1) --> f(x + 1) - g(y + 1) - case details::e_add : return expr_gen.node_allocator_-> - template allocate > > - (branch[0], branch[1]); - - // f(x + 1) - - g(y + 1) --> f(x + 1) + g(y + 1) - case details::e_sub : return expr_gen.node_allocator_-> - template allocate > > - (branch[0], branch[1]); - - // f(x + 1) * -g(y + 1) --> -(f(x + 1) * g(y + 1)) - case details::e_mul : return expr_gen(details::e_neg, - expr_gen.node_allocator_-> - template allocate > > - (branch[0], branch[1])); - - // f(x + 1) / -g(y + 1) --> -(f(x + 1) / g(y + 1)) - case details::e_div : return expr_gen(details::e_neg, - expr_gen.node_allocator_-> - template allocate > > - (branch[0], branch[1])); - - default : return error_node(); - } - } - } - - switch (operation) - { - #define case_stmt(op0,op1) \ - case op0 : return expr_gen.node_allocator_-> \ - template allocate > > \ - (branch[0], branch[1]); \ - - basic_opr_switch_statements - extended_opr_switch_statements - #undef case_stmt - default : return error_node(); - } - } - }; - - struct synthesize_vob_expression - { - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - const Type& v = static_cast*>(branch[0])->ref(); - - #ifndef exprtk_disable_enhanced_features - if (details::is_sf3ext_node(branch[1])) - { - expression_node_ptr result = error_node(); - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile_right - (expr_gen, v, operation, branch[1], result); - - if (synthesis_result) - { - free_node(*expr_gen.node_allocator_,branch[1]); - return result; - } - } - #endif - - if ( - (details::e_mul == operation) || - (details::e_div == operation) - ) - { - if (details::is_uv_node(branch[1])) - { - typedef details::uv_base_node* uvbn_ptr_t; - - details::operator_type o = static_cast(branch[1])->operation(); - - if (details::e_neg == o) - { - const Type& v1 = static_cast(branch[1])->v(); - - free_node(*expr_gen.node_allocator_,branch[1]); - - switch (operation) - { - case details::e_mul : return expr_gen(details::e_neg, - expr_gen.node_allocator_-> - template allocate_rr > >(v,v1)); - - case details::e_div : return expr_gen(details::e_neg, - expr_gen.node_allocator_-> - template allocate_rr > >(v,v1)); - - default : break; - } - } - } - } - - switch (operation) - { - #define case_stmt(op0,op1) \ - case op0 : return expr_gen.node_allocator_-> \ - template allocate_rc > > \ - (v, branch[1]); \ - - basic_opr_switch_statements - extended_opr_switch_statements - #undef case_stmt - default : return error_node(); - } - } - }; - - struct synthesize_bov_expression - { - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - const Type& v = static_cast*>(branch[1])->ref(); - - #ifndef exprtk_disable_enhanced_features - if (details::is_sf3ext_node(branch[0])) - { - expression_node_ptr result = error_node(); - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile_left - (expr_gen, v, operation, branch[0], result); - - if (synthesis_result) - { - free_node(*expr_gen.node_allocator_, branch[0]); - - return result; - } - } - #endif - - if ( - (details::e_add == operation) || - (details::e_sub == operation) || - (details::e_mul == operation) || - (details::e_div == operation) - ) - { - if (details::is_uv_node(branch[0])) - { - typedef details::uv_base_node* uvbn_ptr_t; - - details::operator_type o = static_cast(branch[0])->operation(); - - if (details::e_neg == o) - { - const Type& v0 = static_cast(branch[0])->v(); - - free_node(*expr_gen.node_allocator_,branch[0]); - - switch (operation) - { - case details::e_add : return expr_gen.node_allocator_-> - template allocate_rr > >(v,v0); - - case details::e_sub : return expr_gen(details::e_neg, - expr_gen.node_allocator_-> - template allocate_rr > >(v0,v)); - - case details::e_mul : return expr_gen(details::e_neg, - expr_gen.node_allocator_-> - template allocate_rr > >(v0,v)); - - case details::e_div : return expr_gen(details::e_neg, - expr_gen.node_allocator_-> - template allocate_rr > >(v0,v)); - default : break; - } - } - } - } - - switch (operation) - { - #define case_stmt(op0,op1) \ - case op0 : return expr_gen.node_allocator_-> \ - template allocate_cr > > \ - (branch[0], v); \ - - basic_opr_switch_statements - extended_opr_switch_statements - #undef case_stmt - default : return error_node(); - } - } - }; - - struct synthesize_cob_expression - { - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - const Type c = static_cast*>(branch[0])->value(); - - free_node(*expr_gen.node_allocator_,branch[0]); - - if (std::equal_to()(T(0),c) && (details::e_mul == operation)) - { - free_node(*expr_gen.node_allocator_,branch[1]); - - return expr_gen(T(0)); - } - else if (std::equal_to()(T(0),c) && (details::e_div == operation)) - { - free_node(*expr_gen.node_allocator_, branch[1]); - - return expr_gen(T(0)); - } - else if (std::equal_to()(T(0),c) && (details::e_add == operation)) - return branch[1]; - else if (std::equal_to()(T(1),c) && (details::e_mul == operation)) - return branch[1]; - - if (details::is_cob_node(branch[1])) - { - // Simplify expressions of the form: - // 1. (1 * (2 * (3 * (4 * (5 * (6 * (7 * (8 * (9 + x))))))))) --> 40320 * (9 + x) - // 2. (1 + (2 + (3 + (4 + (5 + (6 + (7 + (8 + (9 + x))))))))) --> 45 + x - if ( - (operation == details::e_mul) || - (operation == details::e_add) - ) - { - details::cob_base_node* cobnode = static_cast*>(branch[1]); - - if (operation == cobnode->operation()) - { - switch (operation) - { - case details::e_add : cobnode->set_c(c + cobnode->c()); break; - case details::e_mul : cobnode->set_c(c * cobnode->c()); break; - default : return error_node(); - } - - return cobnode; - } - } - - if (operation == details::e_mul) - { - details::cob_base_node* cobnode = static_cast*>(branch[1]); - details::operator_type cob_opr = cobnode->operation(); - - if ( - (details::e_div == cob_opr) || - (details::e_mul == cob_opr) - ) - { - switch (cob_opr) - { - case details::e_div : cobnode->set_c(c * cobnode->c()); break; - case details::e_mul : cobnode->set_c(cobnode->c() / c); break; - default : return error_node(); - } - - return cobnode; - } - } - else if (operation == details::e_div) - { - details::cob_base_node* cobnode = static_cast*>(branch[1]); - details::operator_type cob_opr = cobnode->operation(); - - if ( - (details::e_div == cob_opr) || - (details::e_mul == cob_opr) - ) - { - details::expression_node* new_cobnode = error_node(); - - switch (cob_opr) - { - case details::e_div : new_cobnode = expr_gen.node_allocator_-> - template allocate_tt > > - (c / cobnode->c(), cobnode->move_branch(0)); - break; - - case details::e_mul : new_cobnode = expr_gen.node_allocator_-> - template allocate_tt > > - (c / cobnode->c(), cobnode->move_branch(0)); - break; - - default : return error_node(); - } - - free_node(*expr_gen.node_allocator_,branch[1]); - - return new_cobnode; - } - } - } - #ifndef exprtk_disable_enhanced_features - else if (details::is_sf3ext_node(branch[1])) - { - expression_node_ptr result = error_node(); - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile_right - (expr_gen, c, operation, branch[1], result); - - if (synthesis_result) - { - free_node(*expr_gen.node_allocator_,branch[1]); - - return result; - } - } - #endif - - switch (operation) - { - #define case_stmt(op0,op1) \ - case op0 : return expr_gen.node_allocator_-> \ - template allocate_tt > > \ - (c, branch[1]); \ - - basic_opr_switch_statements - extended_opr_switch_statements - #undef case_stmt - default : return error_node(); - } - } - }; - - struct synthesize_boc_expression - { - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - const Type c = static_cast*>(branch[1])->value(); - - details::free_node(*(expr_gen.node_allocator_), branch[1]); - - if (std::equal_to()(T(0),c) && (details::e_mul == operation)) - { - free_node(*expr_gen.node_allocator_, branch[0]); - - return expr_gen(T(0)); - } - else if (std::equal_to()(T(0),c) && (details::e_div == operation)) - { - free_node(*expr_gen.node_allocator_, branch[0]); - - return expr_gen(std::numeric_limits::quiet_NaN()); - } - else if (std::equal_to()(T(0),c) && (details::e_add == operation)) - return branch[0]; - else if (std::equal_to()(T(1),c) && (details::e_mul == operation)) - return branch[0]; - - if (details::is_boc_node(branch[0])) - { - // Simplify expressions of the form: - // 1. (((((((((x + 9) * 8) * 7) * 6) * 5) * 4) * 3) * 2) * 1) --> (x + 9) * 40320 - // 2. (((((((((x + 9) + 8) + 7) + 6) + 5) + 4) + 3) + 2) + 1) --> x + 45 - if ( - (operation == details::e_mul) || - (operation == details::e_add) - ) - { - details::boc_base_node* bocnode = static_cast*>(branch[0]); - - if (operation == bocnode->operation()) - { - switch (operation) - { - case details::e_add : bocnode->set_c(c + bocnode->c()); break; - case details::e_mul : bocnode->set_c(c * bocnode->c()); break; - default : return error_node(); - } - - return bocnode; - } - } - else if (operation == details::e_div) - { - details::boc_base_node* bocnode = static_cast*>(branch[0]); - details::operator_type boc_opr = bocnode->operation(); - - if ( - (details::e_div == boc_opr) || - (details::e_mul == boc_opr) - ) - { - switch (boc_opr) - { - case details::e_div : bocnode->set_c(c * bocnode->c()); break; - case details::e_mul : bocnode->set_c(bocnode->c() / c); break; - default : return error_node(); - } - - return bocnode; - } - } - else if (operation == details::e_pow) - { - // (v ^ c0) ^ c1 --> v ^(c0 * c1) - details::boc_base_node* bocnode = static_cast*>(branch[0]); - details::operator_type boc_opr = bocnode->operation(); - - if (details::e_pow == boc_opr) - { - bocnode->set_c(bocnode->c() * c); - - return bocnode; - } - } - } - - #ifndef exprtk_disable_enhanced_features - if (details::is_sf3ext_node(branch[0])) - { - expression_node_ptr result = error_node(); - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile_left - (expr_gen, c, operation, branch[0], result); - - if (synthesis_result) - { - free_node(*expr_gen.node_allocator_, branch[0]); - - return result; - } - } - #endif - - switch (operation) - { - #define case_stmt(op0,op1) \ - case op0 : return expr_gen.node_allocator_-> \ - template allocate_cr > > \ - (branch[0], c); \ - - basic_opr_switch_statements - extended_opr_switch_statements - #undef case_stmt - default : return error_node(); - } - } - }; - - struct synthesize_cocob_expression - { - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - expression_node_ptr result = error_node(); - - // (cob) o c --> cob - if (details::is_cob_node(branch[0])) - { - details::cob_base_node* cobnode = static_cast*>(branch[0]); - - const Type c = static_cast*>(branch[1])->value(); - - if (std::equal_to()(T(0),c) && (details::e_mul == operation)) - { - free_node(*expr_gen.node_allocator_, branch[0]); - free_node(*expr_gen.node_allocator_, branch[1]); - - return expr_gen(T(0)); - } - else if (std::equal_to()(T(0),c) && (details::e_div == operation)) - { - free_node(*expr_gen.node_allocator_, branch[0]); - free_node(*expr_gen.node_allocator_, branch[1]); - - return expr_gen(T(std::numeric_limits::quiet_NaN())); - } - else if (std::equal_to()(T(0),c) && (details::e_add == operation)) - { - free_node(*expr_gen.node_allocator_, branch[1]); - - return branch[0]; - } - else if (std::equal_to()(T(1),c) && (details::e_mul == operation)) - { - free_node(*expr_gen.node_allocator_, branch[1]); - - return branch[0]; - } - else if (std::equal_to()(T(1),c) && (details::e_div == operation)) - { - free_node(*expr_gen.node_allocator_, branch[1]); - - return branch[0]; - } - - const bool op_addsub = (details::e_add == cobnode->operation()) || - (details::e_sub == cobnode->operation()) ; - - if (op_addsub) - { - switch (operation) - { - case details::e_add : cobnode->set_c(cobnode->c() + c); break; - case details::e_sub : cobnode->set_c(cobnode->c() - c); break; - default : return error_node(); - } - - result = cobnode; - } - else if (details::e_mul == cobnode->operation()) - { - switch (operation) - { - case details::e_mul : cobnode->set_c(cobnode->c() * c); break; - case details::e_div : cobnode->set_c(cobnode->c() / c); break; - default : return error_node(); - } - - result = cobnode; - } - else if (details::e_div == cobnode->operation()) - { - if (details::e_mul == operation) - { - cobnode->set_c(cobnode->c() * c); - result = cobnode; - } - else if (details::e_div == operation) - { - result = expr_gen.node_allocator_-> - template allocate_tt > > - (cobnode->c() / c, cobnode->move_branch(0)); - - free_node(*expr_gen.node_allocator_, branch[0]); - } - } - - if (result) - { - free_node(*expr_gen.node_allocator_,branch[1]); - } - } - - // c o (cob) --> cob - else if (details::is_cob_node(branch[1])) - { - details::cob_base_node* cobnode = static_cast*>(branch[1]); - - const Type c = static_cast*>(branch[0])->value(); - - if (std::equal_to()(T(0),c) && (details::e_mul == operation)) - { - free_node(*expr_gen.node_allocator_, branch[0]); - free_node(*expr_gen.node_allocator_, branch[1]); - - return expr_gen(T(0)); - } - else if (std::equal_to()(T(0),c) && (details::e_div == operation)) - { - free_node(*expr_gen.node_allocator_, branch[0]); - free_node(*expr_gen.node_allocator_, branch[1]); - - return expr_gen(T(0)); - } - else if (std::equal_to()(T(0),c) && (details::e_add == operation)) - { - free_node(*expr_gen.node_allocator_, branch[0]); - - return branch[1]; - } - else if (std::equal_to()(T(1),c) && (details::e_mul == operation)) - { - free_node(*expr_gen.node_allocator_, branch[0]); - - return branch[1]; - } - - if (details::e_add == cobnode->operation()) - { - if (details::e_add == operation) - { - cobnode->set_c(c + cobnode->c()); - result = cobnode; - } - else if (details::e_sub == operation) - { - result = expr_gen.node_allocator_-> - template allocate_tt > > - (c - cobnode->c(), cobnode->move_branch(0)); - - free_node(*expr_gen.node_allocator_,branch[1]); - } - } - else if (details::e_sub == cobnode->operation()) - { - if (details::e_add == operation) - { - cobnode->set_c(c + cobnode->c()); - result = cobnode; - } - else if (details::e_sub == operation) - { - result = expr_gen.node_allocator_-> - template allocate_tt > > - (c - cobnode->c(), cobnode->move_branch(0)); - - free_node(*expr_gen.node_allocator_,branch[1]); - } - } - else if (details::e_mul == cobnode->operation()) - { - if (details::e_mul == operation) - { - cobnode->set_c(c * cobnode->c()); - result = cobnode; - } - else if (details::e_div == operation) - { - result = expr_gen.node_allocator_-> - template allocate_tt > > - (c / cobnode->c(), cobnode->move_branch(0)); - - free_node(*expr_gen.node_allocator_,branch[1]); - } - } - else if (details::e_div == cobnode->operation()) - { - if (details::e_mul == operation) - { - cobnode->set_c(c * cobnode->c()); - result = cobnode; - } - else if (details::e_div == operation) - { - result = expr_gen.node_allocator_-> - template allocate_tt > > - (c / cobnode->c(), cobnode->move_branch(0)); - - free_node(*expr_gen.node_allocator_,branch[1]); - } - } - - if (result) - { - free_node(*expr_gen.node_allocator_,branch[0]); - } - } - - return result; - } - }; - - struct synthesize_coboc_expression - { - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - expression_node_ptr result = error_node(); - - // (boc) o c --> boc - if (details::is_boc_node(branch[0])) - { - details::boc_base_node* bocnode = static_cast*>(branch[0]); - - const Type c = static_cast*>(branch[1])->value(); - - if (details::e_add == bocnode->operation()) - { - switch (operation) - { - case details::e_add : bocnode->set_c(bocnode->c() + c); break; - case details::e_sub : bocnode->set_c(bocnode->c() - c); break; - default : return error_node(); - } - - result = bocnode; - } - else if (details::e_mul == bocnode->operation()) - { - switch (operation) - { - case details::e_mul : bocnode->set_c(bocnode->c() * c); break; - case details::e_div : bocnode->set_c(bocnode->c() / c); break; - default : return error_node(); - } - - result = bocnode; - } - else if (details::e_sub == bocnode->operation()) - { - if (details::e_add == operation) - { - result = expr_gen.node_allocator_-> - template allocate_tt > > - (bocnode->move_branch(0), c - bocnode->c()); - - free_node(*expr_gen.node_allocator_,branch[0]); - } - else if (details::e_sub == operation) - { - bocnode->set_c(bocnode->c() + c); - result = bocnode; - } - } - else if (details::e_div == bocnode->operation()) - { - switch (operation) - { - case details::e_div : bocnode->set_c(bocnode->c() * c); break; - case details::e_mul : bocnode->set_c(bocnode->c() / c); break; - default : return error_node(); - } - - result = bocnode; - } - - if (result) - { - free_node(*expr_gen.node_allocator_, branch[1]); - } - } - - // c o (boc) --> boc - else if (details::is_boc_node(branch[1])) - { - details::boc_base_node* bocnode = static_cast*>(branch[1]); - - const Type c = static_cast*>(branch[0])->value(); - - if (details::e_add == bocnode->operation()) - { - if (details::e_add == operation) - { - bocnode->set_c(c + bocnode->c()); - result = bocnode; - } - else if (details::e_sub == operation) - { - result = expr_gen.node_allocator_-> - template allocate_tt > > - (c - bocnode->c(), bocnode->move_branch(0)); - - free_node(*expr_gen.node_allocator_,branch[1]); - } - } - else if (details::e_sub == bocnode->operation()) - { - if (details::e_add == operation) - { - result = expr_gen.node_allocator_-> - template allocate_tt > > - (bocnode->move_branch(0), c - bocnode->c()); - - free_node(*expr_gen.node_allocator_,branch[1]); - } - else if (details::e_sub == operation) - { - result = expr_gen.node_allocator_-> - template allocate_tt > > - (c + bocnode->c(), bocnode->move_branch(0)); - - free_node(*expr_gen.node_allocator_,branch[1]); - } - } - else if (details::e_mul == bocnode->operation()) - { - if (details::e_mul == operation) - { - bocnode->set_c(c * bocnode->c()); - result = bocnode; - } - else if (details::e_div == operation) - { - result = expr_gen.node_allocator_-> - template allocate_tt > > - (c / bocnode->c(), bocnode->move_branch(0)); - - free_node(*expr_gen.node_allocator_,branch[1]); - } - } - else if (details::e_div == bocnode->operation()) - { - if (details::e_mul == operation) - { - bocnode->set_c(bocnode->c() / c); - result = bocnode; - } - else if (details::e_div == operation) - { - result = expr_gen.node_allocator_-> - template allocate_tt > > - (c * bocnode->c(), bocnode->move_branch(0)); - - free_node(*expr_gen.node_allocator_,branch[1]); - } - } - - if (result) - { - free_node(*expr_gen.node_allocator_,branch[0]); - } - } - - return result; - } - }; - - #ifndef exprtk_disable_enhanced_features - inline bool synthesize_expression(const details::operator_type& operation, - expression_node_ptr (&branch)[2], - expression_node_ptr& result) - { - result = error_node(); - - if (!operation_optimisable(operation)) - return false; - - const std::string node_id = branch_to_id(branch); - - const typename synthesize_map_t::iterator itr = synthesize_map_.find(node_id); - - if (synthesize_map_.end() != itr) - { - result = itr->second((*this), operation, branch); - - return true; - } - else - return false; - } - - struct synthesize_vov_expression - { - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - const Type& v1 = static_cast*>(branch[0])->ref(); - const Type& v2 = static_cast*>(branch[1])->ref(); - - switch (operation) - { - #define case_stmt(op0,op1) \ - case op0 : return expr_gen.node_allocator_-> \ - template allocate_rr > > \ - (v1, v2); \ - - basic_opr_switch_statements - extended_opr_switch_statements - #undef case_stmt - default : return error_node(); - } - } - }; - - struct synthesize_cov_expression - { - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - const Type c = static_cast*> (branch[0])->value(); - const Type& v = static_cast*>(branch[1])->ref (); - - details::free_node(*(expr_gen.node_allocator_),branch[0]); - - if (std::equal_to()(T(0),c) && (details::e_mul == operation)) - return expr_gen(T(0)); - else if (std::equal_to()(T(0),c) && (details::e_div == operation)) - return expr_gen(T(0)); - else if (std::equal_to()(T(0),c) && (details::e_add == operation)) - return static_cast*>(branch[1]); - else if (std::equal_to()(T(1),c) && (details::e_mul == operation)) - return static_cast*>(branch[1]); - - switch (operation) - { - #define case_stmt(op0,op1) \ - case op0 : return expr_gen.node_allocator_-> \ - template allocate_cr > > \ - (c, v); \ - - basic_opr_switch_statements - extended_opr_switch_statements - #undef case_stmt - default : return error_node(); - } - } - }; - - struct synthesize_voc_expression - { - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - const Type& v = static_cast*>(branch[0])->ref (); - const Type c = static_cast*> (branch[1])->value(); - - details::free_node(*(expr_gen.node_allocator_), branch[1]); - - if (expr_gen.cardinal_pow_optimisable(operation,c)) - { - if (std::equal_to()(T(1),c)) - return branch[0]; - else - return expr_gen.cardinal_pow_optimisation(v,c); - } - else if (std::equal_to()(T(0),c) && (details::e_mul == operation)) - return expr_gen(T(0)); - else if (std::equal_to()(T(0),c) && (details::e_div == operation)) - return expr_gen(std::numeric_limits::quiet_NaN()); - else if (std::equal_to()(T(0),c) && (details::e_add == operation)) - return static_cast*>(branch[0]); - else if (std::equal_to()(T(1),c) && (details::e_mul == operation)) - return static_cast*>(branch[0]); - else if (std::equal_to()(T(1),c) && (details::e_div == operation)) - return static_cast*>(branch[0]); - - switch (operation) - { - #define case_stmt(op0,op1) \ - case op0 : return expr_gen.node_allocator_-> \ - template allocate_rc > > \ - (v, c); \ - - basic_opr_switch_statements - extended_opr_switch_statements - #undef case_stmt - default : return error_node(); - } - } - }; - - struct synthesize_sf3ext_expression - { - template - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& sf3opr, - T0 t0, T1 t1, T2 t2) - { - switch (sf3opr) - { - #define case_stmt(op) \ - case details::e_sf##op : return details::T0oT1oT2_sf3ext >:: \ - allocate(*(expr_gen.node_allocator_), t0, t1, t2); \ - - case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03) - case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07) - case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11) - case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15) - case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19) - case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23) - case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27) - case_stmt(28) case_stmt(29) case_stmt(30) - #undef case_stmt - default : return error_node(); - } - } - - template - static inline bool compile(expression_generator& expr_gen, const std::string& id, - T0 t0, T1 t1, T2 t2, - expression_node_ptr& result) - { - details::operator_type sf3opr; - - if (!expr_gen.sf3_optimisable(id,sf3opr)) - return false; - else - result = synthesize_sf3ext_expression::template process - (expr_gen, sf3opr, t0, t1, t2); - - return true; - } - }; - - struct synthesize_sf4ext_expression - { - template - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& sf4opr, - T0 t0, T1 t1, T2 t2, T3 t3) - { - switch (sf4opr) - { - #define case_stmt0(op) \ - case details::e_sf##op : return details::T0oT1oT2oT3_sf4ext >:: \ - allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3); \ - - - #define case_stmt1(op) \ - case details::e_sf4ext##op : return details::T0oT1oT2oT3_sf4ext >:: \ - allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3); \ - - case_stmt0(48) case_stmt0(49) case_stmt0(50) case_stmt0(51) - case_stmt0(52) case_stmt0(53) case_stmt0(54) case_stmt0(55) - case_stmt0(56) case_stmt0(57) case_stmt0(58) case_stmt0(59) - case_stmt0(60) case_stmt0(61) case_stmt0(62) case_stmt0(63) - case_stmt0(64) case_stmt0(65) case_stmt0(66) case_stmt0(67) - case_stmt0(68) case_stmt0(69) case_stmt0(70) case_stmt0(71) - case_stmt0(72) case_stmt0(73) case_stmt0(74) case_stmt0(75) - case_stmt0(76) case_stmt0(77) case_stmt0(78) case_stmt0(79) - case_stmt0(80) case_stmt0(81) case_stmt0(82) case_stmt0(83) - - case_stmt1(00) case_stmt1(01) case_stmt1(02) case_stmt1(03) - case_stmt1(04) case_stmt1(05) case_stmt1(06) case_stmt1(07) - case_stmt1(08) case_stmt1(09) case_stmt1(10) case_stmt1(11) - case_stmt1(12) case_stmt1(13) case_stmt1(14) case_stmt1(15) - case_stmt1(16) case_stmt1(17) case_stmt1(18) case_stmt1(19) - case_stmt1(20) case_stmt1(21) case_stmt1(22) case_stmt1(23) - case_stmt1(24) case_stmt1(25) case_stmt1(26) case_stmt1(27) - case_stmt1(28) case_stmt1(29) case_stmt1(30) case_stmt1(31) - case_stmt1(32) case_stmt1(33) case_stmt1(34) case_stmt1(35) - case_stmt1(36) case_stmt1(37) case_stmt1(38) case_stmt1(39) - case_stmt1(40) case_stmt1(41) case_stmt1(42) case_stmt1(43) - case_stmt1(44) case_stmt1(45) case_stmt1(46) case_stmt1(47) - case_stmt1(48) case_stmt1(49) case_stmt1(50) case_stmt1(51) - case_stmt1(52) case_stmt1(53) case_stmt1(54) case_stmt1(55) - case_stmt1(56) case_stmt1(57) case_stmt1(58) case_stmt1(59) - case_stmt1(60) case_stmt1(61) - - #undef case_stmt0 - #undef case_stmt1 - default : return error_node(); - } - } - - template - static inline bool compile(expression_generator& expr_gen, const std::string& id, - T0 t0, T1 t1, T2 t2, T3 t3, - expression_node_ptr& result) - { - details::operator_type sf4opr; - - if (!expr_gen.sf4_optimisable(id,sf4opr)) - return false; - else - result = synthesize_sf4ext_expression::template process - (expr_gen, sf4opr, t0, t1, t2, t3); - - return true; - } - - // T o (sf3ext) - template - static inline bool compile_right(expression_generator& expr_gen, - ExternalType t, - const details::operator_type& operation, - expression_node_ptr& sf3node, - expression_node_ptr& result) - { - if (!details::is_sf3ext_node(sf3node)) - return false; - - typedef details::T0oT1oT2_base_node* sf3ext_base_ptr; - - sf3ext_base_ptr n = static_cast(sf3node); - const std::string id = "t" + expr_gen.to_str(operation) + "(" + n->type_id() + ")"; - - switch (n->type()) - { - case details::expression_node::e_covoc : return compile_right_impl - - (expr_gen, id, t, sf3node, result); - - case details::expression_node::e_covov : return compile_right_impl - - (expr_gen, id, t, sf3node, result); - - case details::expression_node::e_vocov : return compile_right_impl - - (expr_gen, id, t, sf3node, result); - - case details::expression_node::e_vovoc : return compile_right_impl - - (expr_gen, id, t, sf3node, result); - - case details::expression_node::e_vovov : return compile_right_impl - - (expr_gen, id, t, sf3node, result); - - default : return false; - } - } - - // (sf3ext) o T - template - static inline bool compile_left(expression_generator& expr_gen, - ExternalType t, - const details::operator_type& operation, - expression_node_ptr& sf3node, - expression_node_ptr& result) - { - if (!details::is_sf3ext_node(sf3node)) - return false; - - typedef details::T0oT1oT2_base_node* sf3ext_base_ptr; - - sf3ext_base_ptr n = static_cast(sf3node); - - const std::string id = "(" + n->type_id() + ")" + expr_gen.to_str(operation) + "t"; - - switch (n->type()) - { - case details::expression_node::e_covoc : return compile_left_impl - - (expr_gen, id, t, sf3node, result); - - case details::expression_node::e_covov : return compile_left_impl - - (expr_gen, id, t, sf3node, result); - - case details::expression_node::e_vocov : return compile_left_impl - - (expr_gen, id, t, sf3node, result); - - case details::expression_node::e_vovoc : return compile_left_impl - - (expr_gen, id, t, sf3node, result); - - case details::expression_node::e_vovov : return compile_left_impl - - (expr_gen, id, t, sf3node, result); - - default : return false; - } - } - - template - static inline bool compile_right_impl(expression_generator& expr_gen, - const std::string& id, - ExternalType t, - expression_node_ptr& node, - expression_node_ptr& result) - { - SF3TypeNode* n = dynamic_cast(node); - - if (n) - { - T0 t0 = n->t0(); - T1 t1 = n->t1(); - T2 t2 = n->t2(); - - return synthesize_sf4ext_expression::template compile - (expr_gen, id, t, t0, t1, t2, result); - } - else - return false; - } - - template - static inline bool compile_left_impl(expression_generator& expr_gen, - const std::string& id, - ExternalType t, - expression_node_ptr& node, - expression_node_ptr& result) - { - SF3TypeNode* n = dynamic_cast(node); - - if (n) - { - T0 t0 = n->t0(); - T1 t1 = n->t1(); - T2 t2 = n->t2(); - - return synthesize_sf4ext_expression::template compile - (expr_gen, id, t0, t1, t2, t, result); - } - else - return false; - } - }; - - struct synthesize_vovov_expression0 - { - typedef typename vovov_t::type0 node_type; - typedef typename vovov_t::sf3_type sf3_type; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // (v0 o0 v1) o1 (v2) - const details::vov_base_node* vov = static_cast*>(branch[0]); - const Type& v0 = vov->v0(); - const Type& v1 = vov->v1(); - const Type& v2 = static_cast*>(branch[1])->ref(); - const details::operator_type o0 = vov->operation(); - const details::operator_type o1 = operation; - - binary_functor_t f0 = reinterpret_cast(0); - binary_functor_t f1 = reinterpret_cast(0); - - details::free_node(*(expr_gen.node_allocator_),branch[0]); - - expression_node_ptr result = error_node(); - - if (expr_gen.parser_->settings_.strength_reduction_enabled()) - { - // (v0 / v1) / v2 --> (vovov) v0 / (v1 * v2) - if ((details::e_div == o0) && (details::e_div == o1)) - { - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, "t/(t*t)", v0, v1, v2, result); - - exprtk_debug(("(v0 / v1) / v2 --> (vovov) v0 / (v1 * v2)\n")); - - return (synthesis_result) ? result : error_node(); - } - } - - const bool synthesis_result = - synthesize_sf3ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1), v0, v1, v2, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o0,f0)) - return error_node(); - else if (!expr_gen.valid_operator(o1,f1)) - return error_node(); - else - return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, f0, f1); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1) - { - return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "t"; - } - }; - - struct synthesize_vovov_expression1 - { - typedef typename vovov_t::type1 node_type; - typedef typename vovov_t::sf3_type sf3_type; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // (v0) o0 (v1 o1 v2) - const details::vov_base_node* vov = static_cast*>(branch[1]); - const Type& v0 = static_cast*>(branch[0])->ref(); - const Type& v1 = vov->v0(); - const Type& v2 = vov->v1(); - const details::operator_type o0 = operation; - const details::operator_type o1 = vov->operation(); - - binary_functor_t f0 = reinterpret_cast(0); - binary_functor_t f1 = reinterpret_cast(0); - - details::free_node(*(expr_gen.node_allocator_),branch[1]); - - expression_node_ptr result = error_node(); - - if (expr_gen.parser_->settings_.strength_reduction_enabled()) - { - // v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1 - if ((details::e_div == o0) && (details::e_div == o1)) - { - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, "(t*t)/t", v0, v2, v1, result); - - exprtk_debug(("v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1\n")); - - return (synthesis_result) ? result : error_node(); - } - } - - const bool synthesis_result = - synthesize_sf3ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1), v0, v1, v2, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o0,f0)) - return error_node(); - else if (!expr_gen.valid_operator(o1,f1)) - return error_node(); - else - return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, f0, f1); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1) - { - return details::build_string() - << "t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "t)"; - } - }; - - struct synthesize_vovoc_expression0 - { - typedef typename vovoc_t::type0 node_type; - typedef typename vovoc_t::sf3_type sf3_type; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // (v0 o0 v1) o1 (c) - const details::vov_base_node* vov = static_cast*>(branch[0]); - const Type& v0 = vov->v0(); - const Type& v1 = vov->v1(); - const Type c = static_cast*>(branch[1])->value(); - const details::operator_type o0 = vov->operation(); - const details::operator_type o1 = operation; - - binary_functor_t f0 = reinterpret_cast(0); - binary_functor_t f1 = reinterpret_cast(0); - - details::free_node(*(expr_gen.node_allocator_),branch[0]); - details::free_node(*(expr_gen.node_allocator_),branch[1]); - - expression_node_ptr result = error_node(); - - if (expr_gen.parser_->settings_.strength_reduction_enabled()) - { - // (v0 / v1) / c --> (vovoc) v0 / (v1 * c) - if ((details::e_div == o0) && (details::e_div == o1)) - { - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, "t/(t*t)", v0, v1, c, result); - - exprtk_debug(("(v0 / v1) / c --> (vovoc) v0 / (v1 * c)\n")); - - return (synthesis_result) ? result : error_node(); - } - } - - const bool synthesis_result = - synthesize_sf3ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1), v0, v1, c, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o0,f0)) - return error_node(); - else if (!expr_gen.valid_operator(o1,f1)) - return error_node(); - else - return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, f0, f1); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1) - { - return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "t"; - } - }; - - struct synthesize_vovoc_expression1 - { - typedef typename vovoc_t::type1 node_type; - typedef typename vovoc_t::sf3_type sf3_type; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // (v0) o0 (v1 o1 c) - const details::voc_base_node* voc = static_cast*>(branch[1]); - const Type& v0 = static_cast*>(branch[0])->ref(); - const Type& v1 = voc->v(); - const Type c = voc->c(); - const details::operator_type o0 = operation; - const details::operator_type o1 = voc->operation(); - - binary_functor_t f0 = reinterpret_cast(0); - binary_functor_t f1 = reinterpret_cast(0); - - details::free_node(*(expr_gen.node_allocator_),branch[1]); - - expression_node_ptr result = error_node(); - - if (expr_gen.parser_->settings_.strength_reduction_enabled()) - { - // v0 / (v1 / c) --> (vocov) (v0 * c) / v1 - if ((details::e_div == o0) && (details::e_div == o1)) - { - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, "(t*t)/t", v0, c, v1, result); - - exprtk_debug(("v0 / (v1 / c) --> (vocov) (v0 * c) / v1\n")); - - return (synthesis_result) ? result : error_node(); - } - } - - const bool synthesis_result = - synthesize_sf3ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1), v0, v1, c, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o0,f0)) - return error_node(); - else if (!expr_gen.valid_operator(o1,f1)) - return error_node(); - else - return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, f0, f1); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1) - { - return details::build_string() - << "t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "t)"; - } - }; - - struct synthesize_vocov_expression0 - { - typedef typename vocov_t::type0 node_type; - typedef typename vocov_t::sf3_type sf3_type; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // (v0 o0 c) o1 (v1) - const details::voc_base_node* voc = static_cast*>(branch[0]); - const Type& v0 = voc->v(); - const Type c = voc->c(); - const Type& v1 = static_cast*>(branch[1])->ref(); - const details::operator_type o0 = voc->operation(); - const details::operator_type o1 = operation; - - binary_functor_t f0 = reinterpret_cast(0); - binary_functor_t f1 = reinterpret_cast(0); - - details::free_node(*(expr_gen.node_allocator_),branch[0]); - - expression_node_ptr result = error_node(); - - if (expr_gen.parser_->settings_.strength_reduction_enabled()) - { - // (v0 / c) / v1 --> (vovoc) v0 / (v1 * c) - if ((details::e_div == o0) && (details::e_div == o1)) - { - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, "t/(t*t)", v0, v1, c, result); - - exprtk_debug(("(v0 / c) / v1 --> (vovoc) v0 / (v1 * c)\n")); - - return (synthesis_result) ? result : error_node(); - } - } - - const bool synthesis_result = - synthesize_sf3ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1), v0, c, v1, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o0,f0)) - return error_node(); - else if (!expr_gen.valid_operator(o1,f1)) - return error_node(); - else - return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, f0, f1); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1) - { - return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "t"; - } - }; - - struct synthesize_vocov_expression1 - { - typedef typename vocov_t::type1 node_type; - typedef typename vocov_t::sf3_type sf3_type; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // (v0) o0 (c o1 v1) - const details::cov_base_node* cov = static_cast*>(branch[1]); - const Type& v0 = static_cast*>(branch[0])->ref(); - const Type c = cov->c(); - const Type& v1 = cov->v(); - const details::operator_type o0 = operation; - const details::operator_type o1 = cov->operation(); - - binary_functor_t f0 = reinterpret_cast(0); - binary_functor_t f1 = reinterpret_cast(0); - - details::free_node(*(expr_gen.node_allocator_),branch[1]); - - expression_node_ptr result = error_node(); - - if (expr_gen.parser_->settings_.strength_reduction_enabled()) - { - // v0 / (c / v1) --> (vovoc) (v0 * v1) / c - if ((details::e_div == o0) && (details::e_div == o1)) - { - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, "(t*t)/t", v0, v1, c, result); - - exprtk_debug(("v0 / (c / v1) --> (vovoc) (v0 * v1) / c\n")); - - return (synthesis_result) ? result : error_node(); - } - } - - const bool synthesis_result = - synthesize_sf3ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1), v0, c, v1, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o0,f0)) - return error_node(); - else if (!expr_gen.valid_operator(o1,f1)) - return error_node(); - else - return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, f0, f1); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1) - { - return details::build_string() - << "t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "t)"; - } - }; - - struct synthesize_covov_expression0 - { - typedef typename covov_t::type0 node_type; - typedef typename covov_t::sf3_type sf3_type; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // (c o0 v0) o1 (v1) - const details::cov_base_node* cov = static_cast*>(branch[0]); - const Type c = cov->c(); - const Type& v0 = cov->v(); - const Type& v1 = static_cast*>(branch[1])->ref(); - const details::operator_type o0 = cov->operation(); - const details::operator_type o1 = operation; - - binary_functor_t f0 = reinterpret_cast(0); - binary_functor_t f1 = reinterpret_cast(0); - - details::free_node(*(expr_gen.node_allocator_),branch[0]); - - expression_node_ptr result = error_node(); - - if (expr_gen.parser_->settings_.strength_reduction_enabled()) - { - // (c / v0) / v1 --> (covov) c / (v0 * v1) - if ((details::e_div == o0) && (details::e_div == o1)) - { - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, "t/(t*t)", c, v0, v1, result); - - exprtk_debug(("(c / v0) / v1 --> (covov) c / (v0 * v1)\n")); - - return (synthesis_result) ? result : error_node(); - } - } - - const bool synthesis_result = - synthesize_sf3ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1), c, v0, v1, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o0,f0)) - return error_node(); - else if (!expr_gen.valid_operator(o1,f1)) - return error_node(); - else - return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, f0, f1); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1) - { - return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "t"; - } - }; - - struct synthesize_covov_expression1 - { - typedef typename covov_t::type1 node_type; - typedef typename covov_t::sf3_type sf3_type; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // (c) o0 (v0 o1 v1) - const details::vov_base_node* vov = static_cast*>(branch[1]); - const Type c = static_cast*>(branch[0])->value(); - const Type& v0 = vov->v0(); - const Type& v1 = vov->v1(); - const details::operator_type o0 = operation; - const details::operator_type o1 = vov->operation(); - - binary_functor_t f0 = reinterpret_cast(0); - binary_functor_t f1 = reinterpret_cast(0); - - details::free_node(*(expr_gen.node_allocator_),branch[0]); - details::free_node(*(expr_gen.node_allocator_),branch[1]); - - expression_node_ptr result = error_node(); - - if (expr_gen.parser_->settings_.strength_reduction_enabled()) - { - // c / (v0 / v1) --> (covov) (c * v1) / v0 - if ((details::e_div == o0) && (details::e_div == o1)) - { - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, "(t*t)/t", c, v1, v0, result); - - exprtk_debug(("c / (v0 / v1) --> (covov) (c * v1) / v0\n")); - - return (synthesis_result) ? result : error_node(); - } - } - - const bool synthesis_result = - synthesize_sf3ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1), c, v0, v1, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o0,f0)) - return error_node(); - else if (!expr_gen.valid_operator(o1,f1)) - return error_node(); - else - return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, f0, f1); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1) - { - return details::build_string() - << "t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "t)"; - } - }; - - struct synthesize_covoc_expression0 - { - typedef typename covoc_t::type0 node_type; - typedef typename covoc_t::sf3_type sf3_type; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // (c0 o0 v) o1 (c1) - const details::cov_base_node* cov = static_cast*>(branch[0]); - const Type c0 = cov->c(); - const Type& v = cov->v(); - const Type c1 = static_cast*>(branch[1])->value(); - const details::operator_type o0 = cov->operation(); - const details::operator_type o1 = operation; - - binary_functor_t f0 = reinterpret_cast(0); - binary_functor_t f1 = reinterpret_cast(0); - - details::free_node(*(expr_gen.node_allocator_),branch[0]); - details::free_node(*(expr_gen.node_allocator_),branch[1]); - - expression_node_ptr result = error_node(); - - if (expr_gen.parser_->settings_.strength_reduction_enabled()) - { - // (c0 + v) + c1 --> (cov) (c0 + c1) + v - if ((details::e_add == o0) && (details::e_add == o1)) - { - exprtk_debug(("(c0 + v) + c1 --> (cov) (c0 + c1) + v\n")); - - return expr_gen.node_allocator_-> - template allocate_cr > >(c0 + c1, v); - } - // (c0 + v) - c1 --> (cov) (c0 - c1) + v - else if ((details::e_add == o0) && (details::e_sub == o1)) - { - exprtk_debug(("(c0 + v) - c1 --> (cov) (c0 - c1) + v\n")); - - return expr_gen.node_allocator_-> - template allocate_cr > >(c0 - c1, v); - } - // (c0 - v) + c1 --> (cov) (c0 + c1) - v - else if ((details::e_sub == o0) && (details::e_add == o1)) - { - exprtk_debug(("(c0 - v) + c1 --> (cov) (c0 + c1) - v\n")); - - return expr_gen.node_allocator_-> - template allocate_cr > >(c0 + c1, v); - } - // (c0 - v) - c1 --> (cov) (c0 - c1) - v - else if ((details::e_sub == o0) && (details::e_sub == o1)) - { - exprtk_debug(("(c0 - v) - c1 --> (cov) (c0 - c1) - v\n")); - - return expr_gen.node_allocator_-> - template allocate_cr > >(c0 - c1, v); - } - // (c0 * v) * c1 --> (cov) (c0 * c1) * v - else if ((details::e_mul == o0) && (details::e_mul == o1)) - { - exprtk_debug(("(c0 * v) * c1 --> (cov) (c0 * c1) * v\n")); - - return expr_gen.node_allocator_-> - template allocate_cr > >(c0 * c1, v); - } - // (c0 * v) / c1 --> (cov) (c0 / c1) * v - else if ((details::e_mul == o0) && (details::e_div == o1)) - { - exprtk_debug(("(c0 * v) / c1 --> (cov) (c0 / c1) * v\n")); - - return expr_gen.node_allocator_-> - template allocate_cr > >(c0 / c1, v); - } - // (c0 / v) * c1 --> (cov) (c0 * c1) / v - else if ((details::e_div == o0) && (details::e_mul == o1)) - { - exprtk_debug(("(c0 / v) * c1 --> (cov) (c0 * c1) / v\n")); - - return expr_gen.node_allocator_-> - template allocate_cr > >(c0 * c1, v); - } - // (c0 / v) / c1 --> (cov) (c0 / c1) / v - else if ((details::e_div == o0) && (details::e_div == o1)) - { - exprtk_debug(("(c0 / v) / c1 --> (cov) (c0 / c1) / v\n")); - - return expr_gen.node_allocator_-> - template allocate_cr > >(c0 / c1, v); - } - } - - const bool synthesis_result = - synthesize_sf3ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o0,f0)) - return error_node(); - else if (!expr_gen.valid_operator(o1,f1)) - return error_node(); - else - return node_type::allocate(*(expr_gen.node_allocator_), c0, v, c1, f0, f1); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1) - { - return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "t"; - } - }; - - struct synthesize_covoc_expression1 - { - typedef typename covoc_t::type1 node_type; - typedef typename covoc_t::sf3_type sf3_type; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // (c0) o0 (v o1 c1) - const details::voc_base_node* voc = static_cast*>(branch[1]); - const Type c0 = static_cast*>(branch[0])->value(); - const Type& v = voc->v(); - const Type c1 = voc->c(); - const details::operator_type o0 = operation; - const details::operator_type o1 = voc->operation(); - - binary_functor_t f0 = reinterpret_cast(0); - binary_functor_t f1 = reinterpret_cast(0); - - details::free_node(*(expr_gen.node_allocator_),branch[0]); - details::free_node(*(expr_gen.node_allocator_),branch[1]); - - expression_node_ptr result = error_node(); - - if (expr_gen.parser_->settings_.strength_reduction_enabled()) - { - // (c0) + (v + c1) --> (cov) (c0 + c1) + v - if ((details::e_add == o0) && (details::e_add == o1)) - { - exprtk_debug(("(c0) + (v + c1) --> (cov) (c0 + c1) + v\n")); - - return expr_gen.node_allocator_-> - template allocate_cr > >(c0 + c1, v); - } - // (c0) + (v - c1) --> (cov) (c0 - c1) + v - else if ((details::e_add == o0) && (details::e_sub == o1)) - { - exprtk_debug(("(c0) + (v - c1) --> (cov) (c0 - c1) + v\n")); - - return expr_gen.node_allocator_-> - template allocate_cr > >(c0 - c1, v); - } - // (c0) - (v + c1) --> (cov) (c0 - c1) - v - else if ((details::e_sub == o0) && (details::e_add == o1)) - { - exprtk_debug(("(c0) - (v + c1) --> (cov) (c0 - c1) - v\n")); - - return expr_gen.node_allocator_-> - template allocate_cr > >(c0 - c1, v); - } - // (c0) - (v - c1) --> (cov) (c0 + c1) - v - else if ((details::e_sub == o0) && (details::e_sub == o1)) - { - exprtk_debug(("(c0) - (v - c1) --> (cov) (c0 + c1) - v\n")); - - return expr_gen.node_allocator_-> - template allocate_cr > >(c0 + c1, v); - } - // (c0) * (v * c1) --> (voc) v * (c0 * c1) - else if ((details::e_mul == o0) && (details::e_mul == o1)) - { - exprtk_debug(("(c0) * (v * c1) --> (voc) v * (c0 * c1)\n")); - - return expr_gen.node_allocator_-> - template allocate_cr > >(c0 * c1, v); - } - // (c0) * (v / c1) --> (cov) (c0 / c1) * v - else if ((details::e_mul == o0) && (details::e_div == o1)) - { - exprtk_debug(("(c0) * (v / c1) --> (cov) (c0 / c1) * v\n")); - - return expr_gen.node_allocator_-> - template allocate_cr > >(c0 / c1, v); - } - // (c0) / (v * c1) --> (cov) (c0 / c1) / v - else if ((details::e_div == o0) && (details::e_mul == o1)) - { - exprtk_debug(("(c0) / (v * c1) --> (cov) (c0 / c1) / v\n")); - - return expr_gen.node_allocator_-> - template allocate_cr > >(c0 / c1, v); - } - // (c0) / (v / c1) --> (cov) (c0 * c1) / v - else if ((details::e_div == o0) && (details::e_div == o1)) - { - exprtk_debug(("(c0) / (v / c1) --> (cov) (c0 * c1) / v\n")); - - return expr_gen.node_allocator_-> - template allocate_cr > >(c0 * c1, v); - } - } - - const bool synthesis_result = - synthesize_sf3ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o0,f0)) - return error_node(); - else if (!expr_gen.valid_operator(o1,f1)) - return error_node(); - else - return node_type::allocate(*(expr_gen.node_allocator_), c0, v, c1, f0, f1); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1) - { - return details::build_string() - << "t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "t)"; - } - }; - - struct synthesize_cocov_expression0 - { - typedef typename cocov_t::type0 node_type; - static inline expression_node_ptr process(expression_generator&, const details::operator_type&, expression_node_ptr (&)[2]) - { - // (c0 o0 c1) o1 (v) - Not possible. - return error_node(); - } - }; - - struct synthesize_cocov_expression1 - { - typedef typename cocov_t::type1 node_type; - typedef typename cocov_t::sf3_type sf3_type; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // (c0) o0 (c1 o1 v) - const details::cov_base_node* cov = static_cast*>(branch[1]); - const Type c0 = static_cast*>(branch[0])->value(); - const Type c1 = cov->c(); - const Type& v = cov->v(); - const details::operator_type o0 = operation; - const details::operator_type o1 = cov->operation(); - - binary_functor_t f0 = reinterpret_cast(0); - binary_functor_t f1 = reinterpret_cast(0); - - details::free_node(*(expr_gen.node_allocator_),branch[0]); - details::free_node(*(expr_gen.node_allocator_),branch[1]); - - expression_node_ptr result = error_node(); - - if (expr_gen.parser_->settings_.strength_reduction_enabled()) - { - // (c0) + (c1 + v) --> (cov) (c0 + c1) + v - if ((details::e_add == o0) && (details::e_add == o1)) - { - exprtk_debug(("(c0) + (c1 + v) --> (cov) (c0 + c1) + v\n")); - - return expr_gen.node_allocator_-> - template allocate_cr > >(c0 + c1, v); - } - // (c0) + (c1 - v) --> (cov) (c0 + c1) - v - else if ((details::e_add == o0) && (details::e_sub == o1)) - { - exprtk_debug(("(c0) + (c1 - v) --> (cov) (c0 + c1) - v\n")); - - return expr_gen.node_allocator_-> - template allocate_cr > >(c0 + c1, v); - } - // (c0) - (c1 + v) --> (cov) (c0 - c1) - v - else if ((details::e_sub == o0) && (details::e_add == o1)) - { - exprtk_debug(("(c0) - (c1 + v) --> (cov) (c0 - c1) - v\n")); - - return expr_gen.node_allocator_-> - template allocate_cr > >(c0 - c1, v); - } - // (c0) - (c1 - v) --> (cov) (c0 - c1) + v - else if ((details::e_sub == o0) && (details::e_sub == o1)) - { - exprtk_debug(("(c0) - (c1 - v) --> (cov) (c0 - c1) + v\n")); - - return expr_gen.node_allocator_-> - template allocate_cr > >(c0 - c1, v); - } - // (c0) * (c1 * v) --> (cov) (c0 * c1) * v - else if ((details::e_mul == o0) && (details::e_mul == o1)) - { - exprtk_debug(("(c0) * (c1 * v) --> (cov) (c0 * c1) * v\n")); - - return expr_gen.node_allocator_-> - template allocate_cr > >(c0 * c1, v); - } - // (c0) * (c1 / v) --> (cov) (c0 * c1) / v - else if ((details::e_mul == o0) && (details::e_div == o1)) - { - exprtk_debug(("(c0) * (c1 / v) --> (cov) (c0 * c1) / v\n")); - - return expr_gen.node_allocator_-> - template allocate_cr > >(c0 * c1, v); - } - // (c0) / (c1 * v) --> (cov) (c0 / c1) / v - else if ((details::e_div == o0) && (details::e_mul == o1)) - { - exprtk_debug(("(c0) / (c1 * v) --> (cov) (c0 / c1) / v\n")); - - return expr_gen.node_allocator_-> - template allocate_cr > >(c0 / c1, v); - } - // (c0) / (c1 / v) --> (cov) (c0 / c1) * v - else if ((details::e_div == o0) && (details::e_div == o1)) - { - exprtk_debug(("(c0) / (c1 / v) --> (cov) (c0 / c1) * v\n")); - - return expr_gen.node_allocator_-> - template allocate_cr > >(c0 / c1, v); - } - } - - const bool synthesis_result = - synthesize_sf3ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1), c0, c1, v, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o0,f0)) - return error_node(); - else if (!expr_gen.valid_operator(o1,f1)) - return error_node(); - else - return node_type::allocate(*(expr_gen.node_allocator_), c0, c1, v, f0, f1); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1) - { - return details::build_string() - << "t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "t)"; - } - }; - - struct synthesize_vococ_expression0 - { - typedef typename vococ_t::type0 node_type; - typedef typename vococ_t::sf3_type sf3_type; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // (v o0 c0) o1 (c1) - const details::voc_base_node* voc = static_cast*>(branch[0]); - const Type& v = voc->v(); - const Type& c0 = voc->c(); - const Type& c1 = static_cast*>(branch[1])->value(); - const details::operator_type o0 = voc->operation(); - const details::operator_type o1 = operation; - - binary_functor_t f0 = reinterpret_cast(0); - binary_functor_t f1 = reinterpret_cast(0); - - details::free_node(*(expr_gen.node_allocator_),branch[0]); - details::free_node(*(expr_gen.node_allocator_),branch[1]); - - expression_node_ptr result = error_node(); - - if (expr_gen.parser_->settings_.strength_reduction_enabled()) - { - // (v + c0) + c1 --> (voc) v + (c0 + c1) - if ((details::e_add == o0) && (details::e_add == o1)) - { - exprtk_debug(("(v + c0) + c1 --> (voc) v + (c0 + c1)\n")); - - return expr_gen.node_allocator_-> - template allocate_rc > >(v, c0 + c1); - } - // (v + c0) - c1 --> (voc) v + (c0 - c1) - else if ((details::e_add == o0) && (details::e_sub == o1)) - { - exprtk_debug(("(v + c0) - c1 --> (voc) v + (c0 - c1)\n")); - - return expr_gen.node_allocator_-> - template allocate_rc > >(v, c0 - c1); - } - // (v - c0) + c1 --> (voc) v - (c0 + c1) - else if ((details::e_sub == o0) && (details::e_add == o1)) - { - exprtk_debug(("(v - c0) + c1 --> (voc) v - (c0 + c1)\n")); - - return expr_gen.node_allocator_-> - template allocate_rc > >(v, c1 - c0); - } - // (v - c0) - c1 --> (voc) v - (c0 + c1) - else if ((details::e_sub == o0) && (details::e_sub == o1)) - { - exprtk_debug(("(v - c0) - c1 --> (voc) v - (c0 + c1)\n")); - - return expr_gen.node_allocator_-> - template allocate_rc > >(v, c0 + c1); - } - // (v * c0) * c1 --> (voc) v * (c0 * c1) - else if ((details::e_mul == o0) && (details::e_mul == o1)) - { - exprtk_debug(("(v * c0) * c1 --> (voc) v * (c0 * c1)\n")); - - return expr_gen.node_allocator_-> - template allocate_rc > >(v, c0 * c1); - } - // (v * c0) / c1 --> (voc) v * (c0 / c1) - else if ((details::e_mul == o0) && (details::e_div == o1)) - { - exprtk_debug(("(v * c0) / c1 --> (voc) v * (c0 / c1)\n")); - - return expr_gen.node_allocator_-> - template allocate_rc > >(v, c0 / c1); - } - // (v / c0) * c1 --> (voc) v * (c1 / c0) - else if ((details::e_div == o0) && (details::e_mul == o1)) - { - exprtk_debug(("(v / c0) * c1 --> (voc) v * (c1 / c0)\n")); - - return expr_gen.node_allocator_-> - template allocate_rc > >(v, c1 / c0); - } - // (v / c0) / c1 --> (voc) v / (c0 * c1) - else if ((details::e_div == o0) && (details::e_div == o1)) - { - exprtk_debug(("(v / c0) / c1 --> (voc) v / (c0 * c1)\n")); - - return expr_gen.node_allocator_-> - template allocate_rc > >(v, c0 * c1); - } - // (v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1) - else if ((details::e_pow == o0) && (details::e_pow == o1)) - { - exprtk_debug(("(v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1)\n")); - - return expr_gen.node_allocator_-> - template allocate_rc > >(v, c0 * c1); - } - } - - const bool synthesis_result = - synthesize_sf3ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1), v, c0, c1, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o0,f0)) - return error_node(); - else if (!expr_gen.valid_operator(o1,f1)) - return error_node(); - else - return node_type::allocate(*(expr_gen.node_allocator_), v, c0, c1, f0, f1); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1) - { - return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "t"; - } - }; - - struct synthesize_vococ_expression1 - { - typedef typename vococ_t::type0 node_type; - - static inline expression_node_ptr process(expression_generator&, const details::operator_type&, expression_node_ptr (&)[2]) - { - // (v) o0 (c0 o1 c1) - Not possible. - exprtk_debug(("(v) o0 (c0 o1 c1) - Not possible.\n")); - return error_node(); - } - }; - - struct synthesize_vovovov_expression0 - { - typedef typename vovovov_t::type0 node_type; - typedef typename vovovov_t::sf4_type sf4_type; - typedef typename node_type::T0 T0; - typedef typename node_type::T1 T1; - typedef typename node_type::T2 T2; - typedef typename node_type::T3 T3; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // (v0 o0 v1) o1 (v2 o2 v3) - const details::vov_base_node* vov0 = static_cast*>(branch[0]); - const details::vov_base_node* vov1 = static_cast*>(branch[1]); - const Type& v0 = vov0->v0(); - const Type& v1 = vov0->v1(); - const Type& v2 = vov1->v0(); - const Type& v3 = vov1->v1(); - const details::operator_type o0 = vov0->operation(); - const details::operator_type o1 = operation; - const details::operator_type o2 = vov1->operation(); - - binary_functor_t f0 = reinterpret_cast(0); - binary_functor_t f1 = reinterpret_cast(0); - binary_functor_t f2 = reinterpret_cast(0); - - details::free_node(*(expr_gen.node_allocator_),branch[0]); - details::free_node(*(expr_gen.node_allocator_),branch[1]); - - expression_node_ptr result = error_node(); - - if (expr_gen.parser_->settings_.strength_reduction_enabled()) - { - // (v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3) - if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) - { - const bool synthesis_result = - synthesize_sf4ext_expression:: - template compile(expr_gen, "(t*t)/(t*t)", v0, v2, v1, v3, result); - - exprtk_debug(("(v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3)\n")); - - return (synthesis_result) ? result : error_node(); - } - // (v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2) - else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) - { - const bool synthesis_result = - synthesize_sf4ext_expression:: - template compile(expr_gen, "(t*t)/(t*t)", v0, v3, v1, v2, result); - - exprtk_debug(("(v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2)\n")); - - return (synthesis_result) ? result : error_node(); - } - // (v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2) - else if ((details::e_add == o0) && (details::e_div == o1) && (details::e_div == o2)) - { - const bool synthesis_result = - synthesize_sf4ext_expression:: - template compile(expr_gen, "(t+t)*(t/t)", v0, v1, v3, v2, result); - - exprtk_debug(("(v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)\n")); - - return (synthesis_result) ? result : error_node(); - } - // (v0 - v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2) - else if ((details::e_sub == o0) && (details::e_div == o1) && (details::e_div == o2)) - { - const bool synthesis_result = - synthesize_sf4ext_expression:: - template compile(expr_gen, "(t-t)*(t/t)", v0, v1, v3, v2, result); - - exprtk_debug(("(v0 - v1) / (v2 / v3) --> (vovovov) (v0 - v1) * (v3 / v2)\n")); - - return (synthesis_result) ? result : error_node(); - } - // (v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2 - else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) - { - const bool synthesis_result = - synthesize_sf4ext_expression:: - template compile(expr_gen, "((t*t)*t)/t", v0, v1, v3, v2, result); - - exprtk_debug(("(v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2\n")); - - return (synthesis_result) ? result : error_node(); - } - } - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o0,f0)) - return error_node(); - else if (!expr_gen.valid_operator(o1,f1)) - return error_node(); - else if (!expr_gen.valid_operator(o2,f2)) - return error_node(); - else - return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1, - const details::operator_type o2) - { - return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "(t" << expr_gen.to_str(o2) - << "t)"; - } - }; - - struct synthesize_vovovoc_expression0 - { - typedef typename vovovoc_t::type0 node_type; - typedef typename vovovoc_t::sf4_type sf4_type; - typedef typename node_type::T0 T0; - typedef typename node_type::T1 T1; - typedef typename node_type::T2 T2; - typedef typename node_type::T3 T3; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // (v0 o0 v1) o1 (v2 o2 c) - const details::vov_base_node* vov = static_cast*>(branch[0]); - const details::voc_base_node* voc = static_cast*>(branch[1]); - const Type& v0 = vov->v0(); - const Type& v1 = vov->v1(); - const Type& v2 = voc->v (); - const Type c = voc->c (); - const details::operator_type o0 = vov->operation(); - const details::operator_type o1 = operation; - const details::operator_type o2 = voc->operation(); - - binary_functor_t f0 = reinterpret_cast(0); - binary_functor_t f1 = reinterpret_cast(0); - binary_functor_t f2 = reinterpret_cast(0); - - details::free_node(*(expr_gen.node_allocator_),branch[0]); - details::free_node(*(expr_gen.node_allocator_),branch[1]); - - expression_node_ptr result = error_node(); - - if (expr_gen.parser_->settings_.strength_reduction_enabled()) - { - // (v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c) - if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) - { - const bool synthesis_result = - synthesize_sf4ext_expression:: - template compile(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result); - - exprtk_debug(("(v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c)\n")); - - return (synthesis_result) ? result : error_node(); - } - // (v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2) - if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) - { - const bool synthesis_result = - synthesize_sf4ext_expression:: - template compile(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result); - - exprtk_debug(("(v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2)\n")); - - return (synthesis_result) ? result : error_node(); - } - } - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o0,f0)) - return error_node(); - else if (!expr_gen.valid_operator(o1,f1)) - return error_node(); - else if (!expr_gen.valid_operator(o2,f2)) - return error_node(); - else - return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1, - const details::operator_type o2) - { - return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "(t" << expr_gen.to_str(o2) - << "t)"; - } - }; - - struct synthesize_vovocov_expression0 - { - typedef typename vovocov_t::type0 node_type; - typedef typename vovocov_t::sf4_type sf4_type; - typedef typename node_type::T0 T0; - typedef typename node_type::T1 T1; - typedef typename node_type::T2 T2; - typedef typename node_type::T3 T3; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // (v0 o0 v1) o1 (c o2 v2) - const details::vov_base_node* vov = static_cast*>(branch[0]); - const details::cov_base_node* cov = static_cast*>(branch[1]); - const Type& v0 = vov->v0(); - const Type& v1 = vov->v1(); - const Type& v2 = cov->v (); - const Type c = cov->c (); - const details::operator_type o0 = vov->operation(); - const details::operator_type o1 = operation; - const details::operator_type o2 = cov->operation(); - - binary_functor_t f0 = reinterpret_cast(0); - binary_functor_t f1 = reinterpret_cast(0); - binary_functor_t f2 = reinterpret_cast(0); - - details::free_node(*(expr_gen.node_allocator_),branch[0]); - details::free_node(*(expr_gen.node_allocator_),branch[1]); - - expression_node_ptr result = error_node(); - - if (expr_gen.parser_->settings_.strength_reduction_enabled()) - { - // (v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2) - if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) - { - const bool synthesis_result = - synthesize_sf4ext_expression:: - template compile(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result); - - exprtk_debug(("(v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2)\n")); - - return (synthesis_result) ? result : error_node(); - } - // (v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c) - if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) - { - const bool synthesis_result = - synthesize_sf4ext_expression:: - template compile(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result); - - exprtk_debug(("(v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c)\n")); - - return (synthesis_result) ? result : error_node(); - } - } - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o0,f0)) - return error_node(); - else if (!expr_gen.valid_operator(o1,f1)) - return error_node(); - else if (!expr_gen.valid_operator(o2,f2)) - return error_node(); - else - return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1, - const details::operator_type o2) - { - return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "(t" << expr_gen.to_str(o2) - << "t)"; - } - }; - - struct synthesize_vocovov_expression0 - { - typedef typename vocovov_t::type0 node_type; - typedef typename vocovov_t::sf4_type sf4_type; - typedef typename node_type::T0 T0; - typedef typename node_type::T1 T1; - typedef typename node_type::T2 T2; - typedef typename node_type::T3 T3; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // (v0 o0 c) o1 (v1 o2 v2) - const details::voc_base_node* voc = static_cast*>(branch[0]); - const details::vov_base_node* vov = static_cast*>(branch[1]); - const Type c = voc->c (); - const Type& v0 = voc->v (); - const Type& v1 = vov->v0(); - const Type& v2 = vov->v1(); - const details::operator_type o0 = voc->operation(); - const details::operator_type o1 = operation; - const details::operator_type o2 = vov->operation(); - - binary_functor_t f0 = reinterpret_cast(0); - binary_functor_t f1 = reinterpret_cast(0); - binary_functor_t f2 = reinterpret_cast(0); - - details::free_node(*(expr_gen.node_allocator_),branch[0]); - details::free_node(*(expr_gen.node_allocator_),branch[1]); - - expression_node_ptr result = error_node(); - - if (expr_gen.parser_->settings_.strength_reduction_enabled()) - { - // (v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2) - if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) - { - const bool synthesis_result = - synthesize_sf4ext_expression:: - template compile(expr_gen, "(t*t)/(t*t)", v0, v1, c, v2, result); - - exprtk_debug(("(v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2)\n")); - - return (synthesis_result) ? result : error_node(); - } - // (v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1) - if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) - { - const bool synthesis_result = - synthesize_sf4ext_expression:: - template compile(expr_gen, "(t*t)/(t*t)", v0, v2, c, v1, result); - - exprtk_debug(("(v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1)\n")); - - return (synthesis_result) ? result : error_node(); - } - } - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o0,f0)) - return error_node(); - else if (!expr_gen.valid_operator(o1,f1)) - return error_node(); - else if (!expr_gen.valid_operator(o2,f2)) - return error_node(); - else - return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1, - const details::operator_type o2) - { - return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "(t" << expr_gen.to_str(o2) - << "t)"; - } - }; - - struct synthesize_covovov_expression0 - { - typedef typename covovov_t::type0 node_type; - typedef typename covovov_t::sf4_type sf4_type; - typedef typename node_type::T0 T0; - typedef typename node_type::T1 T1; - typedef typename node_type::T2 T2; - typedef typename node_type::T3 T3; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // (c o0 v0) o1 (v1 o2 v2) - const details::cov_base_node* cov = static_cast*>(branch[0]); - const details::vov_base_node* vov = static_cast*>(branch[1]); - const Type c = cov->c (); - const Type& v0 = cov->v (); - const Type& v1 = vov->v0(); - const Type& v2 = vov->v1(); - const details::operator_type o0 = cov->operation(); - const details::operator_type o1 = operation; - const details::operator_type o2 = vov->operation(); - - binary_functor_t f0 = reinterpret_cast(0); - binary_functor_t f1 = reinterpret_cast(0); - binary_functor_t f2 = reinterpret_cast(0); - - details::free_node(*(expr_gen.node_allocator_),branch[0]); - details::free_node(*(expr_gen.node_allocator_),branch[1]); - - expression_node_ptr result = error_node(); - - if (expr_gen.parser_->settings_.strength_reduction_enabled()) - { - // (c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2) - if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) - { - const bool synthesis_result = - synthesize_sf4ext_expression:: - template compile(expr_gen, "(t*t)/(t*t)", c, v1, v0, v2, result); - - exprtk_debug(("(c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2)\n")); - - return (synthesis_result) ? result : error_node(); - } - // (c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1) - if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) - { - const bool synthesis_result = - synthesize_sf4ext_expression:: - template compile(expr_gen, "(t*t)/(t*t)", c, v2, v0, v1, result); - - exprtk_debug(("(c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1)\n")); - - return (synthesis_result) ? result : error_node(); - } - } - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o0,f0)) - return error_node(); - else if (!expr_gen.valid_operator(o1,f1)) - return error_node(); - else if (!expr_gen.valid_operator(o2,f2)) - return error_node(); - else - return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1, - const details::operator_type o2) - { - return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "(t" << expr_gen.to_str(o2) - << "t)"; - } - }; - - struct synthesize_covocov_expression0 - { - typedef typename covocov_t::type0 node_type; - typedef typename covocov_t::sf4_type sf4_type; - typedef typename node_type::T0 T0; - typedef typename node_type::T1 T1; - typedef typename node_type::T2 T2; - typedef typename node_type::T3 T3; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // (c0 o0 v0) o1 (c1 o2 v1) - const details::cov_base_node* cov0 = static_cast*>(branch[0]); - const details::cov_base_node* cov1 = static_cast*>(branch[1]); - const Type c0 = cov0->c(); - const Type& v0 = cov0->v(); - const Type c1 = cov1->c(); - const Type& v1 = cov1->v(); - const details::operator_type o0 = cov0->operation(); - const details::operator_type o1 = operation; - const details::operator_type o2 = cov1->operation(); - - binary_functor_t f0 = reinterpret_cast(0); - binary_functor_t f1 = reinterpret_cast(0); - binary_functor_t f2 = reinterpret_cast(0); - - details::free_node(*(expr_gen.node_allocator_),branch[0]); - details::free_node(*(expr_gen.node_allocator_),branch[1]); - - expression_node_ptr result = error_node(); - - if (expr_gen.parser_->settings_.strength_reduction_enabled()) - { - // (c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1 - if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) - { - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result); - - exprtk_debug(("(c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n")); - - return (synthesis_result) ? result : error_node(); - } - // (c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1 - else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) - { - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result); - - exprtk_debug(("(c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n")); - - return (synthesis_result) ? result : error_node(); - } - // (c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1 - else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) - { - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, "(t-t)+t", (c0 - c1), v0, v1, result); - - exprtk_debug(("(c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1\n")); - - return (synthesis_result) ? result : error_node(); - } - // (c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1 - else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) - { - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result); - - exprtk_debug(("(c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n")); - - return (synthesis_result) ? result : error_node(); - } - // (c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1) - else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) - { - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result); - - exprtk_debug(("(c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1)\n")); - - return (synthesis_result) ? result : error_node(); - } - // (c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1) - else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) - { - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result); - - exprtk_debug(("(c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1)\n")); - - return (synthesis_result) ? result : error_node(); - } - // (c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0 - else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) - { - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, "(t*t)/t", (c0 / c1), v1, v0, result); - - exprtk_debug(("(c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0\n")); - - return (synthesis_result) ? result : error_node(); - } - // (c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1) - else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) - { - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, "t*(t*t)", (c0 / c1), v0, v1, result); - - exprtk_debug(("(c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n")); - - return (synthesis_result) ? result : error_node(); - } - // (c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1) - else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) - { - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result); - - exprtk_debug(("(c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1)\n")); - - return (synthesis_result) ? result : error_node(); - } - // (c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1) - else if ( - (std::equal_to()(c0,c1)) && - (details::e_mul == o0) && - (details::e_mul == o2) && - ( - (details::e_add == o1) || - (details::e_sub == o1) - ) - ) - { - std::string specfunc; - - switch (o1) - { - case details::e_add : specfunc = "t*(t+t)"; break; - case details::e_sub : specfunc = "t*(t-t)"; break; - default : return error_node(); - } - - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, specfunc, c0, v0, v1, result); - - exprtk_debug(("(c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n")); - - return (synthesis_result) ? result : error_node(); - } - } - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o0,f0)) - return error_node(); - else if (!expr_gen.valid_operator(o1,f1)) - return error_node(); - else if (!expr_gen.valid_operator(o2,f2)) - return error_node(); - else - return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1, - const details::operator_type o2) - { - return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "(t" << expr_gen.to_str(o2) - << "t)"; - } - }; - - struct synthesize_vocovoc_expression0 - { - typedef typename vocovoc_t::type0 node_type; - typedef typename vocovoc_t::sf4_type sf4_type; - typedef typename node_type::T0 T0; - typedef typename node_type::T1 T1; - typedef typename node_type::T2 T2; - typedef typename node_type::T3 T3; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // (v0 o0 c0) o1 (v1 o2 c1) - const details::voc_base_node* voc0 = static_cast*>(branch[0]); - const details::voc_base_node* voc1 = static_cast*>(branch[1]); - const Type c0 = voc0->c(); - const Type& v0 = voc0->v(); - const Type c1 = voc1->c(); - const Type& v1 = voc1->v(); - const details::operator_type o0 = voc0->operation(); - const details::operator_type o1 = operation; - const details::operator_type o2 = voc1->operation(); - - binary_functor_t f0 = reinterpret_cast(0); - binary_functor_t f1 = reinterpret_cast(0); - binary_functor_t f2 = reinterpret_cast(0); - - details::free_node(*(expr_gen.node_allocator_),branch[0]); - details::free_node(*(expr_gen.node_allocator_),branch[1]); - - expression_node_ptr result = error_node(); - - if (expr_gen.parser_->settings_.strength_reduction_enabled()) - { - // (v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1 - if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) - { - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result); - - exprtk_debug(("(v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n")); - - return (synthesis_result) ? result : error_node(); - } - // (v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1 - else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) - { - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result); - - exprtk_debug(("(v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n")); - - return (synthesis_result) ? result : error_node(); - } - // (v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1 - else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) - { - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, "(t+t)-t", (c1 - c0), v0, v1, result); - - exprtk_debug(("(v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1\n")); - - return (synthesis_result) ? result : error_node(); - } - // (v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1 - else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) - { - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result); - - exprtk_debug(("(v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n")); - - return (synthesis_result) ? result : error_node(); - } - // (v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1) - else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) - { - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result); - - exprtk_debug(("(v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n")); - - return (synthesis_result) ? result : error_node(); - } - // (v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1 - else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) - { - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, "(t*t)*t", Type(1) / (c0 * c1), v0, v1, result); - - exprtk_debug(("(v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1\n")); - - return (synthesis_result) ? result : error_node(); - } - // (v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1 - else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) - { - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result); - - exprtk_debug(("(v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1\n")); - - return (synthesis_result) ? result : error_node(); - } - // (v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1) - else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) - { - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, "t*(t/t)", (c0 * c1), v0, v1, result); - - exprtk_debug(("(v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n")); - - return (synthesis_result) ? result : error_node(); - } - // (v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1 - else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) - { - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, "t*(t/t)", Type(1) / (c0 * c1), v0, v1, result); - - exprtk_debug(("(v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1\n")); - - return (synthesis_result) ? result : error_node(); - } - // (v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1) - else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_add == o2)) - { - const bool synthesis_result = - synthesize_sf4ext_expression:: - template compile(expr_gen, "(t*t)*(t+t)", v0, T(1) / c0, v1, c1, result); - - exprtk_debug(("(v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1)\n")); - - return (synthesis_result) ? result : error_node(); - } - // (v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1) - else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_sub == o2)) - { - const bool synthesis_result = - synthesize_sf4ext_expression:: - template compile(expr_gen, "(t*t)*(t-t)", v0, T(1) / c0, v1, c1, result); - - exprtk_debug(("(v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1)\n")); - - return (synthesis_result) ? result : error_node(); - } - // (v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1) - else if ( - (std::equal_to()(c0,c1)) && - (details::e_mul == o0) && - (details::e_mul == o2) && - ( - (details::e_add == o1) || - (details::e_sub == o1) - ) - ) - { - std::string specfunc; - - switch (o1) - { - case details::e_add : specfunc = "t*(t+t)"; break; - case details::e_sub : specfunc = "t*(t-t)"; break; - default : return error_node(); - } - - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, specfunc, c0, v0, v1, result); - - exprtk_debug(("(v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n")); - - return (synthesis_result) ? result : error_node(); - } - // (v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c - else if ( - (std::equal_to()(c0,c1)) && - (details::e_div == o0) && - (details::e_div == o2) && - ( - (details::e_add == o1) || - (details::e_sub == o1) - ) - ) - { - std::string specfunc; - - switch (o1) - { - case details::e_add : specfunc = "(t+t)/t"; break; - case details::e_sub : specfunc = "(t-t)/t"; break; - default : return error_node(); - } - - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, specfunc, v0, v1, c0, result); - - exprtk_debug(("(v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c\n")); - - return (synthesis_result) ? result : error_node(); - } - } - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o0,f0)) - return error_node(); - else if (!expr_gen.valid_operator(o1,f1)) - return error_node(); - else if (!expr_gen.valid_operator(o2,f2)) - return error_node(); - else - return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1, - const details::operator_type o2) - { - return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "(t" << expr_gen.to_str(o2) - << "t)"; - } - }; - - struct synthesize_covovoc_expression0 - { - typedef typename covovoc_t::type0 node_type; - typedef typename covovoc_t::sf4_type sf4_type; - typedef typename node_type::T0 T0; - typedef typename node_type::T1 T1; - typedef typename node_type::T2 T2; - typedef typename node_type::T3 T3; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // (c0 o0 v0) o1 (v1 o2 c1) - const details::cov_base_node* cov = static_cast*>(branch[0]); - const details::voc_base_node* voc = static_cast*>(branch[1]); - const Type c0 = cov->c(); - const Type& v0 = cov->v(); - const Type c1 = voc->c(); - const Type& v1 = voc->v(); - const details::operator_type o0 = cov->operation(); - const details::operator_type o1 = operation; - const details::operator_type o2 = voc->operation(); - - binary_functor_t f0 = reinterpret_cast(0); - binary_functor_t f1 = reinterpret_cast(0); - binary_functor_t f2 = reinterpret_cast(0); - - details::free_node(*(expr_gen.node_allocator_),branch[0]); - details::free_node(*(expr_gen.node_allocator_),branch[1]); - - expression_node_ptr result = error_node(); - - if (expr_gen.parser_->settings_.strength_reduction_enabled()) - { - // (c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1 - if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) - { - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result); - - exprtk_debug(("(c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n")); - - return (synthesis_result) ? result : error_node(); - } - // (c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1 - else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) - { - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result); - - exprtk_debug(("(c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n")); - - return (synthesis_result) ? result : error_node(); - } - // (c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1 - else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) - { - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, "t-(t+t)", (c0 + c1), v0, v1, result); - - exprtk_debug(("(c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1\n")); - - return (synthesis_result) ? result : error_node(); - } - // (c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1 - else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) - { - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result); - - exprtk_debug(("(c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n")); - - return (synthesis_result) ? result : error_node(); - } - // (c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1) - else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) - { - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result); - - exprtk_debug(("(c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n")); - - return (synthesis_result) ? result : error_node(); - } - // (c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0) - else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) - { - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, "t*(t/t)", (c0 / c1), v1, v0, result); - - exprtk_debug(("(c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0)\n")); - - return (synthesis_result) ? result : error_node(); - } - // (c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1) - else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) - { - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result); - - exprtk_debug(("(c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1)\n")); - - return (synthesis_result) ? result : error_node(); - } - // (c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1) - else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) - { - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, "(t*t)/t", (c0 * c1), v0, v1, result); - - exprtk_debug(("(c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n")); - - return (synthesis_result) ? result : error_node(); - } - // (c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1) - else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) - { - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result); - - exprtk_debug(("(c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1)\n")); - - return (synthesis_result) ? result : error_node(); - } - // (c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1) - else if ( - (std::equal_to()(c0,c1)) && - (details::e_mul == o0) && - (details::e_mul == o2) && - ( - (details::e_add == o1) || - (details::e_sub == o1) - ) - ) - { - std::string specfunc; - - switch (o1) - { - case details::e_add : specfunc = "t*(t+t)"; break; - case details::e_sub : specfunc = "t*(t-t)"; break; - default : return error_node(); - } - - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen,specfunc, c0, v0, v1, result); - - exprtk_debug(("(c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n")); - - return (synthesis_result) ? result : error_node(); - } - } - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o0,f0)) - return error_node(); - else if (!expr_gen.valid_operator(o1,f1)) - return error_node(); - else if (!expr_gen.valid_operator(o2,f2)) - return error_node(); - else - return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1, - const details::operator_type o2) - { - return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "(t" << expr_gen.to_str(o2) - << "t)"; - } - }; - - struct synthesize_vococov_expression0 - { - typedef typename vococov_t::type0 node_type; - typedef typename vococov_t::sf4_type sf4_type; - typedef typename node_type::T0 T0; - typedef typename node_type::T1 T1; - typedef typename node_type::T2 T2; - typedef typename node_type::T3 T3; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // (v0 o0 c0) o1 (c1 o2 v1) - const details::voc_base_node* voc = static_cast*>(branch[0]); - const details::cov_base_node* cov = static_cast*>(branch[1]); - const Type c0 = voc->c(); - const Type& v0 = voc->v(); - const Type c1 = cov->c(); - const Type& v1 = cov->v(); - const details::operator_type o0 = voc->operation(); - const details::operator_type o1 = operation; - const details::operator_type o2 = cov->operation(); - - binary_functor_t f0 = reinterpret_cast(0); - binary_functor_t f1 = reinterpret_cast(0); - binary_functor_t f2 = reinterpret_cast(0); - - details::free_node(*(expr_gen.node_allocator_),branch[0]); - details::free_node(*(expr_gen.node_allocator_),branch[1]); - - expression_node_ptr result = error_node(); - - if (expr_gen.parser_->settings_.strength_reduction_enabled()) - { - // (v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1 - if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) - { - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result); - - exprtk_debug(("(v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n")); - - return (synthesis_result) ? result : error_node(); - } - // (v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1 - else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) - { - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result); - - exprtk_debug(("(v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n")); - - return (synthesis_result) ? result : error_node(); - } - // (v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0) - else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) - { - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, "(t+t)-t", v0, v1, (c1 + c0), result); - - exprtk_debug(("(v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0)\n")); - - return (synthesis_result) ? result : error_node(); - } - // (v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1 - else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) - { - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result); - - exprtk_debug(("(v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n")); - - return (synthesis_result) ? result : error_node(); - } - // (v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1) - else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) - { - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result); - - exprtk_debug(("(v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1)\n")); - - return (synthesis_result) ? result : error_node(); - } - // (v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1) - else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) - { - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result); - - exprtk_debug(("(v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1)\n")); - - return (synthesis_result) ? result : error_node(); - } - // (v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1) - else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) - { - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, "(t*t)*t", (c0 / c1), v0, v1, result); - - exprtk_debug(("(v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n")); - - return (synthesis_result) ? result : error_node(); - } - // (v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1) - else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) - { - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, "(t*t)/t", Type(1) / (c0 * c1), v0, v1, result); - - exprtk_debug(("(v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1)\n")); - - return (synthesis_result) ? result : error_node(); - } - // (v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1)) - else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) - { - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, "(t*t)*t", v0, v1, Type(1) / (c0 * c1), result); - - exprtk_debug(("(v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1))\n")); - - return (synthesis_result) ? result : error_node(); - } - // (v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1) - else if ( - (std::equal_to()(c0,c1)) && - (details::e_mul == o0) && - (details::e_mul == o2) && - ( - (details::e_add == o1) || (details::e_sub == o1) - ) - ) - { - std::string specfunc; - - switch (o1) - { - case details::e_add : specfunc = "t*(t+t)"; break; - case details::e_sub : specfunc = "t*(t-t)"; break; - default : return error_node(); - } - - const bool synthesis_result = - synthesize_sf3ext_expression:: - template compile(expr_gen, specfunc, c0, v0, v1, result); - - exprtk_debug(("(v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n")); - - return (synthesis_result) ? result : error_node(); - } - } - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o0,f0)) - return error_node(); - else if (!expr_gen.valid_operator(o1,f1)) - return error_node(); - else if (!expr_gen.valid_operator(o2,f2)) - return error_node(); - else - return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1, - const details::operator_type o2) - { - return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "(t" << expr_gen.to_str(o2) - << "t)"; - } - }; - - struct synthesize_vovovov_expression1 - { - typedef typename vovovov_t::type1 node_type; - typedef typename vovovov_t::sf4_type sf4_type; - typedef typename node_type::T0 T0; - typedef typename node_type::T1 T1; - typedef typename node_type::T2 T2; - typedef typename node_type::T3 T3; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // v0 o0 (v1 o1 (v2 o2 v3)) - typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t; - - const lcl_vovov_t* vovov = static_cast(branch[1]); - const Type& v0 = static_cast*>(branch[0])->ref(); - const Type& v1 = vovov->t0(); - const Type& v2 = vovov->t1(); - const Type& v3 = vovov->t2(); - const details::operator_type o0 = operation; - const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); - const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); - - binary_functor_t f0 = reinterpret_cast(0); - binary_functor_t f1 = vovov->f0(); - binary_functor_t f2 = vovov->f1(); - - details::free_node(*(expr_gen.node_allocator_),branch[1]); - - expression_node_ptr result = error_node(); - - if (synthesize_sf4ext_expression::template compile(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result)) - return result; - else if (!expr_gen.valid_operator(o0,f0)) - return error_node(); - - exprtk_debug(("v0 o0 (v1 o1 (v2 o2 v3))\n")); - - return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1, - const details::operator_type o2) - { - return details::build_string() - << "t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "(t" << expr_gen.to_str(o2) - << "t))"; - } - }; - - struct synthesize_vovovoc_expression1 - { - typedef typename vovovoc_t::type1 node_type; - typedef typename vovovoc_t::sf4_type sf4_type; - typedef typename node_type::T0 T0; - typedef typename node_type::T1 T1; - typedef typename node_type::T2 T2; - typedef typename node_type::T3 T3; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // v0 o0 (v1 o1 (v2 o2 c)) - typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t; - - const lcl_vovoc_t* vovoc = static_cast(branch[1]); - const Type& v0 = static_cast*>(branch[0])->ref(); - const Type& v1 = vovoc->t0(); - const Type& v2 = vovoc->t1(); - const Type c = vovoc->t2(); - const details::operator_type o0 = operation; - const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); - const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); - - binary_functor_t f0 = reinterpret_cast(0); - binary_functor_t f1 = vovoc->f0(); - binary_functor_t f2 = vovoc->f1(); - - details::free_node(*(expr_gen.node_allocator_),branch[1]); - - expression_node_ptr result = error_node(); - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o0,f0)) - return error_node(); - - exprtk_debug(("v0 o0 (v1 o1 (v2 o2 c))\n")); - - return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1, - const details::operator_type o2) - { - return details::build_string() - << "t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "(t" << expr_gen.to_str(o2) - << "t))"; - } - }; - - struct synthesize_vovocov_expression1 - { - typedef typename vovocov_t::type1 node_type; - typedef typename vovocov_t::sf4_type sf4_type; - typedef typename node_type::T0 T0; - typedef typename node_type::T1 T1; - typedef typename node_type::T2 T2; - typedef typename node_type::T3 T3; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // v0 o0 (v1 o1 (c o2 v2)) - typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t; - - const lcl_vocov_t* vocov = static_cast(branch[1]); - const Type& v0 = static_cast*>(branch[0])->ref(); - const Type& v1 = vocov->t0(); - const Type c = vocov->t1(); - const Type& v2 = vocov->t2(); - const details::operator_type o0 = operation; - const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); - const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); - - binary_functor_t f0 = reinterpret_cast(0); - binary_functor_t f1 = vocov->f0(); - binary_functor_t f2 = vocov->f1(); - - details::free_node(*(expr_gen.node_allocator_),branch[1]); - - expression_node_ptr result = error_node(); - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); - - if (synthesis_result) - return result; - if (!expr_gen.valid_operator(o0,f0)) - return error_node(); - - exprtk_debug(("v0 o0 (v1 o1 (c o2 v2))\n")); - - return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1, - const details::operator_type o2) - { - return details::build_string() - << "t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "(t" << expr_gen.to_str(o2) - << "t))"; - } - }; - - struct synthesize_vocovov_expression1 - { - typedef typename vocovov_t::type1 node_type; - typedef typename vocovov_t::sf4_type sf4_type; - typedef typename node_type::T0 T0; - typedef typename node_type::T1 T1; - typedef typename node_type::T2 T2; - typedef typename node_type::T3 T3; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // v0 o0 (c o1 (v1 o2 v2)) - typedef typename synthesize_covov_expression1::node_type lcl_covov_t; - - const lcl_covov_t* covov = static_cast(branch[1]); - const Type& v0 = static_cast*>(branch[0])->ref(); - const Type c = covov->t0(); - const Type& v1 = covov->t1(); - const Type& v2 = covov->t2(); - const details::operator_type o0 = operation; - const details::operator_type o1 = expr_gen.get_operator(covov->f0()); - const details::operator_type o2 = expr_gen.get_operator(covov->f1()); - - binary_functor_t f0 = reinterpret_cast(0); - binary_functor_t f1 = covov->f0(); - binary_functor_t f2 = covov->f1(); - - details::free_node(*(expr_gen.node_allocator_),branch[1]); - - expression_node_ptr result = error_node(); - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o0,f0)) - return error_node(); - - exprtk_debug(("v0 o0 (c o1 (v1 o2 v2))\n")); - - return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1, - const details::operator_type o2) - { - return details::build_string() - << "t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "(t" << expr_gen.to_str(o2) - << "t))"; - } - }; - - struct synthesize_covovov_expression1 - { - typedef typename covovov_t::type1 node_type; - typedef typename covovov_t::sf4_type sf4_type; - typedef typename node_type::T0 T0; - typedef typename node_type::T1 T1; - typedef typename node_type::T2 T2; - typedef typename node_type::T3 T3; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // c o0 (v0 o1 (v1 o2 v2)) - typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t; - - const lcl_vovov_t* vovov = static_cast(branch[1]); - const Type c = static_cast*>(branch[0])->value(); - const Type& v0 = vovov->t0(); - const Type& v1 = vovov->t1(); - const Type& v2 = vovov->t2(); - const details::operator_type o0 = operation; - const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); - const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); - - binary_functor_t f0 = reinterpret_cast(0); - binary_functor_t f1 = vovov->f0(); - binary_functor_t f2 = vovov->f1(); - - details::free_node(*(expr_gen.node_allocator_),branch[0]); - details::free_node(*(expr_gen.node_allocator_),branch[1]); - - expression_node_ptr result = error_node(); - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); - - if (synthesis_result) - return result; - if (!expr_gen.valid_operator(o0,f0)) - return error_node(); - - exprtk_debug(("c o0 (v0 o1 (v1 o2 v2))\n")); - - return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1, - const details::operator_type o2) - { - return details::build_string() - << "t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "(t" << expr_gen.to_str(o2) - << "t))"; - } - }; - - struct synthesize_covocov_expression1 - { - typedef typename covocov_t::type1 node_type; - typedef typename covocov_t::sf4_type sf4_type; - typedef typename node_type::T0 T0; - typedef typename node_type::T1 T1; - typedef typename node_type::T2 T2; - typedef typename node_type::T3 T3; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // c0 o0 (v0 o1 (c1 o2 v1)) - typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t; - - const lcl_vocov_t* vocov = static_cast(branch[1]); - const Type c0 = static_cast*>(branch[0])->value(); - const Type& v0 = vocov->t0(); - const Type c1 = vocov->t1(); - const Type& v1 = vocov->t2(); - const details::operator_type o0 = operation; - const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); - const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); - - binary_functor_t f0 = reinterpret_cast(0); - binary_functor_t f1 = vocov->f0(); - binary_functor_t f2 = vocov->f1(); - - details::free_node(*(expr_gen.node_allocator_),branch[0]); - details::free_node(*(expr_gen.node_allocator_),branch[1]); - - expression_node_ptr result = error_node(); - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o0,f0)) - return error_node(); - - exprtk_debug(("c0 o0 (v0 o1 (c1 o2 v1))\n")); - - return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1, - const details::operator_type o2) - { - return details::build_string() - << "t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "(t" << expr_gen.to_str(o2) - << "t))"; - } - }; - - struct synthesize_vocovoc_expression1 - { - typedef typename vocovoc_t::type1 node_type; - typedef typename vocovoc_t::sf4_type sf4_type; - typedef typename node_type::T0 T0; - typedef typename node_type::T1 T1; - typedef typename node_type::T2 T2; - typedef typename node_type::T3 T3; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // v0 o0 (c0 o1 (v1 o2 c2)) - typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t; - - const lcl_covoc_t* covoc = static_cast(branch[1]); - const Type& v0 = static_cast*>(branch[0])->ref(); - const Type c0 = covoc->t0(); - const Type& v1 = covoc->t1(); - const Type c1 = covoc->t2(); - const details::operator_type o0 = operation; - const details::operator_type o1 = expr_gen.get_operator(covoc->f0()); - const details::operator_type o2 = expr_gen.get_operator(covoc->f1()); - - binary_functor_t f0 = reinterpret_cast(0); - binary_functor_t f1 = covoc->f0(); - binary_functor_t f2 = covoc->f1(); - - details::free_node(*(expr_gen.node_allocator_),branch[1]); - - expression_node_ptr result = error_node(); - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o0,f0)) - return error_node(); - - exprtk_debug(("v0 o0 (c0 o1 (v1 o2 c2))\n")); - - return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1, - const details::operator_type o2) - { - return details::build_string() - << "t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "(t" << expr_gen.to_str(o2) - << "t))"; - } - }; - - struct synthesize_covovoc_expression1 - { - typedef typename covovoc_t::type1 node_type; - typedef typename covovoc_t::sf4_type sf4_type; - typedef typename node_type::T0 T0; - typedef typename node_type::T1 T1; - typedef typename node_type::T2 T2; - typedef typename node_type::T3 T3; - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // c0 o0 (v0 o1 (v1 o2 c1)) - typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t; - - const lcl_vovoc_t* vovoc = static_cast(branch[1]); - const Type c0 = static_cast*>(branch[0])->value(); - const Type& v0 = vovoc->t0(); - const Type& v1 = vovoc->t1(); - const Type c1 = vovoc->t2(); - const details::operator_type o0 = operation; - const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); - const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); - - binary_functor_t f0 = reinterpret_cast(0); - binary_functor_t f1 = vovoc->f0(); - binary_functor_t f2 = vovoc->f1(); - - details::free_node(*(expr_gen.node_allocator_),branch[0]); - details::free_node(*(expr_gen.node_allocator_),branch[1]); - - expression_node_ptr result = error_node(); - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o0,f0)) - return error_node(); - - exprtk_debug(("c0 o0 (v0 o1 (v1 o2 c1))\n")); - - return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1, - const details::operator_type o2) - { - return details::build_string() - << "t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "(t" << expr_gen.to_str(o2) - << "t))"; - } - }; - - struct synthesize_vococov_expression1 - { - typedef typename vococov_t::type1 node_type; - typedef typename vococov_t::sf4_type sf4_type; - typedef typename node_type::T0 T0; - typedef typename node_type::T1 T1; - typedef typename node_type::T2 T2; - typedef typename node_type::T3 T3; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // v0 o0 (c0 o1 (c1 o2 v1)) - typedef typename synthesize_cocov_expression1::node_type lcl_cocov_t; - - const lcl_cocov_t* cocov = static_cast(branch[1]); - const Type& v0 = static_cast*>(branch[0])->ref(); - const Type c0 = cocov->t0(); - const Type c1 = cocov->t1(); - const Type& v1 = cocov->t2(); - const details::operator_type o0 = operation; - const details::operator_type o1 = expr_gen.get_operator(cocov->f0()); - const details::operator_type o2 = expr_gen.get_operator(cocov->f1()); - - binary_functor_t f0 = reinterpret_cast(0); - binary_functor_t f1 = cocov->f0(); - binary_functor_t f2 = cocov->f1(); - - details::free_node(*(expr_gen.node_allocator_),branch[1]); - - expression_node_ptr result = error_node(); - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o0,f0)) - return error_node(); - - exprtk_debug(("v0 o0 (c0 o1 (c1 o2 v1))\n")); - - return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1, - const details::operator_type o2) - { - return details::build_string() - << "t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "(t" << expr_gen.to_str(o2) - << "t))"; - } - }; - - struct synthesize_vovovov_expression2 - { - typedef typename vovovov_t::type2 node_type; - typedef typename vovovov_t::sf4_type sf4_type; - typedef typename node_type::T0 T0; - typedef typename node_type::T1 T1; - typedef typename node_type::T2 T2; - typedef typename node_type::T3 T3; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // v0 o0 ((v1 o1 v2) o2 v3) - typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t; - - const lcl_vovov_t* vovov = static_cast(branch[1]); - const Type& v0 = static_cast*>(branch[0])->ref(); - const Type& v1 = vovov->t0(); - const Type& v2 = vovov->t1(); - const Type& v3 = vovov->t2(); - const details::operator_type o0 = operation; - const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); - const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); - - binary_functor_t f0 = reinterpret_cast(0); - binary_functor_t f1 = vovov->f0(); - binary_functor_t f2 = vovov->f1(); - - details::free_node(*(expr_gen.node_allocator_),branch[1]); - - expression_node_ptr result = error_node(); - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o0,f0)) - return error_node(); - - exprtk_debug(("v0 o0 ((v1 o1 v2) o2 v3)\n")); - - return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1, - const details::operator_type o2) - { - return details::build_string() - << "t" << expr_gen.to_str(o0) - << "((t" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t)"; - } - }; - - struct synthesize_vovovoc_expression2 - { - typedef typename vovovoc_t::type2 node_type; - typedef typename vovovoc_t::sf4_type sf4_type; - typedef typename node_type::T0 T0; - typedef typename node_type::T1 T1; - typedef typename node_type::T2 T2; - typedef typename node_type::T3 T3; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // v0 o0 ((v1 o1 v2) o2 c) - typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t; - - const lcl_vovoc_t* vovoc = static_cast(branch[1]); - const Type& v0 = static_cast*>(branch[0])->ref(); - const Type& v1 = vovoc->t0(); - const Type& v2 = vovoc->t1(); - const Type c = vovoc->t2(); - const details::operator_type o0 = operation; - const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); - const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); - - binary_functor_t f0 = reinterpret_cast(0); - binary_functor_t f1 = vovoc->f0(); - binary_functor_t f2 = vovoc->f1(); - - details::free_node(*(expr_gen.node_allocator_),branch[1]); - - expression_node_ptr result = error_node(); - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o0,f0)) - return error_node(); - - exprtk_debug(("v0 o0 ((v1 o1 v2) o2 c)\n")); - - return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1, - const details::operator_type o2) - { - return details::build_string() - << "t" << expr_gen.to_str(o0) - << "((t" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t)"; - } - }; - - struct synthesize_vovocov_expression2 - { - typedef typename vovocov_t::type2 node_type; - typedef typename vovocov_t::sf4_type sf4_type; - typedef typename node_type::T0 T0; - typedef typename node_type::T1 T1; - typedef typename node_type::T2 T2; - typedef typename node_type::T3 T3; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // v0 o0 ((v1 o1 c) o2 v2) - typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t; - - const lcl_vocov_t* vocov = static_cast(branch[1]); - const Type& v0 = static_cast*>(branch[0])->ref(); - const Type& v1 = vocov->t0(); - const Type c = vocov->t1(); - const Type& v2 = vocov->t2(); - const details::operator_type o0 = operation; - const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); - const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); - - binary_functor_t f0 = reinterpret_cast(0); - binary_functor_t f1 = vocov->f0(); - binary_functor_t f2 = vocov->f1(); - - details::free_node(*(expr_gen.node_allocator_),branch[1]); - - expression_node_ptr result = error_node(); - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o0,f0)) - return error_node(); - - exprtk_debug(("v0 o0 ((v1 o1 c) o2 v2)\n")); - - return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1, - const details::operator_type o2) - { - return details::build_string() - << "t" << expr_gen.to_str(o0) - << "((t" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t)"; - } - }; - - struct synthesize_vocovov_expression2 - { - typedef typename vocovov_t::type2 node_type; - typedef typename vocovov_t::sf4_type sf4_type; - typedef typename node_type::T0 T0; - typedef typename node_type::T1 T1; - typedef typename node_type::T2 T2; - typedef typename node_type::T3 T3; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // v0 o0 ((c o1 v1) o2 v2) - typedef typename synthesize_covov_expression0::node_type lcl_covov_t; - - const lcl_covov_t* covov = static_cast(branch[1]); - const Type& v0 = static_cast*>(branch[0])->ref(); - const Type c = covov->t0(); - const Type& v1 = covov->t1(); - const Type& v2 = covov->t2(); - const details::operator_type o0 = operation; - const details::operator_type o1 = expr_gen.get_operator(covov->f0()); - const details::operator_type o2 = expr_gen.get_operator(covov->f1()); - - binary_functor_t f0 = reinterpret_cast(0); - binary_functor_t f1 = covov->f0(); - binary_functor_t f2 = covov->f1(); - - details::free_node(*(expr_gen.node_allocator_),branch[1]); - - expression_node_ptr result = error_node(); - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o0,f0)) - return error_node(); - - exprtk_debug(("v0 o0 ((c o1 v1) o2 v2)\n")); - - return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1, - const details::operator_type o2) - { - return details::build_string() - << "t" << expr_gen.to_str(o0) - << "((t" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t)"; - } - }; - - struct synthesize_covovov_expression2 - { - typedef typename covovov_t::type2 node_type; - typedef typename covovov_t::sf4_type sf4_type; - typedef typename node_type::T0 T0; - typedef typename node_type::T1 T1; - typedef typename node_type::T2 T2; - typedef typename node_type::T3 T3; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // c o0 ((v1 o1 v2) o2 v3) - typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t; - - const lcl_vovov_t* vovov = static_cast(branch[1]); - const Type c = static_cast*>(branch[0])->value(); - const Type& v0 = vovov->t0(); - const Type& v1 = vovov->t1(); - const Type& v2 = vovov->t2(); - const details::operator_type o0 = operation; - const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); - const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); - - binary_functor_t f0 = reinterpret_cast(0); - binary_functor_t f1 = vovov->f0(); - binary_functor_t f2 = vovov->f1(); - - details::free_node(*(expr_gen.node_allocator_),branch[0]); - details::free_node(*(expr_gen.node_allocator_),branch[1]); - - expression_node_ptr result = error_node(); - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o0,f0)) - return error_node(); - - exprtk_debug(("c o0 ((v1 o1 v2) o2 v3)\n")); - - return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1, - const details::operator_type o2) - { - return details::build_string() - << "t" << expr_gen.to_str(o0) - << "((t" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t)"; - } - }; - - struct synthesize_covocov_expression2 - { - typedef typename covocov_t::type2 node_type; - typedef typename covocov_t::sf4_type sf4_type; - typedef typename node_type::T0 T0; - typedef typename node_type::T1 T1; - typedef typename node_type::T2 T2; - typedef typename node_type::T3 T3; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // c0 o0 ((v0 o1 c1) o2 v1) - typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t; - - const lcl_vocov_t* vocov = static_cast(branch[1]); - const Type c0 = static_cast*>(branch[0])->value(); - const Type& v0 = vocov->t0(); - const Type c1 = vocov->t1(); - const Type& v1 = vocov->t2(); - const details::operator_type o0 = operation; - const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); - const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); - - binary_functor_t f0 = reinterpret_cast(0); - binary_functor_t f1 = vocov->f0(); - binary_functor_t f2 = vocov->f1(); - - details::free_node(*(expr_gen.node_allocator_),branch[0]); - details::free_node(*(expr_gen.node_allocator_),branch[1]); - - expression_node_ptr result = error_node(); - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o0,f0)) - return error_node(); - - exprtk_debug(("c0 o0 ((v0 o1 c1) o2 v1)\n")); - - return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1, - const details::operator_type o2) - { - return details::build_string() - << "t" << expr_gen.to_str(o0) - << "((t" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t)"; - } - }; - - struct synthesize_vocovoc_expression2 - { - typedef typename vocovoc_t::type2 node_type; - typedef typename vocovoc_t::sf4_type sf4_type; - typedef typename node_type::T0 T0; - typedef typename node_type::T1 T1; - typedef typename node_type::T2 T2; - typedef typename node_type::T3 T3; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // v0 o0 ((c0 o1 v1) o2 c1) - typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t; - - const lcl_covoc_t* covoc = static_cast(branch[1]); - const Type& v0 = static_cast*>(branch[0])->ref(); - const Type c0 = covoc->t0(); - const Type& v1 = covoc->t1(); - const Type c1 = covoc->t2(); - const details::operator_type o0 = operation; - const details::operator_type o1 = expr_gen.get_operator(covoc->f0()); - const details::operator_type o2 = expr_gen.get_operator(covoc->f1()); - - binary_functor_t f0 = reinterpret_cast(0); - binary_functor_t f1 = covoc->f0(); - binary_functor_t f2 = covoc->f1(); - - details::free_node(*(expr_gen.node_allocator_),branch[1]); - - expression_node_ptr result = error_node(); - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o0,f0)) - return error_node(); - - exprtk_debug(("v0 o0 ((c0 o1 v1) o2 c1)\n")); - - return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1, - const details::operator_type o2) - { - return details::build_string() - << "t" << expr_gen.to_str(o0) - << "((t" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t)"; - } - }; - - struct synthesize_covovoc_expression2 - { - typedef typename covovoc_t::type2 node_type; - typedef typename covovoc_t::sf4_type sf4_type; - typedef typename node_type::T0 T0; - typedef typename node_type::T1 T1; - typedef typename node_type::T2 T2; - typedef typename node_type::T3 T3; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // c0 o0 ((v0 o1 v1) o2 c1) - typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t; - - const lcl_vovoc_t* vovoc = static_cast(branch[1]); - const Type c0 = static_cast*>(branch[0])->value(); - const Type& v0 = vovoc->t0(); - const Type& v1 = vovoc->t1(); - const Type c1 = vovoc->t2(); - const details::operator_type o0 = operation; - const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); - const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); - - binary_functor_t f0 = reinterpret_cast(0); - binary_functor_t f1 = vovoc->f0(); - binary_functor_t f2 = vovoc->f1(); - - details::free_node(*(expr_gen.node_allocator_),branch[0]); - details::free_node(*(expr_gen.node_allocator_),branch[1]); - - expression_node_ptr result = error_node(); - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o0,f0)) - return error_node(); - - exprtk_debug(("c0 o0 ((v0 o1 v1) o2 c1)\n")); - - return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1, - const details::operator_type o2) - { - return details::build_string() - << "t" << expr_gen.to_str(o0) - << "((t" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t)"; - } - }; - - struct synthesize_vococov_expression2 - { - typedef typename vococov_t::type2 node_type; - static inline expression_node_ptr process(expression_generator&, const details::operator_type&, expression_node_ptr (&)[2]) - { - // v0 o0 ((c0 o1 c1) o2 v1) - Not possible - exprtk_debug(("v0 o0 ((c0 o1 c1) o2 v1) - Not possible\n")); - return error_node(); - } - - static inline std::string id(expression_generator&, - const details::operator_type, const details::operator_type, const details::operator_type) - { - return "INVALID"; - } - }; - - struct synthesize_vovovov_expression3 - { - typedef typename vovovov_t::type3 node_type; - typedef typename vovovov_t::sf4_type sf4_type; - typedef typename node_type::T0 T0; - typedef typename node_type::T1 T1; - typedef typename node_type::T2 T2; - typedef typename node_type::T3 T3; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // ((v0 o0 v1) o1 v2) o2 v3 - typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t; - - const lcl_vovov_t* vovov = static_cast(branch[0]); - const Type& v0 = vovov->t0(); - const Type& v1 = vovov->t1(); - const Type& v2 = vovov->t2(); - const Type& v3 = static_cast*>(branch[1])->ref(); - const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); - const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); - const details::operator_type o2 = operation; - - binary_functor_t f0 = vovov->f0(); - binary_functor_t f1 = vovov->f1(); - binary_functor_t f2 = reinterpret_cast(0); - - details::free_node(*(expr_gen.node_allocator_),branch[0]); - - expression_node_ptr result = error_node(); - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o2,f2)) - return error_node(); - - exprtk_debug(("((v0 o0 v1) o1 v2) o2 v3\n")); - - return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1, - const details::operator_type o2) - { - return details::build_string() - << "((t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t"; - } - }; - - struct synthesize_vovovoc_expression3 - { - typedef typename vovovoc_t::type3 node_type; - typedef typename vovovoc_t::sf4_type sf4_type; - typedef typename node_type::T0 T0; - typedef typename node_type::T1 T1; - typedef typename node_type::T2 T2; - typedef typename node_type::T3 T3; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // ((v0 o0 v1) o1 v2) o2 c - typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t; - - const lcl_vovov_t* vovov = static_cast(branch[0]); - const Type& v0 = vovov->t0(); - const Type& v1 = vovov->t1(); - const Type& v2 = vovov->t2(); - const Type c = static_cast*>(branch[1])->value(); - const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); - const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); - const details::operator_type o2 = operation; - - binary_functor_t f0 = vovov->f0(); - binary_functor_t f1 = vovov->f1(); - binary_functor_t f2 = reinterpret_cast(0); - - details::free_node(*(expr_gen.node_allocator_),branch[0]); - details::free_node(*(expr_gen.node_allocator_),branch[1]); - - expression_node_ptr result = error_node(); - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o2,f2)) - return error_node(); - - exprtk_debug(("((v0 o0 v1) o1 v2) o2 c\n")); - - return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1, - const details::operator_type o2) - { - return details::build_string() - << "((t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t"; - } - }; - - struct synthesize_vovocov_expression3 - { - typedef typename vovocov_t::type3 node_type; - typedef typename vovocov_t::sf4_type sf4_type; - typedef typename node_type::T0 T0; - typedef typename node_type::T1 T1; - typedef typename node_type::T2 T2; - typedef typename node_type::T3 T3; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // ((v0 o0 v1) o1 c) o2 v2 - typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t; - - const lcl_vovoc_t* vovoc = static_cast(branch[0]); - const Type& v0 = vovoc->t0(); - const Type& v1 = vovoc->t1(); - const Type c = vovoc->t2(); - const Type& v2 = static_cast*>(branch[1])->ref(); - const details::operator_type o0 = expr_gen.get_operator(vovoc->f0()); - const details::operator_type o1 = expr_gen.get_operator(vovoc->f1()); - const details::operator_type o2 = operation; - - binary_functor_t f0 = vovoc->f0(); - binary_functor_t f1 = vovoc->f1(); - binary_functor_t f2 = reinterpret_cast(0); - - details::free_node(*(expr_gen.node_allocator_),branch[0]); - - expression_node_ptr result = error_node(); - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o2,f2)) - return error_node(); - - exprtk_debug(("((v0 o0 v1) o1 c) o2 v2\n")); - - return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1, - const details::operator_type o2) - { - return details::build_string() - << "((t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t"; - } - }; - - struct synthesize_vocovov_expression3 - { - typedef typename vocovov_t::type3 node_type; - typedef typename vocovov_t::sf4_type sf4_type; - typedef typename node_type::T0 T0; - typedef typename node_type::T1 T1; - typedef typename node_type::T2 T2; - typedef typename node_type::T3 T3; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // ((v0 o0 c) o1 v1) o2 v2 - typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t; - - const lcl_vocov_t* vocov = static_cast(branch[0]); - const Type& v0 = vocov->t0(); - const Type c = vocov->t1(); - const Type& v1 = vocov->t2(); - const Type& v2 = static_cast*>(branch[1])->ref(); - const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); - const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); - const details::operator_type o2 = operation; - - binary_functor_t f0 = vocov->f0(); - binary_functor_t f1 = vocov->f1(); - binary_functor_t f2 = reinterpret_cast(0); - - details::free_node(*(expr_gen.node_allocator_),branch[0]); - - expression_node_ptr result = error_node(); - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o2,f2)) - return error_node(); - - exprtk_debug(("((v0 o0 c) o1 v1) o2 v2\n")); - - return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1, - const details::operator_type o2) - { - return details::build_string() - << "((t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t"; - } - }; - - struct synthesize_covovov_expression3 - { - typedef typename covovov_t::type3 node_type; - typedef typename covovov_t::sf4_type sf4_type; - typedef typename node_type::T0 T0; - typedef typename node_type::T1 T1; - typedef typename node_type::T2 T2; - typedef typename node_type::T3 T3; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // ((c o0 v0) o1 v1) o2 v2 - typedef typename synthesize_covov_expression0::node_type lcl_covov_t; - - const lcl_covov_t* covov = static_cast(branch[0]); - const Type c = covov->t0(); - const Type& v0 = covov->t1(); - const Type& v1 = covov->t2(); - const Type& v2 = static_cast*>(branch[1])->ref(); - const details::operator_type o0 = expr_gen.get_operator(covov->f0()); - const details::operator_type o1 = expr_gen.get_operator(covov->f1()); - const details::operator_type o2 = operation; - - binary_functor_t f0 = covov->f0(); - binary_functor_t f1 = covov->f1(); - binary_functor_t f2 = reinterpret_cast(0); - - details::free_node(*(expr_gen.node_allocator_),branch[0]); - - expression_node_ptr result = error_node(); - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o2,f2)) - return error_node(); - - exprtk_debug(("((c o0 v0) o1 v1) o2 v2\n")); - - return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1, - const details::operator_type o2) - { - return details::build_string() - << "((t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t"; - } - }; - - struct synthesize_covocov_expression3 - { - typedef typename covocov_t::type3 node_type; - typedef typename covocov_t::sf4_type sf4_type; - typedef typename node_type::T0 T0; - typedef typename node_type::T1 T1; - typedef typename node_type::T2 T2; - typedef typename node_type::T3 T3; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // ((c0 o0 v0) o1 c1) o2 v1 - typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t; - - const lcl_covoc_t* covoc = static_cast(branch[0]); - const Type c0 = covoc->t0(); - const Type& v0 = covoc->t1(); - const Type c1 = covoc->t2(); - const Type& v1 = static_cast*>(branch[1])->ref(); - const details::operator_type o0 = expr_gen.get_operator(covoc->f0()); - const details::operator_type o1 = expr_gen.get_operator(covoc->f1()); - const details::operator_type o2 = operation; - - binary_functor_t f0 = covoc->f0(); - binary_functor_t f1 = covoc->f1(); - binary_functor_t f2 = reinterpret_cast(0); - - details::free_node(*(expr_gen.node_allocator_),branch[0]); - - expression_node_ptr result = error_node(); - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o2,f2)) - return error_node(); - - exprtk_debug(("((c0 o0 v0) o1 c1) o2 v1\n")); - - return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1, - const details::operator_type o2) - { - return details::build_string() - << "((t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t"; - } - }; - - struct synthesize_vocovoc_expression3 - { - typedef typename vocovoc_t::type3 node_type; - typedef typename vocovoc_t::sf4_type sf4_type; - typedef typename node_type::T0 T0; - typedef typename node_type::T1 T1; - typedef typename node_type::T2 T2; - typedef typename node_type::T3 T3; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // ((v0 o0 c0) o1 v1) o2 c1 - typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t; - - const lcl_vocov_t* vocov = static_cast(branch[0]); - const Type& v0 = vocov->t0(); - const Type c0 = vocov->t1(); - const Type& v1 = vocov->t2(); - const Type c1 = static_cast*>(branch[1])->value(); - const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); - const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); - const details::operator_type o2 = operation; - - binary_functor_t f0 = vocov->f0(); - binary_functor_t f1 = vocov->f1(); - binary_functor_t f2 = reinterpret_cast(0); - - details::free_node(*(expr_gen.node_allocator_),branch[0]); - details::free_node(*(expr_gen.node_allocator_),branch[1]); - - expression_node_ptr result = error_node(); - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o2,f2)) - return error_node(); - - exprtk_debug(("((v0 o0 c0) o1 v1) o2 c1\n")); - - return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1, - const details::operator_type o2) - { - return details::build_string() - << "((t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t"; - } - }; - - struct synthesize_covovoc_expression3 - { - typedef typename covovoc_t::type3 node_type; - typedef typename covovoc_t::sf4_type sf4_type; - typedef typename node_type::T0 T0; - typedef typename node_type::T1 T1; - typedef typename node_type::T2 T2; - typedef typename node_type::T3 T3; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // ((c0 o0 v0) o1 v1) o2 c1 - typedef typename synthesize_covov_expression0::node_type lcl_covov_t; - - const lcl_covov_t* covov = static_cast(branch[0]); - const Type c0 = covov->t0(); - const Type& v0 = covov->t1(); - const Type& v1 = covov->t2(); - const Type c1 = static_cast*>(branch[1])->value(); - const details::operator_type o0 = expr_gen.get_operator(covov->f0()); - const details::operator_type o1 = expr_gen.get_operator(covov->f1()); - const details::operator_type o2 = operation; - - binary_functor_t f0 = covov->f0(); - binary_functor_t f1 = covov->f1(); - binary_functor_t f2 = reinterpret_cast(0); - - details::free_node(*(expr_gen.node_allocator_),branch[0]); - details::free_node(*(expr_gen.node_allocator_),branch[1]); - - expression_node_ptr result = error_node(); - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o2,f2)) - return error_node(); - - exprtk_debug(("((c0 o0 v0) o1 v1) o2 c1\n")); - - return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1, - const details::operator_type o2) - { - return details::build_string() - << "((t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t"; - } - }; - - struct synthesize_vococov_expression3 - { - typedef typename vococov_t::type3 node_type; - typedef typename vococov_t::sf4_type sf4_type; - typedef typename node_type::T0 T0; - typedef typename node_type::T1 T1; - typedef typename node_type::T2 T2; - typedef typename node_type::T3 T3; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // ((v0 o0 c0) o1 c1) o2 v1 - typedef typename synthesize_vococ_expression0::node_type lcl_vococ_t; - - const lcl_vococ_t* vococ = static_cast(branch[0]); - const Type& v0 = vococ->t0(); - const Type c0 = vococ->t1(); - const Type c1 = vococ->t2(); - const Type& v1 = static_cast*>(branch[1])->ref(); - const details::operator_type o0 = expr_gen.get_operator(vococ->f0()); - const details::operator_type o1 = expr_gen.get_operator(vococ->f1()); - const details::operator_type o2 = operation; - - binary_functor_t f0 = vococ->f0(); - binary_functor_t f1 = vococ->f1(); - binary_functor_t f2 = reinterpret_cast(0); - - details::free_node(*(expr_gen.node_allocator_),branch[0]); - - expression_node_ptr result = error_node(); - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o2,f2)) - return error_node(); - - exprtk_debug(("((v0 o0 c0) o1 c1) o2 v1\n")); - - return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1, - const details::operator_type o2) - { - return details::build_string() - << "((t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t"; - } - }; - - struct synthesize_vovovov_expression4 - { - typedef typename vovovov_t::type4 node_type; - typedef typename vovovov_t::sf4_type sf4_type; - typedef typename node_type::T0 T0; - typedef typename node_type::T1 T1; - typedef typename node_type::T2 T2; - typedef typename node_type::T3 T3; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // (v0 o0 (v1 o1 v2)) o2 v3 - typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t; - - const lcl_vovov_t* vovov = static_cast(branch[0]); - const Type& v0 = vovov->t0(); - const Type& v1 = vovov->t1(); - const Type& v2 = vovov->t2(); - const Type& v3 = static_cast*>(branch[1])->ref(); - const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); - const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); - const details::operator_type o2 = operation; - - binary_functor_t f0 = vovov->f0(); - binary_functor_t f1 = vovov->f1(); - binary_functor_t f2 = reinterpret_cast(0); - - details::free_node(*(expr_gen.node_allocator_),branch[0]); - - expression_node_ptr result = error_node(); - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o2,f2)) - return error_node(); - - exprtk_debug(("(v0 o0 (v1 o1 v2)) o2 v3\n")); - - return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1, - const details::operator_type o2) - { - return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t"; - } - }; - - struct synthesize_vovovoc_expression4 - { - typedef typename vovovoc_t::type4 node_type; - typedef typename vovovoc_t::sf4_type sf4_type; - typedef typename node_type::T0 T0; - typedef typename node_type::T1 T1; - typedef typename node_type::T2 T2; - typedef typename node_type::T3 T3; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // ((v0 o0 (v1 o1 v2)) o2 c) - typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t; - - const lcl_vovov_t* vovov = static_cast(branch[0]); - const Type& v0 = vovov->t0(); - const Type& v1 = vovov->t1(); - const Type& v2 = vovov->t2(); - const Type c = static_cast*>(branch[1])->value(); - const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); - const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); - const details::operator_type o2 = operation; - - binary_functor_t f0 = vovov->f0(); - binary_functor_t f1 = vovov->f1(); - binary_functor_t f2 = reinterpret_cast(0); - - details::free_node(*(expr_gen.node_allocator_),branch[0]); - details::free_node(*(expr_gen.node_allocator_),branch[1]); - - expression_node_ptr result = error_node(); - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o2,f2)) - return error_node(); - - exprtk_debug(("((v0 o0 (v1 o1 v2)) o2 c)\n")); - - return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1, - const details::operator_type o2) - { - return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t"; - } - }; - - struct synthesize_vovocov_expression4 - { - typedef typename vovocov_t::type4 node_type; - typedef typename vovocov_t::sf4_type sf4_type; - typedef typename node_type::T0 T0; - typedef typename node_type::T1 T1; - typedef typename node_type::T2 T2; - typedef typename node_type::T3 T3; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // ((v0 o0 (v1 o1 c)) o2 v1) - typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t; - - const lcl_vovoc_t* vovoc = static_cast(branch[0]); - const Type& v0 = vovoc->t0(); - const Type& v1 = vovoc->t1(); - const Type c = vovoc->t2(); - const Type& v2 = static_cast*>(branch[1])->ref(); - const details::operator_type o0 = expr_gen.get_operator(vovoc->f0()); - const details::operator_type o1 = expr_gen.get_operator(vovoc->f1()); - const details::operator_type o2 = operation; - - binary_functor_t f0 = vovoc->f0(); - binary_functor_t f1 = vovoc->f1(); - binary_functor_t f2 = reinterpret_cast(0); - - details::free_node(*(expr_gen.node_allocator_),branch[0]); - - expression_node_ptr result = error_node(); - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o2,f2)) - return error_node(); - - exprtk_debug(("((v0 o0 (v1 o1 c)) o2 v1)\n")); - - return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1, - const details::operator_type o2) - { - return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t"; - } - }; - - struct synthesize_vocovov_expression4 - { - typedef typename vocovov_t::type4 node_type; - typedef typename vocovov_t::sf4_type sf4_type; - typedef typename node_type::T0 T0; - typedef typename node_type::T1 T1; - typedef typename node_type::T2 T2; - typedef typename node_type::T3 T3; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // ((v0 o0 (c o1 v1)) o2 v2) - typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t; - - const lcl_vocov_t* vocov = static_cast(branch[0]); - const Type& v0 = vocov->t0(); - const Type c = vocov->t1(); - const Type& v1 = vocov->t2(); - const Type& v2 = static_cast*>(branch[1])->ref(); - const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); - const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); - const details::operator_type o2 = operation; - - binary_functor_t f0 = vocov->f0(); - binary_functor_t f1 = vocov->f1(); - binary_functor_t f2 = reinterpret_cast(0); - - details::free_node(*(expr_gen.node_allocator_),branch[0]); - expression_node_ptr result = error_node(); - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o2,f2)) - return error_node(); - - exprtk_debug(("((v0 o0 (c o1 v1)) o2 v2)\n")); - - return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1, - const details::operator_type o2) - { - return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t"; - } - }; - - struct synthesize_covovov_expression4 - { - typedef typename covovov_t::type4 node_type; - typedef typename covovov_t::sf4_type sf4_type; - typedef typename node_type::T0 T0; - typedef typename node_type::T1 T1; - typedef typename node_type::T2 T2; - typedef typename node_type::T3 T3; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // ((c o0 (v0 o1 v1)) o2 v2) - typedef typename synthesize_covov_expression1::node_type lcl_covov_t; - - const lcl_covov_t* covov = static_cast(branch[0]); - const Type c = covov->t0(); - const Type& v0 = covov->t1(); - const Type& v1 = covov->t2(); - const Type& v2 = static_cast*>(branch[1])->ref(); - const details::operator_type o0 = expr_gen.get_operator(covov->f0()); - const details::operator_type o1 = expr_gen.get_operator(covov->f1()); - const details::operator_type o2 = operation; - - binary_functor_t f0 = covov->f0(); - binary_functor_t f1 = covov->f1(); - binary_functor_t f2 = reinterpret_cast(0); - - details::free_node(*(expr_gen.node_allocator_),branch[0]); - - expression_node_ptr result = error_node(); - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o2,f2)) - return error_node(); - - exprtk_debug(("((c o0 (v0 o1 v1)) o2 v2)\n")); - - return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1, - const details::operator_type o2) - { - return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t"; - } - }; - - struct synthesize_covocov_expression4 - { - typedef typename covocov_t::type4 node_type; - typedef typename covocov_t::sf4_type sf4_type; - typedef typename node_type::T0 T0; - typedef typename node_type::T1 T1; - typedef typename node_type::T2 T2; - typedef typename node_type::T3 T3; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // ((c0 o0 (v0 o1 c1)) o2 v1) - typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t; - - const lcl_covoc_t* covoc = static_cast(branch[0]); - const Type c0 = covoc->t0(); - const Type& v0 = covoc->t1(); - const Type c1 = covoc->t2(); - const Type& v1 = static_cast*>(branch[1])->ref(); - const details::operator_type o0 = expr_gen.get_operator(covoc->f0()); - const details::operator_type o1 = expr_gen.get_operator(covoc->f1()); - const details::operator_type o2 = operation; - - binary_functor_t f0 = covoc->f0(); - binary_functor_t f1 = covoc->f1(); - binary_functor_t f2 = reinterpret_cast(0); - - details::free_node(*(expr_gen.node_allocator_),branch[0]); - - expression_node_ptr result = error_node(); - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o2,f2)) - return error_node(); - - exprtk_debug(("((c0 o0 (v0 o1 c1)) o2 v1)\n")); - - return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1, - const details::operator_type o2) - { - return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t"; - } - }; - - struct synthesize_vocovoc_expression4 - { - typedef typename vocovoc_t::type4 node_type; - typedef typename vocovoc_t::sf4_type sf4_type; - typedef typename node_type::T0 T0; - typedef typename node_type::T1 T1; - typedef typename node_type::T2 T2; - typedef typename node_type::T3 T3; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // ((v0 o0 (c0 o1 v1)) o2 c1) - typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t; - - const lcl_vocov_t* vocov = static_cast(branch[0]); - const Type& v0 = vocov->t0(); - const Type c0 = vocov->t1(); - const Type& v1 = vocov->t2(); - const Type c1 = static_cast*>(branch[1])->value(); - const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); - const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); - const details::operator_type o2 = operation; - - binary_functor_t f0 = vocov->f0(); - binary_functor_t f1 = vocov->f1(); - binary_functor_t f2 = reinterpret_cast(0); - - details::free_node(*(expr_gen.node_allocator_),branch[0]); - details::free_node(*(expr_gen.node_allocator_),branch[1]); - - expression_node_ptr result = error_node(); - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o2,f2)) - return error_node(); - - exprtk_debug(("((v0 o0 (c0 o1 v1)) o2 c1)\n")); - - return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1, - const details::operator_type o2) - { - return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t"; - } - }; - - struct synthesize_covovoc_expression4 - { - typedef typename covovoc_t::type4 node_type; - typedef typename covovoc_t::sf4_type sf4_type; - typedef typename node_type::T0 T0; - typedef typename node_type::T1 T1; - typedef typename node_type::T2 T2; - typedef typename node_type::T3 T3; - - static inline expression_node_ptr process(expression_generator& expr_gen, - const details::operator_type& operation, - expression_node_ptr (&branch)[2]) - { - // ((c0 o0 (v0 o1 v1)) o2 c1) - typedef typename synthesize_covov_expression1::node_type lcl_covov_t; - - const lcl_covov_t* covov = static_cast(branch[0]); - const Type c0 = covov->t0(); - const Type& v0 = covov->t1(); - const Type& v1 = covov->t2(); - const Type c1 = static_cast*>(branch[1])->value(); - const details::operator_type o0 = expr_gen.get_operator(covov->f0()); - const details::operator_type o1 = expr_gen.get_operator(covov->f1()); - const details::operator_type o2 = operation; - - binary_functor_t f0 = covov->f0(); - binary_functor_t f1 = covov->f1(); - binary_functor_t f2 = reinterpret_cast(0); - - details::free_node(*(expr_gen.node_allocator_),branch[0]); - details::free_node(*(expr_gen.node_allocator_),branch[1]); - - expression_node_ptr result = error_node(); - - const bool synthesis_result = - synthesize_sf4ext_expression::template compile - (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); - - if (synthesis_result) - return result; - else if (!expr_gen.valid_operator(o2,f2)) - return error_node(); - - exprtk_debug(("((c0 o0 (v0 o1 v1)) o2 c1)\n")); - - return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); - } - - static inline std::string id(expression_generator& expr_gen, - const details::operator_type o0, - const details::operator_type o1, - const details::operator_type o2) - { - return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t"; - } - }; - - struct synthesize_vococov_expression4 - { - typedef typename vococov_t::type4 node_type; - static inline expression_node_ptr process(expression_generator&, const details::operator_type&, expression_node_ptr (&)[2]) - { - // ((v0 o0 (c0 o1 c1)) o2 v1) - Not possible - exprtk_debug(("((v0 o0 (c0 o1 c1)) o2 v1) - Not possible\n")); - return error_node(); - } - - static inline std::string id(expression_generator&, - const details::operator_type, const details::operator_type, const details::operator_type) - { - return "INVALID"; - } - }; - #endif - - inline expression_node_ptr synthesize_uvouv_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) - { - // Definition: uv o uv - details::operator_type o0 = static_cast*>(branch[0])->operation(); - details::operator_type o1 = static_cast*>(branch[1])->operation(); - const Type& v0 = static_cast*>(branch[0])->v(); - const Type& v1 = static_cast*>(branch[1])->v(); - unary_functor_t u0 = reinterpret_cast (0); - unary_functor_t u1 = reinterpret_cast (0); - binary_functor_t f = reinterpret_cast(0); - - if (!valid_operator(o0,u0)) - return error_node(); - else if (!valid_operator(o1,u1)) - return error_node(); - else if (!valid_operator(operation,f)) - return error_node(); - - expression_node_ptr result = error_node(); - - if ( - (details::e_neg == o0) && - (details::e_neg == o1) - ) - { - switch (operation) - { - // (-v0 + -v1) --> -(v0 + v1) - case details::e_add : result = (*this)(details::e_neg, - node_allocator_-> - allocate_rr > >(v0, v1)); - exprtk_debug(("(-v0 + -v1) --> -(v0 + v1)\n")); - break; - - // (-v0 - -v1) --> (v1 - v0) - case details::e_sub : result = node_allocator_-> - allocate_rr > >(v1, v0); - exprtk_debug(("(-v0 - -v1) --> (v1 - v0)\n")); - break; - - // (-v0 * -v1) --> (v0 * v1) - case details::e_mul : result = node_allocator_-> - allocate_rr > >(v0, v1); - exprtk_debug(("(-v0 * -v1) --> (v0 * v1)\n")); - break; - - // (-v0 / -v1) --> (v0 / v1) - case details::e_div : result = node_allocator_-> - allocate_rr > >(v0, v1); - exprtk_debug(("(-v0 / -v1) --> (v0 / v1)\n")); - break; - - default : break; - } - } - - if (0 == result) - { - result = node_allocator_-> - allocate_rrrrr >(v0, v1, u0, u1, f); - } - - details::free_all_nodes(*node_allocator_,branch); - return result; - } - - #undef basic_opr_switch_statements - #undef extended_opr_switch_statements - #undef unary_opr_switch_statements - - #ifndef exprtk_disable_string_capabilities - - #define string_opr_switch_statements \ - case_stmt(details::e_lt , details::lt_op ) \ - case_stmt(details::e_lte , details::lte_op ) \ - case_stmt(details::e_gt , details::gt_op ) \ - case_stmt(details::e_gte , details::gte_op ) \ - case_stmt(details::e_eq , details::eq_op ) \ - case_stmt(details::e_ne , details::ne_op ) \ - case_stmt(details::e_in , details::in_op ) \ - case_stmt(details::e_like , details::like_op ) \ - case_stmt(details::e_ilike , details::ilike_op) \ - - template - inline expression_node_ptr synthesize_str_xrox_expression_impl(const details::operator_type& opr, - T0 s0, T1 s1, - range_t rp0) - { - switch (opr) - { - #define case_stmt(op0,op1) \ - case op0 : return node_allocator_-> \ - allocate_ttt >,T0,T1> \ - (s0, s1, rp0); \ - - string_opr_switch_statements - #undef case_stmt - default : return error_node(); - } - } - - template - inline expression_node_ptr synthesize_str_xoxr_expression_impl(const details::operator_type& opr, - T0 s0, T1 s1, - range_t rp1) - { - switch (opr) - { - #define case_stmt(op0,op1) \ - case op0 : return node_allocator_-> \ - allocate_ttt >,T0,T1> \ - (s0, s1, rp1); \ - - string_opr_switch_statements - #undef case_stmt - default : return error_node(); - } - } - - template - inline expression_node_ptr synthesize_str_xroxr_expression_impl(const details::operator_type& opr, - T0 s0, T1 s1, - range_t rp0, range_t rp1) - { - switch (opr) - { - #define case_stmt(op0,op1) \ - case op0 : return node_allocator_-> \ - allocate_tttt >,T0,T1> \ - (s0, s1, rp0, rp1); \ - - string_opr_switch_statements - #undef case_stmt - default : return error_node(); - } - } - - template - inline expression_node_ptr synthesize_sos_expression_impl(const details::operator_type& opr, T0 s0, T1 s1) - { - switch (opr) - { - #define case_stmt(op0,op1) \ - case op0 : return node_allocator_-> \ - allocate_tt >,T0,T1>(s0, s1); \ - - string_opr_switch_statements - #undef case_stmt - default : return error_node(); - } - } - - inline expression_node_ptr synthesize_sos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) - { - std::string& s0 = static_cast*>(branch[0])->ref(); - std::string& s1 = static_cast*>(branch[1])->ref(); - - return synthesize_sos_expression_impl(opr, s0, s1); - } - - inline expression_node_ptr synthesize_sros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) - { - std::string& s0 = static_cast*>(branch[0])->ref (); - std::string& s1 = static_cast*> (branch[1])->ref (); - range_t rp0 = static_cast*>(branch[0])->range(); - - static_cast*>(branch[0])->range_ref().clear(); - - free_node(*node_allocator_,branch[0]); - - return synthesize_str_xrox_expression_impl(opr, s0, s1, rp0); - } - - inline expression_node_ptr synthesize_sosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) - { - std::string& s0 = static_cast*> (branch[0])->ref (); - std::string& s1 = static_cast*>(branch[1])->ref (); - range_t rp1 = static_cast*>(branch[1])->range(); - - static_cast*>(branch[1])->range_ref().clear(); - - free_node(*node_allocator_,branch[1]); - - return synthesize_str_xoxr_expression_impl(opr, s0, s1, rp1); - } - - inline expression_node_ptr synthesize_socsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) - { - std::string& s0 = static_cast*> (branch[0])->ref (); - std::string s1 = static_cast*>(branch[1])->str (); - range_t rp1 = static_cast*>(branch[1])->range(); - - static_cast*>(branch[1])->range_ref().clear(); - - free_node(*node_allocator_,branch[1]); - - return synthesize_str_xoxr_expression_impl(opr, s0, s1, rp1); - } - - inline expression_node_ptr synthesize_srosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) - { - std::string& s0 = static_cast*>(branch[0])->ref (); - std::string& s1 = static_cast*>(branch[1])->ref (); - range_t rp0 = static_cast*>(branch[0])->range(); - range_t rp1 = static_cast*>(branch[1])->range(); - - static_cast*>(branch[0])->range_ref().clear(); - static_cast*>(branch[1])->range_ref().clear(); - - details::free_node(*node_allocator_,branch[0]); - details::free_node(*node_allocator_,branch[1]); - - return synthesize_str_xroxr_expression_impl(opr, s0, s1, rp0, rp1); - } - - inline expression_node_ptr synthesize_socs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) - { - std::string& s0 = static_cast< details::stringvar_node*>(branch[0])->ref(); - std::string s1 = static_cast*>(branch[1])->str(); - - details::free_node(*node_allocator_,branch[1]); - - return synthesize_sos_expression_impl(opr, s0, s1); - } - - inline expression_node_ptr synthesize_csos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) - { - std::string s0 = static_cast*>(branch[0])->str(); - std::string& s1 = static_cast< details::stringvar_node*>(branch[1])->ref(); - - details::free_node(*node_allocator_,branch[0]); - - return synthesize_sos_expression_impl(opr, s0, s1); - } - - inline expression_node_ptr synthesize_csosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) - { - std::string s0 = static_cast*>(branch[0])->str (); - std::string& s1 = static_cast*> (branch[1])->ref (); - range_t rp1 = static_cast*> (branch[1])->range(); - - static_cast*>(branch[1])->range_ref().clear(); - - details::free_node(*node_allocator_,branch[0]); - details::free_node(*node_allocator_,branch[1]); - - return synthesize_str_xoxr_expression_impl(opr, s0, s1, rp1); - } - - inline expression_node_ptr synthesize_srocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) - { - std::string& s0 = static_cast*> (branch[0])->ref (); - std::string s1 = static_cast*>(branch[1])->str (); - range_t rp0 = static_cast*> (branch[0])->range(); - - static_cast*>(branch[0])->range_ref().clear(); - - details::free_node(*node_allocator_,branch[0]); - details::free_node(*node_allocator_,branch[1]); - - return synthesize_str_xrox_expression_impl(opr, s0, s1, rp0); - } - - inline expression_node_ptr synthesize_srocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) - { - std::string& s0 = static_cast*> (branch[0])->ref (); - std::string s1 = static_cast*>(branch[1])->str (); - range_t rp0 = static_cast*> (branch[0])->range(); - range_t rp1 = static_cast*>(branch[1])->range(); - - static_cast*> (branch[0])->range_ref().clear(); - static_cast*>(branch[1])->range_ref().clear(); - - details::free_node(*node_allocator_,branch[0]); - details::free_node(*node_allocator_,branch[1]); - - return synthesize_str_xroxr_expression_impl(opr, s0, s1, rp0, rp1); - } - - inline expression_node_ptr synthesize_csocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) - { - const std::string s0 = static_cast*>(branch[0])->str(); - const std::string s1 = static_cast*>(branch[1])->str(); - - expression_node_ptr result = error_node(); - - if (details::e_add == opr) - result = node_allocator_->allocate_c >(s0 + s1); - else if (details::e_in == opr) - result = node_allocator_->allocate_c >(details::in_op ::process(s0,s1)); - else if (details::e_like == opr) - result = node_allocator_->allocate_c >(details::like_op ::process(s0,s1)); - else if (details::e_ilike == opr) - result = node_allocator_->allocate_c >(details::ilike_op::process(s0,s1)); - else - { - expression_node_ptr temp = synthesize_sos_expression_impl(opr, s0, s1); - - const Type v = temp->value(); - - details::free_node(*node_allocator_,temp); - - result = node_allocator_->allocate(v); - } - - details::free_all_nodes(*node_allocator_,branch); - - return result; - } - - inline expression_node_ptr synthesize_csocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) - { - const std::string s0 = static_cast*> (branch[0])->str (); - std::string s1 = static_cast*>(branch[1])->str (); - range_t rp1 = static_cast*>(branch[1])->range(); - - static_cast*>(branch[1])->range_ref().clear(); - - free_node(*node_allocator_,branch[0]); - free_node(*node_allocator_,branch[1]); - - return synthesize_str_xoxr_expression_impl(opr, s0, s1, rp1); - } - - inline expression_node_ptr synthesize_csros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) - { - std::string s0 = static_cast*>(branch[0])->str (); - std::string& s1 = static_cast*> (branch[1])->ref (); - range_t rp0 = static_cast*>(branch[0])->range(); - - static_cast*>(branch[0])->range_ref().clear(); - - free_node(*node_allocator_,branch[0]); - - return synthesize_str_xrox_expression_impl(opr, s0, s1, rp0); - } - - inline expression_node_ptr synthesize_csrosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) - { - const std::string s0 = static_cast*>(branch[0])->str (); - std::string& s1 = static_cast*> (branch[1])->ref (); - const range_t rp0 = static_cast*>(branch[0])->range(); - const range_t rp1 = static_cast*> (branch[1])->range(); - - static_cast*>(branch[0])->range_ref().clear(); - static_cast*> (branch[1])->range_ref().clear(); - - free_node(*node_allocator_,branch[0]); - free_node(*node_allocator_,branch[1]); - - return synthesize_str_xroxr_expression_impl(opr, s0, s1, rp0, rp1); - } - - inline expression_node_ptr synthesize_csrocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) - { - const std::string s0 = static_cast*>(branch[0])->str (); - const std::string s1 = static_cast*> (branch[1])->str (); - const range_t rp0 = static_cast*>(branch[0])->range(); - - static_cast*>(branch[0])->range_ref().clear(); - - details::free_all_nodes(*node_allocator_,branch); - - return synthesize_str_xrox_expression_impl(opr, s0, s1, rp0); - } - - inline expression_node_ptr synthesize_csrocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) - { - const std::string s0 = static_cast*>(branch[0])->str (); - const std::string s1 = static_cast*>(branch[1])->str (); - const range_t rp0 = static_cast*>(branch[0])->range(); - const range_t rp1 = static_cast*>(branch[1])->range(); - - static_cast*>(branch[0])->range_ref().clear(); - static_cast*>(branch[1])->range_ref().clear(); - - details::free_all_nodes(*node_allocator_,branch); - - return synthesize_str_xroxr_expression_impl(opr, s0, s1, rp0, rp1); - } - - inline expression_node_ptr synthesize_strogen_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) - { - switch (opr) - { - #define case_stmt(op0,op1) \ - case op0 : return node_allocator_-> \ - allocate_ttt > > \ - (opr, branch[0], branch[1]); \ - - string_opr_switch_statements - #undef case_stmt - default : return error_node(); - } - } - #endif - - #ifndef exprtk_disable_string_capabilities - inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) - { - if ((0 == branch[0]) || (0 == branch[1])) - { - details::free_all_nodes(*node_allocator_,branch); - - return error_node(); - } - - const bool b0_is_s = details::is_string_node (branch[0]); - const bool b0_is_cs = details::is_const_string_node (branch[0]); - const bool b0_is_sr = details::is_string_range_node (branch[0]); - const bool b0_is_csr = details::is_const_string_range_node(branch[0]); - - const bool b1_is_s = details::is_string_node (branch[1]); - const bool b1_is_cs = details::is_const_string_node (branch[1]); - const bool b1_is_sr = details::is_string_range_node (branch[1]); - const bool b1_is_csr = details::is_const_string_range_node(branch[1]); - - const bool b0_is_gen = details::is_string_assignment_node (branch[0]) || - details::is_genricstring_range_node(branch[0]) || - details::is_string_concat_node (branch[0]) || - details::is_string_function_node (branch[0]) || - details::is_string_condition_node (branch[0]) || - details::is_string_ccondition_node (branch[0]) || - details::is_string_vararg_node (branch[0]) ; - - const bool b1_is_gen = details::is_string_assignment_node (branch[1]) || - details::is_genricstring_range_node(branch[1]) || - details::is_string_concat_node (branch[1]) || - details::is_string_function_node (branch[1]) || - details::is_string_condition_node (branch[1]) || - details::is_string_ccondition_node (branch[1]) || - details::is_string_vararg_node (branch[1]) ; - - if (details::e_add == opr) - { - if (!b0_is_cs || !b1_is_cs) - { - return synthesize_expression(opr,branch); - } - } - - if (b0_is_gen || b1_is_gen) - { - return synthesize_strogen_expression(opr,branch); - } - else if (b0_is_s) - { - if (b1_is_s ) return synthesize_sos_expression (opr,branch); - else if (b1_is_cs ) return synthesize_socs_expression (opr,branch); - else if (b1_is_sr ) return synthesize_sosr_expression (opr,branch); - else if (b1_is_csr) return synthesize_socsr_expression (opr,branch); - } - else if (b0_is_cs) - { - if (b1_is_s ) return synthesize_csos_expression (opr,branch); - else if (b1_is_cs ) return synthesize_csocs_expression (opr,branch); - else if (b1_is_sr ) return synthesize_csosr_expression (opr,branch); - else if (b1_is_csr) return synthesize_csocsr_expression(opr,branch); - } - else if (b0_is_sr) - { - if (b1_is_s ) return synthesize_sros_expression (opr,branch); - else if (b1_is_sr ) return synthesize_srosr_expression (opr,branch); - else if (b1_is_cs ) return synthesize_srocs_expression (opr,branch); - else if (b1_is_csr) return synthesize_srocsr_expression(opr,branch); - } - else if (b0_is_csr) - { - if (b1_is_s ) return synthesize_csros_expression (opr,branch); - else if (b1_is_sr ) return synthesize_csrosr_expression (opr,branch); - else if (b1_is_cs ) return synthesize_csrocs_expression (opr,branch); - else if (b1_is_csr) return synthesize_csrocsr_expression(opr,branch); - } - - return error_node(); - } - #else - inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[2]) - { - details::free_all_nodes(*node_allocator_,branch); - return error_node(); - } - #endif - - #ifndef exprtk_disable_string_capabilities - inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[3]) - { - if (details::e_inrange != opr) - return error_node(); - else if ((0 == branch[0]) || (0 == branch[1]) || (0 == branch[2])) - { - details::free_all_nodes(*node_allocator_,branch); - - return error_node(); - } - else if ( - details::is_const_string_node(branch[0]) && - details::is_const_string_node(branch[1]) && - details::is_const_string_node(branch[2]) - ) - { - const std::string s0 = static_cast*>(branch[0])->str(); - const std::string s1 = static_cast*>(branch[1])->str(); - const std::string s2 = static_cast*>(branch[2])->str(); - - const Type v = (((s0 <= s1) && (s1 <= s2)) ? Type(1) : Type(0)); - - details::free_all_nodes(*node_allocator_,branch); - - return node_allocator_->allocate_c >(v); - } - else if ( - details::is_string_node(branch[0]) && - details::is_string_node(branch[1]) && - details::is_string_node(branch[2]) - ) - { - std::string& s0 = static_cast*>(branch[0])->ref(); - std::string& s1 = static_cast*>(branch[1])->ref(); - std::string& s2 = static_cast*>(branch[2])->ref(); - - typedef typename details::sosos_node > inrange_t; - - return node_allocator_->allocate_type(s0, s1, s2); - } - else if ( - details::is_const_string_node(branch[0]) && - details::is_string_node(branch[1]) && - details::is_const_string_node(branch[2]) - ) - { - std::string s0 = static_cast*>(branch[0])->str(); - std::string& s1 = static_cast< details::stringvar_node*>(branch[1])->ref(); - std::string s2 = static_cast*>(branch[2])->str(); - - typedef typename details::sosos_node > inrange_t; - - details::free_node(*node_allocator_,branch[0]); - details::free_node(*node_allocator_,branch[2]); - - return node_allocator_->allocate_type(s0, s1, s2); - } - else if ( - details::is_string_node(branch[0]) && - details::is_const_string_node(branch[1]) && - details::is_string_node(branch[2]) - ) - { - std::string& s0 = static_cast< details::stringvar_node*>(branch[0])->ref(); - std::string s1 = static_cast*>(branch[1])->str(); - std::string& s2 = static_cast< details::stringvar_node*>(branch[2])->ref(); - - typedef typename details::sosos_node > inrange_t; - - details::free_node(*node_allocator_,branch[1]); - - return node_allocator_->allocate_type(s0, s1, s2); - } - else if ( - details::is_string_node(branch[0]) && - details::is_string_node(branch[1]) && - details::is_const_string_node(branch[2]) - ) - { - std::string& s0 = static_cast< details::stringvar_node*>(branch[0])->ref(); - std::string& s1 = static_cast< details::stringvar_node*>(branch[1])->ref(); - std::string s2 = static_cast*>(branch[2])->str(); - - typedef typename details::sosos_node > inrange_t; - - details::free_node(*node_allocator_,branch[2]); - - return node_allocator_->allocate_type(s0, s1, s2); - } - else if ( - details::is_const_string_node(branch[0]) && - details:: is_string_node(branch[1]) && - details:: is_string_node(branch[2]) - ) - { - std::string s0 = static_cast*>(branch[0])->str(); - std::string& s1 = static_cast< details::stringvar_node*>(branch[1])->ref(); - std::string& s2 = static_cast< details::stringvar_node*>(branch[2])->ref(); - - typedef typename details::sosos_node > inrange_t; - - details::free_node(*node_allocator_,branch[0]); - - return node_allocator_->allocate_type(s0, s1, s2); - } - else - return error_node(); - } - #else - inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[3]) - { - details::free_all_nodes(*node_allocator_,branch); - return error_node(); - } - #endif - - inline expression_node_ptr synthesize_null_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) - { - /* - Note: The following are the type promotion rules - that relate to operations that include 'null': - 0. null ==/!= null --> true false - 1. null operation null --> null - 2. x ==/!= null --> true/false - 3. null ==/!= x --> true/false - 4. x operation null --> x - 5. null operation x --> x - */ - - typedef typename details::null_eq_node nulleq_node_t; - - const bool b0_null = details::is_null_node(branch[0]); - const bool b1_null = details::is_null_node(branch[1]); - - if (b0_null && b1_null) - { - expression_node_ptr result = error_node(); - - if (details::e_eq == operation) - result = node_allocator_->allocate_c(T(1)); - else if (details::e_ne == operation) - result = node_allocator_->allocate_c(T(0)); - - if (result) - { - details::free_node(*node_allocator_,branch[0]); - details::free_node(*node_allocator_,branch[1]); - - return result; - } - - details::free_node(*node_allocator_,branch[1]); - - return branch[0]; - } - else if (details::e_eq == operation) - { - expression_node_ptr result = node_allocator_-> - allocate_rc(branch[b0_null ? 0 : 1],true); - - details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]); - - return result; - } - else if (details::e_ne == operation) - { - expression_node_ptr result = node_allocator_-> - allocate_rc(branch[b0_null ? 0 : 1],false); - - details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]); - - return result; - } - else if (b0_null) - { - details::free_node(*node_allocator_,branch[0]); - branch[0] = branch[1]; - branch[1] = error_node(); - } - else if (b1_null) - { - details::free_node(*node_allocator_,branch[1]); - branch[1] = error_node(); - } - - if ( - (details::e_add == operation) || (details::e_sub == operation) || - (details::e_mul == operation) || (details::e_div == operation) || - (details::e_mod == operation) || (details::e_pow == operation) - ) - { - return branch[0]; - } - - details::free_node(*node_allocator_, branch[0]); - - if ( - (details::e_lt == operation) || (details::e_lte == operation) || - (details::e_gt == operation) || (details::e_gte == operation) || - (details::e_and == operation) || (details::e_nand == operation) || - (details::e_or == operation) || (details::e_nor == operation) || - (details::e_xor == operation) || (details::e_xnor == operation) || - (details::e_in == operation) || (details::e_like == operation) || - (details::e_ilike == operation) - ) - { - return node_allocator_->allocate_c(T(0)); - } - - return node_allocator_->allocate >(); - } - - template - inline expression_node_ptr synthesize_expression(const details::operator_type& operation, expression_node_ptr (&branch)[N]) - { - if ( - (details::e_in == operation) || - (details::e_like == operation) || - (details::e_ilike == operation) - ) - { - free_all_nodes(*node_allocator_,branch); - - return error_node(); - } - else if (!details::all_nodes_valid(branch)) - { - free_all_nodes(*node_allocator_,branch); - - return error_node(); - } - else if ((details::e_default != operation)) - { - // Attempt simple constant folding optimisation. - expression_node_ptr expression_point = node_allocator_->allocate(operation,branch); - - if (is_constant_foldable(branch)) - { - const Type v = expression_point->value(); - details::free_node(*node_allocator_,expression_point); - - return node_allocator_->allocate(v); - } - else - return expression_point; - } - else - return error_node(); - } - - template - inline expression_node_ptr synthesize_expression(F* f, expression_node_ptr (&branch)[N]) - { - if (!details::all_nodes_valid(branch)) - { - free_all_nodes(*node_allocator_,branch); - - return error_node(); - } - - typedef typename details::function_N_node function_N_node_t; - - // Attempt simple constant folding optimisation. - - expression_node_ptr expression_point = node_allocator_->allocate(f); - function_N_node_t* func_node_ptr = dynamic_cast(expression_point); - - if (0 == func_node_ptr) - { - free_all_nodes(*node_allocator_,branch); - - return error_node(); - } - else - func_node_ptr->init_branches(branch); - - if (is_constant_foldable(branch) && !f->has_side_effects()) - { - Type v = expression_point->value(); - details::free_node(*node_allocator_,expression_point); - - return node_allocator_->allocate(v); - } - - parser_->state_.activate_side_effect("synthesize_expression(function)"); - - return expression_point; - } - - bool strength_reduction_enabled_; - details::node_allocator* node_allocator_; - synthesize_map_t synthesize_map_; - unary_op_map_t* unary_op_map_; - binary_op_map_t* binary_op_map_; - inv_binary_op_map_t* inv_binary_op_map_; - sf3_map_t* sf3_map_; - sf4_map_t* sf4_map_; - parser_t* parser_; - }; - - inline void set_error(const parser_error::type& error_type) - { - error_list_.push_back(error_type); - } - - inline void remove_last_error() - { - if (!error_list_.empty()) - { - error_list_.pop_back(); - } - } - - inline void set_synthesis_error(const std::string& synthesis_error_message) - { - if (synthesis_error_.empty()) - { - synthesis_error_ = synthesis_error_message; - } - } - - inline void register_local_vars(expression& e) - { - for (std::size_t i = 0; i < sem_.size(); ++i) - { - scope_element& se = sem_.get_element(i); - - if ( - (scope_element::e_variable == se.type) || - (scope_element::e_vecelem == se.type) - ) - { - if (se.var_node) - { - e.register_local_var(se.var_node); - } - - if (se.data) - { - e.register_local_data(se.data, 1, 0); - } - } - else if (scope_element::e_vector == se.type) - { - if (se.vec_node) - { - e.register_local_var(se.vec_node); - } - - if (se.data) - { - e.register_local_data(se.data, se.size, 1); - } - } - #ifndef exprtk_disable_string_capabilities - else if (scope_element::e_string == se.type) - { - if (se.str_node) - { - e.register_local_var(se.str_node); - } - - if (se.data) - { - e.register_local_data(se.data, se.size, 2); - } - } - #endif - - se.var_node = 0; - se.vec_node = 0; - #ifndef exprtk_disable_string_capabilities - se.str_node = 0; - #endif - se.data = 0; - se.ref_count = 0; - se.active = false; - } - } - - inline void register_return_results(expression& e) - { - e.register_return_results(results_context_); - results_context_ = 0; - } - - inline void load_unary_operations_map(unary_op_map_t& m) - { - #define register_unary_op(Op,UnaryFunctor) \ - m.insert(std::make_pair(Op,UnaryFunctor::process)); \ - - register_unary_op(details::e_abs , details::abs_op ) - register_unary_op(details::e_acos , details::acos_op ) - register_unary_op(details::e_acosh , details::acosh_op) - register_unary_op(details::e_asin , details::asin_op ) - register_unary_op(details::e_asinh , details::asinh_op) - register_unary_op(details::e_atanh , details::atanh_op) - register_unary_op(details::e_ceil , details::ceil_op ) - register_unary_op(details::e_cos , details::cos_op ) - register_unary_op(details::e_cosh , details::cosh_op ) - register_unary_op(details::e_exp , details::exp_op ) - register_unary_op(details::e_expm1 , details::expm1_op) - register_unary_op(details::e_floor , details::floor_op) - register_unary_op(details::e_log , details::log_op ) - register_unary_op(details::e_log10 , details::log10_op) - register_unary_op(details::e_log2 , details::log2_op ) - register_unary_op(details::e_log1p , details::log1p_op) - register_unary_op(details::e_neg , details::neg_op ) - register_unary_op(details::e_pos , details::pos_op ) - register_unary_op(details::e_round , details::round_op) - register_unary_op(details::e_sin , details::sin_op ) - register_unary_op(details::e_sinc , details::sinc_op ) - register_unary_op(details::e_sinh , details::sinh_op ) - register_unary_op(details::e_sqrt , details::sqrt_op ) - register_unary_op(details::e_tan , details::tan_op ) - register_unary_op(details::e_tanh , details::tanh_op ) - register_unary_op(details::e_cot , details::cot_op ) - register_unary_op(details::e_sec , details::sec_op ) - register_unary_op(details::e_csc , details::csc_op ) - register_unary_op(details::e_r2d , details::r2d_op ) - register_unary_op(details::e_d2r , details::d2r_op ) - register_unary_op(details::e_d2g , details::d2g_op ) - register_unary_op(details::e_g2d , details::g2d_op ) - register_unary_op(details::e_notl , details::notl_op ) - register_unary_op(details::e_sgn , details::sgn_op ) - register_unary_op(details::e_erf , details::erf_op ) - register_unary_op(details::e_erfc , details::erfc_op ) - register_unary_op(details::e_ncdf , details::ncdf_op ) - register_unary_op(details::e_frac , details::frac_op ) - register_unary_op(details::e_trunc , details::trunc_op) - #undef register_unary_op - } - - inline void load_binary_operations_map(binary_op_map_t& m) - { - typedef typename binary_op_map_t::value_type value_type; - - #define register_binary_op(Op,BinaryFunctor) \ - m.insert(value_type(Op,BinaryFunctor::process)); \ - - register_binary_op(details::e_add , details::add_op ) - register_binary_op(details::e_sub , details::sub_op ) - register_binary_op(details::e_mul , details::mul_op ) - register_binary_op(details::e_div , details::div_op ) - register_binary_op(details::e_mod , details::mod_op ) - register_binary_op(details::e_pow , details::pow_op ) - register_binary_op(details::e_lt , details::lt_op ) - register_binary_op(details::e_lte , details::lte_op ) - register_binary_op(details::e_gt , details::gt_op ) - register_binary_op(details::e_gte , details::gte_op ) - register_binary_op(details::e_eq , details::eq_op ) - register_binary_op(details::e_ne , details::ne_op ) - register_binary_op(details::e_and , details::and_op ) - register_binary_op(details::e_nand , details::nand_op) - register_binary_op(details::e_or , details::or_op ) - register_binary_op(details::e_nor , details::nor_op ) - register_binary_op(details::e_xor , details::xor_op ) - register_binary_op(details::e_xnor , details::xnor_op) - #undef register_binary_op - } - - inline void load_inv_binary_operations_map(inv_binary_op_map_t& m) - { - typedef typename inv_binary_op_map_t::value_type value_type; - - #define register_binary_op(Op,BinaryFunctor) \ - m.insert(value_type(BinaryFunctor::process,Op)); \ - - register_binary_op(details::e_add , details::add_op ) - register_binary_op(details::e_sub , details::sub_op ) - register_binary_op(details::e_mul , details::mul_op ) - register_binary_op(details::e_div , details::div_op ) - register_binary_op(details::e_mod , details::mod_op ) - register_binary_op(details::e_pow , details::pow_op ) - register_binary_op(details::e_lt , details::lt_op ) - register_binary_op(details::e_lte , details::lte_op ) - register_binary_op(details::e_gt , details::gt_op ) - register_binary_op(details::e_gte , details::gte_op ) - register_binary_op(details::e_eq , details::eq_op ) - register_binary_op(details::e_ne , details::ne_op ) - register_binary_op(details::e_and , details::and_op ) - register_binary_op(details::e_nand , details::nand_op) - register_binary_op(details::e_or , details::or_op ) - register_binary_op(details::e_nor , details::nor_op ) - register_binary_op(details::e_xor , details::xor_op ) - register_binary_op(details::e_xnor , details::xnor_op) - #undef register_binary_op - } - - inline void load_sf3_map(sf3_map_t& sf3_map) - { - typedef std::pair pair_t; - - #define register_sf3(Op) \ - sf3_map[details::sf##Op##_op::id()] = pair_t(details::sf##Op##_op::process,details::e_sf##Op); \ - - register_sf3(00) register_sf3(01) register_sf3(02) register_sf3(03) - register_sf3(04) register_sf3(05) register_sf3(06) register_sf3(07) - register_sf3(08) register_sf3(09) register_sf3(10) register_sf3(11) - register_sf3(12) register_sf3(13) register_sf3(14) register_sf3(15) - register_sf3(16) register_sf3(17) register_sf3(18) register_sf3(19) - register_sf3(20) register_sf3(21) register_sf3(22) register_sf3(23) - register_sf3(24) register_sf3(25) register_sf3(26) register_sf3(27) - register_sf3(28) register_sf3(29) register_sf3(30) - #undef register_sf3 - - #define register_sf3_extid(Id, Op) \ - sf3_map[Id] = pair_t(details::sf##Op##_op::process,details::e_sf##Op); \ - - register_sf3_extid("(t-t)-t",23) // (t-t)-t --> t-(t+t) - #undef register_sf3_extid - } - - inline void load_sf4_map(sf4_map_t& sf4_map) - { - typedef std::pair pair_t; - - #define register_sf4(Op) \ - sf4_map[details::sf##Op##_op::id()] = pair_t(details::sf##Op##_op::process,details::e_sf##Op); \ - - register_sf4(48) register_sf4(49) register_sf4(50) register_sf4(51) - register_sf4(52) register_sf4(53) register_sf4(54) register_sf4(55) - register_sf4(56) register_sf4(57) register_sf4(58) register_sf4(59) - register_sf4(60) register_sf4(61) register_sf4(62) register_sf4(63) - register_sf4(64) register_sf4(65) register_sf4(66) register_sf4(67) - register_sf4(68) register_sf4(69) register_sf4(70) register_sf4(71) - register_sf4(72) register_sf4(73) register_sf4(74) register_sf4(75) - register_sf4(76) register_sf4(77) register_sf4(78) register_sf4(79) - register_sf4(80) register_sf4(81) register_sf4(82) register_sf4(83) - #undef register_sf4 - - #define register_sf4ext(Op) \ - sf4_map[details::sfext##Op##_op::id()] = pair_t(details::sfext##Op##_op::process,details::e_sf4ext##Op); \ - - register_sf4ext(00) register_sf4ext(01) register_sf4ext(02) register_sf4ext(03) - register_sf4ext(04) register_sf4ext(05) register_sf4ext(06) register_sf4ext(07) - register_sf4ext(08) register_sf4ext(09) register_sf4ext(10) register_sf4ext(11) - register_sf4ext(12) register_sf4ext(13) register_sf4ext(14) register_sf4ext(15) - register_sf4ext(16) register_sf4ext(17) register_sf4ext(18) register_sf4ext(19) - register_sf4ext(20) register_sf4ext(21) register_sf4ext(22) register_sf4ext(23) - register_sf4ext(24) register_sf4ext(25) register_sf4ext(26) register_sf4ext(27) - register_sf4ext(28) register_sf4ext(29) register_sf4ext(30) register_sf4ext(31) - register_sf4ext(32) register_sf4ext(33) register_sf4ext(34) register_sf4ext(35) - register_sf4ext(36) register_sf4ext(36) register_sf4ext(38) register_sf4ext(39) - register_sf4ext(40) register_sf4ext(41) register_sf4ext(42) register_sf4ext(43) - register_sf4ext(44) register_sf4ext(45) register_sf4ext(46) register_sf4ext(47) - register_sf4ext(48) register_sf4ext(49) register_sf4ext(50) register_sf4ext(51) - register_sf4ext(52) register_sf4ext(53) register_sf4ext(54) register_sf4ext(55) - register_sf4ext(56) register_sf4ext(57) register_sf4ext(58) register_sf4ext(59) - register_sf4ext(60) register_sf4ext(61) - #undef register_sf4ext - } - - inline results_context_t& results_ctx() - { - if (0 == results_context_) - { - results_context_ = new results_context_t(); - } - - return (*results_context_); - } - - inline void return_cleanup() - { - #ifndef exprtk_disable_return_statement - if (results_context_) - { - delete results_context_; - results_context_ = 0; - } - - state_.return_stmt_present = false; - #endif - } - - private: - - parser(const parser&); - parser& operator=(const parser&); - - settings_store settings_; - expression_generator expression_generator_; - details::node_allocator node_allocator_; - symtab_store symtab_store_; - dependent_entity_collector dec_; - std::deque error_list_; - std::deque brkcnt_list_; - parser_state state_; - bool resolve_unknown_symbol_; - results_context_t* results_context_; - unknown_symbol_resolver* unknown_symbol_resolver_; - unknown_symbol_resolver default_usr_; - base_ops_map_t base_ops_map_; - unary_op_map_t unary_op_map_; - binary_op_map_t binary_op_map_; - inv_binary_op_map_t inv_binary_op_map_; - sf3_map_t sf3_map_; - sf4_map_t sf4_map_; - std::string synthesis_error_; - scope_element_manager sem_; - - lexer::helper::helper_assembly helper_assembly_; - - lexer::helper::commutative_inserter commutative_inserter_; - lexer::helper::operator_joiner operator_joiner_2_; - lexer::helper::operator_joiner operator_joiner_3_; - lexer::helper::symbol_replacer symbol_replacer_; - lexer::helper::bracket_checker bracket_checker_; - lexer::helper::numeric_checker numeric_checker_; - lexer::helper::sequence_validator sequence_validator_; - lexer::helper::sequence_validator_3tokens sequence_validator_3tkns_; - - loop_runtime_check_ptr loop_runtime_check_; - - template - friend void details::disable_type_checking(ParserType& p); - }; - - namespace details - { - template - struct collector_helper - { - typedef exprtk::symbol_table symbol_table_t; - typedef exprtk::expression expression_t; - typedef exprtk::parser parser_t; - typedef typename parser_t::dependent_entity_collector::symbol_t symbol_t; - typedef typename parser_t::unknown_symbol_resolver usr_t; - - struct resolve_as_vector : public parser_t::unknown_symbol_resolver - { - typedef exprtk::parser parser_t; - - resolve_as_vector() - : usr_t(usr_t::e_usrmode_extended) - {} - - virtual bool process(const std::string& unknown_symbol, - symbol_table_t& symbol_table, - std::string&) - { - static T v[1]; - symbol_table.add_vector(unknown_symbol,v); - return true; - } - }; - - static inline bool collection_pass(const std::string& expression_string, - std::set& symbol_set, - const bool collect_variables, - const bool collect_functions, - const bool vector_pass, - symbol_table_t& ext_symbol_table) - { - symbol_table_t symbol_table; - expression_t expression; - parser_t parser; - - resolve_as_vector vect_resolver; - - expression.register_symbol_table(symbol_table ); - expression.register_symbol_table(ext_symbol_table); - - if (vector_pass) - parser.enable_unknown_symbol_resolver(&vect_resolver); - else - parser.enable_unknown_symbol_resolver(); - - if (collect_variables) - parser.dec().collect_variables() = true; - - if (collect_functions) - parser.dec().collect_functions() = true; - - bool pass_result = false; - - details::disable_type_checking(parser); - - if (parser.compile(expression_string, expression)) - { - pass_result = true; - - std::deque symb_list; - parser.dec().symbols(symb_list); - - for (std::size_t i = 0; i < symb_list.size(); ++i) - { - symbol_set.insert(symb_list[i].first); - } - } - - return pass_result; - } - }; - } - - template class Sequence> - inline bool collect_variables(const std::string& expression, - Sequence& symbol_list) - { - typedef double T; - typedef details::collector_helper collect_t; - - collect_t::symbol_table_t null_symbol_table; - - std::set symbol_set; - - const bool variable_pass = collect_t::collection_pass - (expression, symbol_set, true, false, false, null_symbol_table); - const bool vector_pass = collect_t::collection_pass - (expression, symbol_set, true, false, true, null_symbol_table); - - if (!variable_pass && !vector_pass) - return false; - - std::set::iterator itr = symbol_set.begin(); - - while (symbol_set.end() != itr) - { - symbol_list.push_back(*itr); - ++itr; - } - - return true; - } - - template class Sequence> - inline bool collect_variables(const std::string& expression, - exprtk::symbol_table& extrnl_symbol_table, - Sequence& symbol_list) - { - typedef details::collector_helper collect_t; - - std::set symbol_set; - - const bool variable_pass = collect_t::collection_pass - (expression, symbol_set, true, false, false, extrnl_symbol_table); - const bool vector_pass = collect_t::collection_pass - (expression, symbol_set, true, false, true, extrnl_symbol_table); - - if (!variable_pass && !vector_pass) - return false; - - std::set::iterator itr = symbol_set.begin(); - - while (symbol_set.end() != itr) - { - symbol_list.push_back(*itr); - ++itr; - } - - return true; - } - - template class Sequence> - inline bool collect_functions(const std::string& expression, - Sequence& symbol_list) - { - typedef double T; - typedef details::collector_helper collect_t; - - collect_t::symbol_table_t null_symbol_table; - - std::set symbol_set; - - const bool variable_pass = collect_t::collection_pass - (expression, symbol_set, false, true, false, null_symbol_table); - const bool vector_pass = collect_t::collection_pass - (expression, symbol_set, false, true, true, null_symbol_table); - - if (!variable_pass && !vector_pass) - return false; - - std::set::iterator itr = symbol_set.begin(); - - while (symbol_set.end() != itr) - { - symbol_list.push_back(*itr); - ++itr; - } - - return true; - } - - template class Sequence> - inline bool collect_functions(const std::string& expression, - exprtk::symbol_table& extrnl_symbol_table, - Sequence& symbol_list) - { - typedef details::collector_helper collect_t; - - std::set symbol_set; - - const bool variable_pass = collect_t::collection_pass - (expression, symbol_set, false, true, false, extrnl_symbol_table); - const bool vector_pass = collect_t::collection_pass - (expression, symbol_set, false, true, true, extrnl_symbol_table); - - if (!variable_pass && !vector_pass) - return false; - - std::set::iterator itr = symbol_set.begin(); - - while (symbol_set.end() != itr) - { - symbol_list.push_back(*itr); - ++itr; - } - - return true; - } - - template - inline T integrate(const expression& e, - T& x, - const T& r0, const T& r1, - const std::size_t number_of_intervals = 1000000) - { - if (r0 > r1) - return T(0); - - const T h = (r1 - r0) / (T(2) * number_of_intervals); - T total_area = T(0); - - for (std::size_t i = 0; i < number_of_intervals; ++i) - { - x = r0 + T(2) * i * h; - const T y0 = e.value(); x += h; - const T y1 = e.value(); x += h; - const T y2 = e.value(); x += h; - total_area += h * (y0 + T(4) * y1 + y2) / T(3); - } - - return total_area; - } - - template - inline T integrate(const expression& e, - const std::string& variable_name, - const T& r0, const T& r1, - const std::size_t number_of_intervals = 1000000) - { - const symbol_table& sym_table = e.get_symbol_table(); - - if (!sym_table.valid()) - return std::numeric_limits::quiet_NaN(); - - details::variable_node* var = sym_table.get_variable(variable_name); - - if (var) - { - T& x = var->ref(); - const T x_original = x; - const T result = integrate(e, x, r0, r1, number_of_intervals); - x = x_original; - - return result; - } - else - return std::numeric_limits::quiet_NaN(); - } - - template - inline T derivative(const expression& e, - T& x, - const T& h = T(0.00000001)) - { - const T x_init = x; - const T _2h = T(2) * h; - - x = x_init + _2h; - const T y0 = e.value(); - x = x_init + h; - const T y1 = e.value(); - x = x_init - h; - const T y2 = e.value(); - x = x_init - _2h; - const T y3 = e.value(); - x = x_init; - - return (-y0 + T(8) * (y1 - y2) + y3) / (T(12) * h); - } - - template - inline T second_derivative(const expression& e, - T& x, - const T& h = T(0.00001)) - { - const T x_init = x; - const T _2h = T(2) * h; - - const T y = e.value(); - x = x_init + _2h; - const T y0 = e.value(); - x = x_init + h; - const T y1 = e.value(); - x = x_init - h; - const T y2 = e.value(); - x = x_init - _2h; - const T y3 = e.value(); - x = x_init; - - return (-y0 + T(16) * (y1 + y2) - T(30) * y - y3) / (T(12) * h * h); - } - - template - inline T third_derivative(const expression& e, - T& x, - const T& h = T(0.0001)) - { - const T x_init = x; - const T _2h = T(2) * h; - - x = x_init + _2h; - const T y0 = e.value(); - x = x_init + h; - const T y1 = e.value(); - x = x_init - h; - const T y2 = e.value(); - x = x_init - _2h; - const T y3 = e.value(); - x = x_init; - - return (y0 + T(2) * (y2 - y1) - y3) / (T(2) * h * h * h); - } - - template - inline T derivative(const expression& e, - const std::string& variable_name, - const T& h = T(0.00000001)) - { - const symbol_table& sym_table = e.get_symbol_table(); - - if (!sym_table.valid()) - { - return std::numeric_limits::quiet_NaN(); - } - - details::variable_node* var = sym_table.get_variable(variable_name); - - if (var) - { - T& x = var->ref(); - const T x_original = x; - const T result = derivative(e, x, h); - x = x_original; - - return result; - } - else - return std::numeric_limits::quiet_NaN(); - } - - template - inline T second_derivative(const expression& e, - const std::string& variable_name, - const T& h = T(0.00001)) - { - const symbol_table& sym_table = e.get_symbol_table(); - - if (!sym_table.valid()) - { - return std::numeric_limits::quiet_NaN(); - } - - details::variable_node* var = sym_table.get_variable(variable_name); - - if (var) - { - T& x = var->ref(); - const T x_original = x; - const T result = second_derivative(e, x, h); - x = x_original; - - return result; - } - else - return std::numeric_limits::quiet_NaN(); - } - - template - inline T third_derivative(const expression& e, - const std::string& variable_name, - const T& h = T(0.0001)) - { - const symbol_table& sym_table = e.get_symbol_table(); - - if (!sym_table.valid()) - { - return std::numeric_limits::quiet_NaN(); - } - - details::variable_node* var = sym_table.get_variable(variable_name); - - if (var) - { - T& x = var->ref(); - const T x_original = x; - const T result = third_derivative(e, x, h); - x = x_original; - - return result; - } - else - return std::numeric_limits::quiet_NaN(); - } - - /* - Note: The following 'compute' routines are simple helpers, - for quickly setting up the required pieces of code in order - to evaluate an expression. By virtue of how they operate - there will be an overhead with regards to their setup and - teardown and hence should not be used in time critical - sections of code. - Furthermore they only assume a small sub set of variables, - no string variables or user defined functions. - */ - template - inline bool compute(const std::string& expression_string, T& result) - { - // No variables - symbol_table symbol_table; - symbol_table.add_constants(); - - expression expression; - expression.register_symbol_table(symbol_table); - - parser parser; - - if (parser.compile(expression_string,expression)) - { - result = expression.value(); - - return true; - } - else - return false; - } - - template - inline bool compute(const std::string& expression_string, - const T& x, - T& result) - { - // Only 'x' - static const std::string x_var("x"); - - symbol_table symbol_table; - symbol_table.add_constants(); - symbol_table.add_constant(x_var,x); - - expression expression; - expression.register_symbol_table(symbol_table); - - parser parser; - - if (parser.compile(expression_string,expression)) - { - result = expression.value(); - - return true; - } - else - return false; - } - - template - inline bool compute(const std::string& expression_string, - const T&x, const T& y, - T& result) - { - // Only 'x' and 'y' - static const std::string x_var("x"); - static const std::string y_var("y"); - - symbol_table symbol_table; - symbol_table.add_constants(); - symbol_table.add_constant(x_var,x); - symbol_table.add_constant(y_var,y); - - expression expression; - expression.register_symbol_table(symbol_table); - - parser parser; - - if (parser.compile(expression_string,expression)) - { - result = expression.value(); - - return true; - } - else - return false; - } - - template - inline bool compute(const std::string& expression_string, - const T& x, const T& y, const T& z, - T& result) - { - // Only 'x', 'y' or 'z' - static const std::string x_var("x"); - static const std::string y_var("y"); - static const std::string z_var("z"); - - symbol_table symbol_table; - symbol_table.add_constants(); - symbol_table.add_constant(x_var,x); - symbol_table.add_constant(y_var,y); - symbol_table.add_constant(z_var,z); - - expression expression; - expression.register_symbol_table(symbol_table); - - parser parser; - - if (parser.compile(expression_string,expression)) - { - result = expression.value(); - - return true; - } - else - return false; - } - - template - class polynomial : public ifunction - { - private: - - template - struct poly_impl { }; - - template - struct poly_impl - { - static inline T evaluate(const Type x, - const Type c12, const Type c11, const Type c10, const Type c9, const Type c8, - const Type c7, const Type c6, const Type c5, const Type c4, const Type c3, - const Type c2, const Type c1, const Type c0) - { - // p(x) = c_12x^12 + c_11x^11 + c_10x^10 + c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 - return ((((((((((((c12 * x + c11) * x + c10) * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); - } - }; - - template - struct poly_impl - { - static inline T evaluate(const Type x, - const Type c11, const Type c10, const Type c9, const Type c8, const Type c7, - const Type c6, const Type c5, const Type c4, const Type c3, const Type c2, - const Type c1, const Type c0) - { - // p(x) = c_11x^11 + c_10x^10 + c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 - return (((((((((((c11 * x + c10) * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); - } - }; - - template - struct poly_impl - { - static inline T evaluate(const Type x, - const Type c10, const Type c9, const Type c8, const Type c7, const Type c6, - const Type c5, const Type c4, const Type c3, const Type c2, const Type c1, - const Type c0) - { - // p(x) = c_10x^10 + c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 - return ((((((((((c10 * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); - } - }; - - template - struct poly_impl - { - static inline T evaluate(const Type x, - const Type c9, const Type c8, const Type c7, const Type c6, const Type c5, - const Type c4, const Type c3, const Type c2, const Type c1, const Type c0) - { - // p(x) = c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 - return (((((((((c9 * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); - } - }; - - template - struct poly_impl - { - static inline T evaluate(const Type x, - const Type c8, const Type c7, const Type c6, const Type c5, const Type c4, - const Type c3, const Type c2, const Type c1, const Type c0) - { - // p(x) = c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 - return ((((((((c8 * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); - } - }; - - template - struct poly_impl - { - static inline T evaluate(const Type x, - const Type c7, const Type c6, const Type c5, const Type c4, const Type c3, - const Type c2, const Type c1, const Type c0) - { - // p(x) = c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 - return (((((((c7 * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); - } - }; - - template - struct poly_impl - { - static inline T evaluate(const Type x, - const Type c6, const Type c5, const Type c4, const Type c3, const Type c2, - const Type c1, const Type c0) - { - // p(x) = c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 - return ((((((c6 * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); - } - }; - - template - struct poly_impl - { - static inline T evaluate(const Type x, - const Type c5, const Type c4, const Type c3, const Type c2, - const Type c1, const Type c0) - { - // p(x) = c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 - return (((((c5 * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); - } - }; - - template - struct poly_impl - { - static inline T evaluate(const Type x, const Type c4, const Type c3, const Type c2, const Type c1, const Type c0) - { - // p(x) = c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 - return ((((c4 * x + c3) * x + c2) * x + c1) * x + c0); - } - }; - - template - struct poly_impl - { - static inline T evaluate(const Type x, const Type c3, const Type c2, const Type c1, const Type c0) - { - // p(x) = c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 - return (((c3 * x + c2) * x + c1) * x + c0); - } - }; - - template - struct poly_impl - { - static inline T evaluate(const Type x, const Type c2, const Type c1, const Type c0) - { - // p(x) = c_2x^2 + c_1x^1 + c_0x^0 - return ((c2 * x + c1) * x + c0); - } - }; - - template - struct poly_impl - { - static inline T evaluate(const Type x, const Type c1, const Type c0) - { - // p(x) = c_1x^1 + c_0x^0 - return (c1 * x + c0); - } - }; - - public: - - using ifunction::operator(); - - polynomial() - : ifunction((N+2 <= 20) ? (N + 2) : std::numeric_limits::max()) - { - disable_has_side_effects(*this); - } - - virtual ~polynomial() - {} - - #define poly_rtrn(NN) \ - return (NN != N) ? std::numeric_limits::quiet_NaN() : - - inline virtual T operator() (const T& x, const T& c1, const T& c0) - { - poly_rtrn(1) (poly_impl::evaluate(x, c1, c0)); - } - - inline virtual T operator() (const T& x, const T& c2, const T& c1, const T& c0) - { - poly_rtrn(2) (poly_impl::evaluate(x, c2, c1, c0)); - } - - inline virtual T operator() (const T& x, const T& c3, const T& c2, const T& c1, const T& c0) - { - poly_rtrn(3) (poly_impl::evaluate(x, c3, c2, c1, c0)); - } - - inline virtual T operator() (const T& x, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) - { - poly_rtrn(4) (poly_impl::evaluate(x, c4, c3, c2, c1, c0)); - } - - inline virtual T operator() (const T& x, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) - { - poly_rtrn(5) (poly_impl::evaluate(x, c5, c4, c3, c2, c1, c0)); - } - - inline virtual T operator() (const T& x, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) - { - poly_rtrn(6) (poly_impl::evaluate(x, c6, c5, c4, c3, c2, c1, c0)); - } - - inline virtual T operator() (const T& x, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) - { - poly_rtrn(7) (poly_impl::evaluate(x, c7, c6, c5, c4, c3, c2, c1, c0)); - } - - inline virtual T operator() (const T& x, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) - { - poly_rtrn(8) (poly_impl::evaluate(x, c8, c7, c6, c5, c4, c3, c2, c1, c0)); - } - - inline virtual T operator() (const T& x, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) - { - poly_rtrn(9) (poly_impl::evaluate(x, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); - } - - inline virtual T operator() (const T& x, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) - { - poly_rtrn(10) (poly_impl::evaluate(x, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); - } - - inline virtual T operator() (const T& x, const T& c11, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) - { - poly_rtrn(11) (poly_impl::evaluate(x, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); - } - - inline virtual T operator() (const T& x, const T& c12, const T& c11, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) - { - poly_rtrn(12) (poly_impl::evaluate(x, c12, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); - } - - #undef poly_rtrn - - inline virtual T operator() () - { - return std::numeric_limits::quiet_NaN(); - } - - inline virtual T operator() (const T&) - { - return std::numeric_limits::quiet_NaN(); - } - - inline virtual T operator() (const T&, const T&) - { - return std::numeric_limits::quiet_NaN(); - } - }; - - template - class function_compositor - { - public: - - typedef exprtk::expression expression_t; - typedef exprtk::symbol_table symbol_table_t; - typedef exprtk::parser parser_t; - typedef typename parser_t::settings_store settings_t; - - struct function - { - function() - {} - - function(const std::string& n) - : name_(n) - {} - - function(const std::string& name, - const std::string& expression) - : name_(name), - expression_(expression) - {} - - function(const std::string& name, - const std::string& expression, - const std::string& v0) - : name_(name), - expression_(expression) - { - v_.push_back(v0); - } - - function(const std::string& name, - const std::string& expression, - const std::string& v0, const std::string& v1) - : name_(name), - expression_(expression) - { - v_.push_back(v0); v_.push_back(v1); - } - - function(const std::string& name, - const std::string& expression, - const std::string& v0, const std::string& v1, - const std::string& v2) - : name_(name), - expression_(expression) - { - v_.push_back(v0); v_.push_back(v1); - v_.push_back(v2); - } - - function(const std::string& name, - const std::string& expression, - const std::string& v0, const std::string& v1, - const std::string& v2, const std::string& v3) - : name_(name), - expression_(expression) - { - v_.push_back(v0); v_.push_back(v1); - v_.push_back(v2); v_.push_back(v3); - } - - function(const std::string& name, - const std::string& expression, - const std::string& v0, const std::string& v1, - const std::string& v2, const std::string& v3, - const std::string& v4) - : name_(name), - expression_(expression) - { - v_.push_back(v0); v_.push_back(v1); - v_.push_back(v2); v_.push_back(v3); - v_.push_back(v4); - } - - inline function& name(const std::string& n) - { - name_ = n; - return (*this); - } - - inline function& expression(const std::string& e) - { - expression_ = e; - return (*this); - } - - inline function& var(const std::string& v) - { - v_.push_back(v); - return (*this); - } - - std::string name_; - std::string expression_; - std::deque v_; - }; - - private: - - struct base_func : public exprtk::ifunction - { - typedef const T& type; - typedef exprtk::ifunction function_t; - typedef std::vector varref_t; - typedef std::vector var_t; - typedef std::pair lvarref_t; - typedef std::vector lvr_vec_t; - - using exprtk::ifunction::operator(); - - base_func(const std::size_t& pc = 0) - : exprtk::ifunction(pc), - local_var_stack_size(0), - stack_depth(0) - { - v.resize(pc); - } - - virtual ~base_func() - {} - - inline void update(const T& v0) - { - (*v[0]) = v0; - } - - inline void update(const T& v0, const T& v1) - { - (*v[0]) = v0; (*v[1]) = v1; - } - - inline void update(const T& v0, const T& v1, const T& v2) - { - (*v[0]) = v0; (*v[1]) = v1; - (*v[2]) = v2; - } - - inline void update(const T& v0, const T& v1, const T& v2, const T& v3) - { - (*v[0]) = v0; (*v[1]) = v1; - (*v[2]) = v2; (*v[3]) = v3; - } - - inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4) - { - (*v[0]) = v0; (*v[1]) = v1; - (*v[2]) = v2; (*v[3]) = v3; - (*v[4]) = v4; - } - - inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5) - { - (*v[0]) = v0; (*v[1]) = v1; - (*v[2]) = v2; (*v[3]) = v3; - (*v[4]) = v4; (*v[5]) = v5; - } - - inline function_t& setup(expression_t& expr) - { - expression = expr; - - typedef typename expression_t::control_block::local_data_list_t ldl_t; - - const ldl_t ldl = expr.local_data_list(); - - std::vector index_list; - - for (std::size_t i = 0; i < ldl.size(); ++i) - { - if (ldl[i].size) - { - index_list.push_back(i); - } - } - - std::size_t input_param_count = 0; - - for (std::size_t i = 0; i < index_list.size(); ++i) - { - const std::size_t index = index_list[i]; - - if (i < (index_list.size() - v.size())) - { - lv.push_back( - std::make_pair( - reinterpret_cast(ldl[index].pointer), - ldl[index].size)); - - local_var_stack_size += ldl[index].size; - } - else - v[input_param_count++] = reinterpret_cast(ldl[index].pointer); - } - - clear_stack(); - - return (*this); - } - - inline void pre() - { - if (stack_depth++) - { - if (!v.empty()) - { - var_t var_stack(v.size(),T(0)); - copy(v,var_stack); - param_stack.push_back(var_stack); - } - - if (!lv.empty()) - { - var_t local_var_stack(local_var_stack_size,T(0)); - copy(lv,local_var_stack); - local_stack.push_back(local_var_stack); - } - } - } - - inline void post() - { - if (--stack_depth) - { - if (!v.empty()) - { - copy(param_stack.back(),v); - param_stack.pop_back(); - } - - if (!lv.empty()) - { - copy(local_stack.back(),lv); - local_stack.pop_back(); - } - } - } - - void copy(const varref_t& src_v, var_t& dest_v) - { - for (std::size_t i = 0; i < src_v.size(); ++i) - { - dest_v[i] = (*src_v[i]); - } - } - - void copy(const var_t& src_v, varref_t& dest_v) - { - for (std::size_t i = 0; i < src_v.size(); ++i) - { - (*dest_v[i]) = src_v[i]; - } - } - - void copy(const lvr_vec_t& src_v, var_t& dest_v) - { - typename var_t::iterator itr = dest_v.begin(); - typedef typename std::iterator_traits::difference_type diff_t; - - for (std::size_t i = 0; i < src_v.size(); ++i) - { - lvarref_t vr = src_v[i]; - - if (1 == vr.second) - *itr++ = (*vr.first); - else - { - std::copy(vr.first, vr.first + vr.second, itr); - itr += static_cast(vr.second); - } - } - } - - void copy(const var_t& src_v, lvr_vec_t& dest_v) - { - typename var_t::const_iterator itr = src_v.begin(); - typedef typename std::iterator_traits::difference_type diff_t; - - for (std::size_t i = 0; i < src_v.size(); ++i) - { - lvarref_t vr = dest_v[i]; - - if (1 == vr.second) - (*vr.first) = *itr++; - else - { - std::copy(itr, itr + static_cast(vr.second), vr.first); - itr += static_cast(vr.second); - } - } - } - - inline void clear_stack() - { - for (std::size_t i = 0; i < v.size(); ++i) - { - (*v[i]) = 0; - } - } - - inline virtual T value(expression_t& e) - { - return e.value(); - } - - expression_t expression; - varref_t v; - lvr_vec_t lv; - std::size_t local_var_stack_size; - std::size_t stack_depth; - std::deque param_stack; - std::deque local_stack; - }; - - typedef std::map funcparam_t; - - struct func_0param : public base_func - { - using exprtk::ifunction::operator(); - - func_0param() : base_func(0) {} - - inline T operator() () - { - return this->value(base_func::expression); - } - }; - - typedef const T& type; - - template - struct scoped_bft - { - explicit scoped_bft(BaseFuncType& bft) - : bft_(bft) - { - bft_.pre (); - } - - ~scoped_bft() - { - bft_.post(); - } - - BaseFuncType& bft_; - - private: - - scoped_bft(scoped_bft&); - scoped_bft& operator=(scoped_bft&); - }; - - struct func_1param : public base_func - { - using exprtk::ifunction::operator(); - - func_1param() : base_func(1) {} - - inline T operator() (type v0) - { - scoped_bft sb(*this); - base_func::update(v0); - return this->value(base_func::expression); - } - }; - - struct func_2param : public base_func - { - using exprtk::ifunction::operator(); - - func_2param() : base_func(2) {} - - inline T operator() (type v0, type v1) - { - scoped_bft sb(*this); - base_func::update(v0, v1); - return this->value(base_func::expression); - } - }; - - struct func_3param : public base_func - { - using exprtk::ifunction::operator(); - - func_3param() : base_func(3) {} - - inline T operator() (type v0, type v1, type v2) - { - scoped_bft sb(*this); - base_func::update(v0, v1, v2); - return this->value(base_func::expression); - } - }; - - struct func_4param : public base_func - { - using exprtk::ifunction::operator(); - - func_4param() : base_func(4) {} - - inline T operator() (type v0, type v1, type v2, type v3) - { - scoped_bft sb(*this); - base_func::update(v0, v1, v2, v3); - return this->value(base_func::expression); - } - }; - - struct func_5param : public base_func - { - using exprtk::ifunction::operator(); - - func_5param() : base_func(5) {} - - inline T operator() (type v0, type v1, type v2, type v3, type v4) - { - scoped_bft sb(*this); - base_func::update(v0, v1, v2, v3, v4); - return this->value(base_func::expression); - } - }; - - struct func_6param : public base_func - { - using exprtk::ifunction::operator(); - - func_6param() : base_func(6) {} - - inline T operator() (type v0, type v1, type v2, type v3, type v4, type v5) - { - scoped_bft sb(*this); - base_func::update(v0, v1, v2, v3, v4, v5); - return this->value(base_func::expression); - } - }; - - static T return_value(expression_t& e) - { - typedef exprtk::results_context results_context_t; - typedef typename results_context_t::type_store_t type_t; - typedef typename type_t::scalar_view scalar_t; - - const T result = e.value(); - - if (e.return_invoked()) - { - // Due to the post compilation checks, it can be safely - // assumed that there will be at least one parameter - // and that the first parameter will always be scalar. - return scalar_t(e.results()[0])(); - } - - return result; - } - - #define def_fp_retval(N) \ - struct func_##N##param_retval : public func_##N##param \ - { \ - inline T value(expression_t& e) \ - { \ - return return_value(e); \ - } \ - }; \ - - def_fp_retval(0) - def_fp_retval(1) - def_fp_retval(2) - def_fp_retval(3) - def_fp_retval(4) - def_fp_retval(5) - def_fp_retval(6) - - template class Sequence> - inline bool add(const std::string& name, - const std::string& expression, - const Sequence& var_list, - const bool override = false) - { - const typename std::map::iterator itr = expr_map_.find(name); - - if (expr_map_.end() != itr) - { - if (!override) - { - exprtk_debug(("Compositor error(add): function '%s' already defined\n", - name.c_str())); - - return false; - } - - remove(name, var_list.size()); - } - - if (compile_expression(name,expression,var_list)) - { - const std::size_t n = var_list.size(); - - fp_map_[n][name]->setup(expr_map_[name]); - - return true; - } - else - { - exprtk_debug(("Compositor error(add): Failed to compile function '%s'\n", - name.c_str())); - - return false; - } - } - - public: - - function_compositor() - : parser_(settings_t::compile_all_opts + - settings_t::e_disable_zero_return), - fp_map_(7) - {} - - function_compositor(const symbol_table_t& st) - : symbol_table_(st), - parser_(settings_t::compile_all_opts + - settings_t::e_disable_zero_return), - fp_map_(7) - {} - - ~function_compositor() - { - clear(); - } - - inline symbol_table_t& symbol_table() - { - return symbol_table_; - } - - inline const symbol_table_t& symbol_table() const - { - return symbol_table_; - } - - inline void add_auxiliary_symtab(symbol_table_t& symtab) - { - auxiliary_symtab_list_.push_back(&symtab); - } - - void clear() - { - symbol_table_.clear(); - expr_map_ .clear(); - - for (std::size_t i = 0; i < fp_map_.size(); ++i) - { - typename funcparam_t::iterator itr = fp_map_[i].begin(); - typename funcparam_t::iterator end = fp_map_[i].end (); - - while (itr != end) - { - delete itr->second; - ++itr; - } - - fp_map_[i].clear(); - } - } - - inline bool add(const function& f, const bool override = false) - { - return add(f.name_, f.expression_, f.v_,override); - } - - private: - - template class Sequence> - bool compile_expression(const std::string& name, - const std::string& expression, - const Sequence& input_var_list, - bool return_present = false) - { - expression_t compiled_expression; - symbol_table_t local_symbol_table; - - local_symbol_table.load_from(symbol_table_); - local_symbol_table.add_constants(); - - if (!valid(name,input_var_list.size())) - return false; - - if (!forward(name, - input_var_list.size(), - local_symbol_table, - return_present)) - return false; - - compiled_expression.register_symbol_table(local_symbol_table); - - for (std::size_t i = 0; i < auxiliary_symtab_list_.size(); ++i) - { - compiled_expression.register_symbol_table((*auxiliary_symtab_list_[i])); - } - - std::string mod_expression; - - for (std::size_t i = 0; i < input_var_list.size(); ++i) - { - mod_expression += " var " + input_var_list[i] + "{};\n"; - } - - if ( - ('{' == details::front(expression)) && - ('}' == details::back (expression)) - ) - mod_expression += "~" + expression + ";"; - else - mod_expression += "~{" + expression + "};"; - - if (!parser_.compile(mod_expression,compiled_expression)) - { - exprtk_debug(("Compositor Error: %s\n",parser_.error().c_str())); - exprtk_debug(("Compositor modified expression: \n%s\n",mod_expression.c_str())); - - remove(name,input_var_list.size()); - - return false; - } - - if (!return_present && parser_.dec().return_present()) - { - remove(name,input_var_list.size()); - - return compile_expression(name, expression, input_var_list, true); - } - - // Make sure every return point has a scalar as its first parameter - if (parser_.dec().return_present()) - { - typedef std::vector str_list_t; - - str_list_t ret_param_list = parser_.dec().return_param_type_list(); - - for (std::size_t i = 0; i < ret_param_list.size(); ++i) - { - const std::string& params = ret_param_list[i]; - - if (params.empty() || ('T' != params[0])) - { - exprtk_debug(("Compositor Error: Return statement in function '%s' is invalid\n", - name.c_str())); - - remove(name,input_var_list.size()); - - return false; - } - } - } - - expr_map_[name] = compiled_expression; - - exprtk::ifunction& ifunc = (*(fp_map_[input_var_list.size()])[name]); - - if (symbol_table_.add_function(name,ifunc)) - return true; - else - { - exprtk_debug(("Compositor Error: Failed to add function '%s' to symbol table\n", - name.c_str())); - return false; - } - } - - inline bool symbol_used(const std::string& symbol) const - { - return ( - symbol_table_.is_variable (symbol) || - symbol_table_.is_stringvar (symbol) || - symbol_table_.is_function (symbol) || - symbol_table_.is_vector (symbol) || - symbol_table_.is_vararg_function(symbol) - ); - } - - inline bool valid(const std::string& name, - const std::size_t& arg_count) const - { - if (arg_count > 6) - return false; - else if (symbol_used(name)) - return false; - else if (fp_map_[arg_count].end() != fp_map_[arg_count].find(name)) - return false; - else - return true; - } - - inline bool forward(const std::string& name, - const std::size_t& arg_count, - symbol_table_t& sym_table, - const bool ret_present = false) - { - switch (arg_count) - { - #define case_stmt(N) \ - case N : (fp_map_[arg_count])[name] = \ - (!ret_present) ? static_cast \ - (new func_##N##param) : \ - static_cast \ - (new func_##N##param_retval) ; \ - break; \ - - case_stmt(0) case_stmt(1) case_stmt(2) - case_stmt(3) case_stmt(4) case_stmt(5) - case_stmt(6) - #undef case_stmt - } - - exprtk::ifunction& ifunc = (*(fp_map_[arg_count])[name]); - - return sym_table.add_function(name,ifunc); - } - - inline void remove(const std::string& name, const std::size_t& arg_count) - { - if (arg_count > 6) - return; - - const typename std::map::iterator em_itr = expr_map_.find(name); - - if (expr_map_.end() != em_itr) - { - expr_map_.erase(em_itr); - } - - const typename funcparam_t::iterator fp_itr = fp_map_[arg_count].find(name); - - if (fp_map_[arg_count].end() != fp_itr) - { - delete fp_itr->second; - fp_map_[arg_count].erase(fp_itr); - } - - symbol_table_.remove_function(name); - } - - private: - - symbol_table_t symbol_table_; - parser_t parser_; - std::map expr_map_; - std::vector fp_map_; - std::vector auxiliary_symtab_list_; - }; - - template - inline bool pgo_primer() - { - static const std::string expression_list[] = - { - "(y + x)", - "2 * (y + x)", - "(2 * y + 2 * x)", - "(y + x / y) * (x - y / x)", - "x / ((x + y) * (x - y)) / y", - "1 - ((x * y) + (y / x)) - 3", - "sin(2 * x) + cos(pi / y)", - "1 - sin(2 * x) + cos(pi / y)", - "sqrt(1 - sin(2 * x) + cos(pi / y) / 3)", - "(x^2 / sin(2 * pi / y)) -x / 2", - "x + (cos(y - sin(2 / x * pi)) - sin(x - cos(2 * y / pi))) - y", - "clamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)", - "iclamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)", - "max(3.33, min(sqrt(1 - sin(2 * x) + cos(pi / y) / 3), 1.11))", - "if(avg(x,y) <= x + y, x - y, x * y) + 2 * pi / x", - "1.1x^1 + 2.2y^2 - 3.3x^3 + 4.4y^4 - 5.5x^5 + 6.6y^6 - 7.7x^27 + 8.8y^55", - "(yy + xx)", - "2 * (yy + xx)", - "(2 * yy + 2 * xx)", - "(yy + xx / yy) * (xx - yy / xx)", - "xx / ((xx + yy) * (xx - yy)) / yy", - "1 - ((xx * yy) + (yy / xx)) - 3", - "sin(2 * xx) + cos(pi / yy)", - "1 - sin(2 * xx) + cos(pi / yy)", - "sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3)", - "(xx^2 / sin(2 * pi / yy)) -xx / 2", - "xx + (cos(yy - sin(2 / xx * pi)) - sin(xx - cos(2 * yy / pi))) - yy", - "clamp(-1.0, sin(2 * pi * xx) + cos(yy / 2 * pi), +1.0)", - "max(3.33, min(sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3), 1.11))", - "if(avg(xx,yy) <= xx + yy, xx - yy, xx * yy) + 2 * pi / xx", - "1.1xx^1 + 2.2yy^2 - 3.3xx^3 + 4.4yy^4 - 5.5xx^5 + 6.6yy^6 - 7.7xx^27 + 8.8yy^55", - "(1.1*(2.2*(3.3*(4.4*(5.5*(6.6*(7.7*(8.8*(9.9+x)))))))))", - "(((((((((x+9.9)*8.8)*7.7)*6.6)*5.5)*4.4)*3.3)*2.2)*1.1)", - "(x + y) * z", "x + (y * z)", "(x + y) * 7", "x + (y * 7)", - "(x + 7) * y", "x + (7 * y)", "(7 + x) * y", "7 + (x * y)", - "(2 + x) * 3", "2 + (x * 3)", "(2 + 3) * x", "2 + (3 * x)", - "(x + 2) * 3", "x + (2 * 3)", - "(x + y) * (z / w)", "(x + y) * (z / 7)", "(x + y) * (7 / z)", "(x + 7) * (y / z)", - "(7 + x) * (y / z)", "(2 + x) * (y / z)", "(x + 2) * (y / 3)", "(2 + x) * (y / 3)", - "(x + 2) * (3 / y)", "x + (y * (z / w))", "x + (y * (z / 7))", "x + (y * (7 / z))", - "x + (7 * (y / z))", "7 + (x * (y / z))", "2 + (x * (3 / y))", "x + (2 * (y / 4))", - "2 + (x * (y / 3))", "x + (2 * (3 / y))", - "x + ((y * z) / w)", "x + ((y * z) / 7)", "x + ((y * 7) / z)", "x + ((7 * y) / z)", - "7 + ((y * z) / w)", "2 + ((x * 3) / y)", "x + ((2 * y) / 3)", "2 + ((x * y) / 3)", - "x + ((2 * 3) / y)", "(((x + y) * z) / w)", - "(((x + y) * z) / 7)", "(((x + y) * 7) / z)", "(((x + 7) * y) / z)", "(((7 + x) * y) / z)", - "(((2 + x) * 3) / y)", "(((x + 2) * y) / 3)", "(((2 + x) * y) / 3)", "(((x + 2) * 3) / y)", - "((x + (y * z)) / w)", "((x + (y * z)) / 7)", "((x + (y * 7)) / y)", "((x + (7 * y)) / z)", - "((7 + (x * y)) / z)", "((2 + (x * 3)) / y)", "((x + (2 * y)) / 3)", "((2 + (x * y)) / 3)", - "((x + (2 * 3)) / y)", - "(xx + yy) * zz", "xx + (yy * zz)", - "(xx + yy) * 7", "xx + (yy * 7)", - "(xx + 7) * yy", "xx + (7 * yy)", - "(7 + xx) * yy", "7 + (xx * yy)", - "(2 + x) * 3", "2 + (x * 3)", - "(2 + 3) * x", "2 + (3 * x)", - "(x + 2) * 3", "x + (2 * 3)", - "(xx + yy) * (zz / ww)", "(xx + yy) * (zz / 7)", - "(xx + yy) * (7 / zz)", "(xx + 7) * (yy / zz)", - "(7 + xx) * (yy / zz)", "(2 + xx) * (yy / zz)", - "(xx + 2) * (yy / 3)", "(2 + xx) * (yy / 3)", - "(xx + 2) * (3 / yy)", "xx + (yy * (zz / ww))", - "xx + (yy * (zz / 7))", "xx + (yy * (7 / zz))", - "xx + (7 * (yy / zz))", "7 + (xx * (yy / zz))", - "2 + (xx * (3 / yy))", "xx + (2 * (yy / 4))", - "2 + (xx * (yy / 3))", "xx + (2 * (3 / yy))", - "xx + ((yy * zz) / ww)", "xx + ((yy * zz) / 7)", - "xx + ((yy * 7) / zz)", "xx + ((7 * yy) / zz)", - "7 + ((yy * zz) / ww)", "2 + ((xx * 3) / yy)", - "xx + ((2 * yy) / 3)", "2 + ((xx * yy) / 3)", - "xx + ((2 * 3) / yy)", "(((xx + yy) * zz) / ww)", - "(((xx + yy) * zz) / 7)", "(((xx + yy) * 7) / zz)", - "(((xx + 7) * yy) / zz)", "(((7 + xx) * yy) / zz)", - "(((2 + xx) * 3) / yy)", "(((xx + 2) * yy) / 3)", - "(((2 + xx) * yy) / 3)", "(((xx + 2) * 3) / yy)", - "((xx + (yy * zz)) / ww)", "((xx + (yy * zz)) / 7)", - "((xx + (yy * 7)) / yy)", "((xx + (7 * yy)) / zz)", - "((7 + (xx * yy)) / zz)", "((2 + (xx * 3)) / yy)", - "((xx + (2 * yy)) / 3)", "((2 + (xx * yy)) / 3)", - "((xx + (2 * 3)) / yy)" - }; - - static const std::size_t expression_list_size = sizeof(expression_list) / sizeof(std::string); - - T x = T(0); - T y = T(0); - T z = T(0); - T w = T(0); - T xx = T(0); - T yy = T(0); - T zz = T(0); - T ww = T(0); - - exprtk::symbol_table symbol_table; - symbol_table.add_constants(); - symbol_table.add_variable( "x", x); - symbol_table.add_variable( "y", y); - symbol_table.add_variable( "z", z); - symbol_table.add_variable( "w", w); - symbol_table.add_variable("xx",xx); - symbol_table.add_variable("yy",yy); - symbol_table.add_variable("zz",zz); - symbol_table.add_variable("ww",ww); - - typedef typename std::deque > expr_list_t; - expr_list_t expr_list; - - const std::size_t rounds = 50; - - { - for (std::size_t r = 0; r < rounds; ++r) - { - expr_list.clear(); - exprtk::parser parser; - - for (std::size_t i = 0; i < expression_list_size; ++i) - { - exprtk::expression expression; - expression.register_symbol_table(symbol_table); - - if (!parser.compile(expression_list[i],expression)) - { - return false; - } - - expr_list.push_back(expression); - } - } - } - - struct execute - { - static inline T process(T& x, T& y, expression& expression) - { - static const T lower_bound = T(-20); - static const T upper_bound = T(+20); - static const T delta = T(0.1); - - T total = T(0); - - for (x = lower_bound; x <= upper_bound; x += delta) - { - for (y = lower_bound; y <= upper_bound; y += delta) - { - total += expression.value(); - } - } - - return total; - } - }; - - for (std::size_t i = 0; i < expr_list.size(); ++i) - { - execute::process( x, y, expr_list[i]); - execute::process(xx, yy, expr_list[i]); - } - - { - for (std::size_t i = 0; i < 10000; ++i) - { - const T v = T(123.456 + i); - - if (details::is_true(details::numeric::nequal(details::numeric::fast_exp::result(v),details::numeric::pow(v,T(1))))) - return false; - - #define else_stmt(N) \ - else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp::result(v),details::numeric::pow(v,T(N))))) \ - return false; \ - - else_stmt( 2) else_stmt( 3) else_stmt( 4) else_stmt( 5) - else_stmt( 6) else_stmt( 7) else_stmt( 8) else_stmt( 9) - else_stmt(10) else_stmt(11) else_stmt(12) else_stmt(13) - else_stmt(14) else_stmt(15) else_stmt(16) else_stmt(17) - else_stmt(18) else_stmt(19) else_stmt(20) else_stmt(21) - else_stmt(22) else_stmt(23) else_stmt(24) else_stmt(25) - else_stmt(26) else_stmt(27) else_stmt(28) else_stmt(29) - else_stmt(30) else_stmt(31) else_stmt(32) else_stmt(33) - else_stmt(34) else_stmt(35) else_stmt(36) else_stmt(37) - else_stmt(38) else_stmt(39) else_stmt(40) else_stmt(41) - else_stmt(42) else_stmt(43) else_stmt(44) else_stmt(45) - else_stmt(46) else_stmt(47) else_stmt(48) else_stmt(49) - else_stmt(50) else_stmt(51) else_stmt(52) else_stmt(53) - else_stmt(54) else_stmt(55) else_stmt(56) else_stmt(57) - else_stmt(58) else_stmt(59) else_stmt(60) else_stmt(61) - } - } - - return true; - } -} - -#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) -# ifndef NOMINMAX -# define NOMINMAX -# endif -# ifndef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN -# endif -# include -# include -#else -# include -# include -# include -#endif - -namespace exprtk -{ - class timer - { - public: - - #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) - timer() - : in_use_(false) - { - QueryPerformanceFrequency(&clock_frequency_); - } - - inline void start() - { - in_use_ = true; - QueryPerformanceCounter(&start_time_); - } - - inline void stop() - { - QueryPerformanceCounter(&stop_time_); - in_use_ = false; - } - - inline double time() const - { - return (1.0 * (stop_time_.QuadPart - start_time_.QuadPart)) / (1.0 * clock_frequency_.QuadPart); - } - - #else - - timer() - : in_use_(false) - { - start_time_.tv_sec = 0; - start_time_.tv_usec = 0; - stop_time_.tv_sec = 0; - stop_time_.tv_usec = 0; - } - - inline void start() - { - in_use_ = true; - gettimeofday(&start_time_,0); - } - - inline void stop() - { - gettimeofday(&stop_time_, 0); - in_use_ = false; - } - - inline unsigned long long int usec_time() const - { - if (!in_use_) - { - if (stop_time_.tv_sec >= start_time_.tv_sec) - { - return 1000000LLU * static_cast(stop_time_.tv_sec - start_time_.tv_sec ) + - static_cast(stop_time_.tv_usec - start_time_.tv_usec) ; - } - else - return std::numeric_limits::max(); - } - else - return std::numeric_limits::max(); - } - - inline double time() const - { - return usec_time() * 0.000001; - } - - #endif - - inline bool in_use() const - { - return in_use_; - } - - private: - - bool in_use_; - - #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) - LARGE_INTEGER start_time_; - LARGE_INTEGER stop_time_; - LARGE_INTEGER clock_frequency_; - #else - struct timeval start_time_; - struct timeval stop_time_; - #endif - }; - -} // namespace exprtk - -#ifndef exprtk_disable_rtl_io -namespace exprtk -{ - namespace rtl { namespace io { namespace details - { - template - inline void print_type(const std::string& fmt, - const T v, - exprtk::details::numeric::details::real_type_tag) - { - printf(fmt.c_str(),v); - } - - template - struct print_impl - { - typedef typename igeneric_function::generic_type generic_type; - typedef typename igeneric_function::parameter_list_t parameter_list_t; - typedef typename generic_type::scalar_view scalar_t; - typedef typename generic_type::vector_view vector_t; - typedef typename generic_type::string_view string_t; - typedef typename exprtk::details::numeric::details::number_type::type num_type; - - static void process(const std::string& scalar_format, parameter_list_t parameters) - { - for (std::size_t i = 0; i < parameters.size(); ++i) - { - generic_type& gt = parameters[i]; - - switch (gt.type) - { - case generic_type::e_scalar : print(scalar_format,scalar_t(gt)); - break; - - case generic_type::e_vector : print(scalar_format,vector_t(gt)); - break; - - case generic_type::e_string : print(string_t(gt)); - break; - - default : continue; - } - } - } - - static inline void print(const std::string& scalar_format, const scalar_t& s) - { - print_type(scalar_format,s(),num_type()); - } - - static inline void print(const std::string& scalar_format, const vector_t& v) - { - for (std::size_t i = 0; i < v.size(); ++i) - { - print_type(scalar_format,v[i],num_type()); - - if ((i + 1) < v.size()) - printf(" "); - } - } - - static inline void print(const string_t& s) - { - printf("%s",to_str(s).c_str()); - } - }; - - } // namespace exprtk::rtl::io::details - - template - struct print : public exprtk::igeneric_function - { - typedef typename igeneric_function::parameter_list_t parameter_list_t; - - using exprtk::igeneric_function::operator(); - - print(const std::string& scalar_format = "%10.5f") - : scalar_format_(scalar_format) - { - exprtk::enable_zero_parameters(*this); - } - - inline T operator() (parameter_list_t parameters) - { - details::print_impl::process(scalar_format_,parameters); - return T(0); - } - - std::string scalar_format_; - }; - - template - struct println : public exprtk::igeneric_function - { - typedef typename igeneric_function::parameter_list_t parameter_list_t; - - using exprtk::igeneric_function::operator(); - - println(const std::string& scalar_format = "%10.5f") - : scalar_format_(scalar_format) - { - exprtk::enable_zero_parameters(*this); - } - - inline T operator() (parameter_list_t parameters) - { - details::print_impl::process(scalar_format_,parameters); - printf("\n"); - return T(0); - } - - std::string scalar_format_; - }; - - template - struct package - { - print p; - println pl; - - bool register_package(exprtk::symbol_table& symtab) - { - #define exprtk_register_function(FunctionName,FunctionType) \ - if (!symtab.add_function(FunctionName,FunctionType)) \ - { \ - exprtk_debug(( \ - "exprtk::rtl::io::register_package - Failed to add function: %s\n", \ - FunctionName)); \ - return false; \ - } \ - - exprtk_register_function("print" , p ) - exprtk_register_function("println", pl) - #undef exprtk_register_function - - return true; - } - }; - - } // namespace exprtk::rtl::io - } // namespace exprtk::rtl -} // namespace exprtk -#endif - -#ifndef exprtk_disable_rtl_io_file -#include -namespace exprtk -{ - namespace rtl { namespace io { namespace file { namespace details - { - enum file_mode - { - e_error = 0, - e_read = 1, - e_write = 2, - e_rdwrt = 4 - }; - - struct file_descriptor - { - file_descriptor(const std::string& fname, const std::string& access) - : stream_ptr(0), - mode(get_file_mode(access)), - file_name(fname) - {} - - void* stream_ptr; - file_mode mode; - std::string file_name; - - bool open() - { - if (e_read == mode) - { - std::ifstream* stream = new std::ifstream(file_name.c_str(),std::ios::binary); - - if (!(*stream)) - { - file_name.clear(); - delete stream; - - return false; - } - else - stream_ptr = stream; - - return true; - } - else if (e_write == mode) - { - std::ofstream* stream = new std::ofstream(file_name.c_str(),std::ios::binary); - - if (!(*stream)) - { - file_name.clear(); - delete stream; - - return false; - } - else - stream_ptr = stream; - - return true; - } - else if (e_rdwrt == mode) - { - std::fstream* stream = new std::fstream(file_name.c_str(),std::ios::binary); - - if (!(*stream)) - { - file_name.clear(); - delete stream; - - return false; - } - else - stream_ptr = stream; - - return true; - } - else - return false; - } - - template - void close(Ptr& p) - { - Stream* stream = reinterpret_cast(p); - stream->close(); - delete stream; - p = reinterpret_cast(0); - } - - bool close() - { - switch (mode) - { - case e_read : close(stream_ptr); - break; - - case e_write : close(stream_ptr); - break; - - case e_rdwrt : close (stream_ptr); - break; - - default : return false; - } - - return true; - } - - template - bool write(const View& view, const std::size_t amount, const std::size_t offset = 0) - { - switch (mode) - { - case e_write : reinterpret_cast(stream_ptr)-> - write(reinterpret_cast(view.begin() + offset), amount * sizeof(typename View::value_t)); - break; - - case e_rdwrt : reinterpret_cast(stream_ptr)-> - write(reinterpret_cast(view.begin() + offset) , amount * sizeof(typename View::value_t)); - break; - - default : return false; - } - - return true; - } - - template - bool read(View& view, const std::size_t amount, const std::size_t offset = 0) - { - switch (mode) - { - case e_read : reinterpret_cast(stream_ptr)-> - read(reinterpret_cast(view.begin() + offset), amount * sizeof(typename View::value_t)); - break; - - case e_rdwrt : reinterpret_cast(stream_ptr)-> - read(reinterpret_cast(view.begin() + offset) , amount * sizeof(typename View::value_t)); - break; - - default : return false; - } - - return true; - } - - bool getline(std::string& s) - { - switch (mode) - { - case e_read : return (!!std::getline(*reinterpret_cast(stream_ptr),s)); - case e_rdwrt : return (!!std::getline(*reinterpret_cast(stream_ptr),s)); - default : return false; - } - } - - bool eof() const - { - switch (mode) - { - case e_read : return reinterpret_cast(stream_ptr)->eof(); - case e_write : return reinterpret_cast(stream_ptr)->eof(); - case e_rdwrt : return reinterpret_cast(stream_ptr)->eof(); - default : return true; - } - } - - file_mode get_file_mode(const std::string& access) const - { - if (access.empty() || access.size() > 2) - return e_error; - - std::size_t w_cnt = 0; - std::size_t r_cnt = 0; - - for (std::size_t i = 0; i < access.size(); ++i) - { - switch (std::tolower(access[i])) - { - case 'r' : r_cnt++; break; - case 'w' : w_cnt++; break; - default : return e_error; - } - } - - if ((0 == r_cnt) && (0 == w_cnt)) - return e_error; - else if ((r_cnt > 1) || (w_cnt > 1)) - return e_error; - else if ((1 == r_cnt) && (1 == w_cnt)) - return e_rdwrt; - else if (1 == r_cnt) - return e_read; - else - return e_write; - } - }; - - template - file_descriptor* make_handle(T v) - { - file_descriptor* fd = reinterpret_cast(0); - - std::memcpy(reinterpret_cast(&fd), - reinterpret_cast(&v), - sizeof(fd)); - return fd; - } - - template - void perform_check() - { - #ifdef _MSC_VER - #pragma warning(push) - #pragma warning(disable: 4127) - #endif - if (sizeof(T) < sizeof(void*)) - { - throw std::runtime_error("exprtk::rtl::io::file - Error - pointer size larger than holder."); - } - #ifdef _MSC_VER - #pragma warning(pop) - #endif - } - - } // namespace exprtk::rtl::io::file::details - - template - class open : public exprtk::igeneric_function - { - public: - - typedef typename exprtk::igeneric_function igfun_t; - typedef typename igfun_t::parameter_list_t parameter_list_t; - typedef typename igfun_t::generic_type generic_type; - typedef typename generic_type::string_view string_t; - - using exprtk::igeneric_function::operator(); - - open() - : exprtk::igeneric_function("S|SS") - { details::perform_check(); } - - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) - { - std::string file_name = to_str(string_t(parameters[0])); - std::string access; - - if (file_name.empty()) - return T(0); - - if (0 == ps_index) - access = "r"; - else if (0 == string_t(parameters[1]).size()) - return T(0); - else - access = to_str(string_t(parameters[1])); - - details::file_descriptor* fd = new details::file_descriptor(file_name,access); - - if (fd->open()) - { - T t = T(0); - - std::memcpy(reinterpret_cast(&t ), - reinterpret_cast(&fd), - sizeof(fd)); - return t; - } - else - { - delete fd; - return T(0); - } - } - }; - - template - struct close : public exprtk::ifunction - { - using exprtk::ifunction::operator(); - - close() - : exprtk::ifunction(1) - { details::perform_check(); } - - inline T operator() (const T& v) - { - details::file_descriptor* fd = details::make_handle(v); - - if (!fd->close()) - return T(0); - - delete fd; - - return T(1); - } - }; - - template - class write : public exprtk::igeneric_function - { - public: - - typedef typename exprtk::igeneric_function igfun_t; - typedef typename igfun_t::parameter_list_t parameter_list_t; - typedef typename igfun_t::generic_type generic_type; - typedef typename generic_type::string_view string_t; - typedef typename generic_type::scalar_view scalar_t; - typedef typename generic_type::vector_view vector_t; - - using exprtk::igeneric_function::operator(); - - write() - : igfun_t("TS|TST|TV|TVT") - { details::perform_check(); } - - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) - { - details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])()); - - std::size_t amount = 0; - - switch (ps_index) - { - case 0 : { - const string_t buffer(parameters[1]); - amount = buffer.size(); - return T(fd->write(buffer, amount) ? 1 : 0); - } - - case 1 : { - const string_t buffer(parameters[1]); - amount = std::min(buffer.size(), - static_cast(scalar_t(parameters[2])())); - return T(fd->write(buffer, amount) ? 1 : 0); - } - - case 2 : { - const vector_t vec(parameters[1]); - amount = vec.size(); - return T(fd->write(vec, amount) ? 1 : 0); - } - - case 3 : { - const vector_t vec(parameters[1]); - amount = std::min(vec.size(), - static_cast(scalar_t(parameters[2])())); - return T(fd->write(vec, amount) ? 1 : 0); - } - } - - return T(0); - } - }; - - template - class read : public exprtk::igeneric_function - { - public: - - typedef typename exprtk::igeneric_function igfun_t; - typedef typename igfun_t::parameter_list_t parameter_list_t; - typedef typename igfun_t::generic_type generic_type; - typedef typename generic_type::string_view string_t; - typedef typename generic_type::scalar_view scalar_t; - typedef typename generic_type::vector_view vector_t; - - using exprtk::igeneric_function::operator(); - - read() - : igfun_t("TS|TST|TV|TVT") - { details::perform_check(); } - - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) - { - details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])()); - - std::size_t amount = 0; - - switch (ps_index) - { - case 0 : { - string_t buffer(parameters[1]); - amount = buffer.size(); - return T(fd->read(buffer,amount) ? 1 : 0); - } - - case 1 : { - string_t buffer(parameters[1]); - amount = std::min(buffer.size(), - static_cast(scalar_t(parameters[2])())); - return T(fd->read(buffer,amount) ? 1 : 0); - } - - case 2 : { - vector_t vec(parameters[1]); - amount = vec.size(); - return T(fd->read(vec,amount) ? 1 : 0); - } - - case 3 : { - vector_t vec(parameters[1]); - amount = std::min(vec.size(), - static_cast(scalar_t(parameters[2])())); - return T(fd->read(vec,amount) ? 1 : 0); - } - } - - return T(0); - } - }; - - template - class getline : public exprtk::igeneric_function - { - public: - - typedef typename exprtk::igeneric_function igfun_t; - typedef typename igfun_t::parameter_list_t parameter_list_t; - typedef typename igfun_t::generic_type generic_type; - typedef typename generic_type::string_view string_t; - typedef typename generic_type::scalar_view scalar_t; - - using exprtk::igeneric_function::operator(); - - getline() - : igfun_t("T",igfun_t::e_rtrn_string) - { details::perform_check(); } - - inline T operator() (std::string& result, - parameter_list_t parameters) - { - details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])()); - return T(fd->getline(result) ? 1 : 0); - } - }; - - template - struct eof : public exprtk::ifunction - { - using exprtk::ifunction::operator(); - - eof() - : exprtk::ifunction(1) - { details::perform_check(); } - - inline T operator() (const T& v) - { - details::file_descriptor* fd = details::make_handle(v); - - return (fd->eof() ? T(1) : T(0)); - } - }; - - template - struct package - { - open o; - close c; - write w; - read r; - getline g; - eof e; - - bool register_package(exprtk::symbol_table& symtab) - { - #define exprtk_register_function(FunctionName,FunctionType) \ - if (!symtab.add_function(FunctionName,FunctionType)) \ - { \ - exprtk_debug(( \ - "exprtk::rtl::io::file::register_package - Failed to add function: %s\n", \ - FunctionName)); \ - return false; \ - } \ - - exprtk_register_function("open" , o) - exprtk_register_function("close" , c) - exprtk_register_function("write" , w) - exprtk_register_function("read" , r) - exprtk_register_function("getline", g) - exprtk_register_function("eof" , e) - #undef exprtk_register_function - - return true; - } - }; - - } // namespace exprtk::rtl::io::file - } // namespace exprtk::rtl::io - } // namespace exprtk::rtl -} // namespace exprtk -#endif - -#ifndef exprtk_disable_rtl_vecops -namespace exprtk -{ - namespace rtl { namespace vecops { - - namespace helper - { - template - inline bool invalid_range(const Vector& v, const std::size_t r0, const std::size_t r1) - { - if (r0 > (v.size() - 1)) - return true; - else if (r1 > (v.size() - 1)) - return true; - else if (r1 < r0) - return true; - else - return false; - } - - template - struct load_vector_range - { - typedef typename exprtk::igeneric_function igfun_t; - typedef typename igfun_t::parameter_list_t parameter_list_t; - typedef typename igfun_t::generic_type generic_type; - typedef typename generic_type::scalar_view scalar_t; - typedef typename generic_type::vector_view vector_t; - - static inline bool process(parameter_list_t& parameters, - std::size_t& r0, std::size_t& r1, - const std::size_t& r0_prmidx, - const std::size_t& r1_prmidx, - const std::size_t vec_idx = 0) - { - if (r0_prmidx >= parameters.size()) - return false; - - if (r1_prmidx >= parameters.size()) - return false; - - if (!scalar_t(parameters[r0_prmidx]).to_uint(r0)) - return false; - - if (!scalar_t(parameters[r1_prmidx]).to_uint(r1)) - return false; - - return !invalid_range(vector_t(parameters[vec_idx]), r0, r1); - } - }; - } - - namespace details - { - template - inline void kahan_sum(T& sum, T& error, const T v) - { - const T x = v - error; - const T y = sum + x; - error = (y - sum) - x; - sum = y; - } - - } // namespace exprtk::rtl::details - - template - class all_true : public exprtk::igeneric_function - { - public: - - typedef typename exprtk::igeneric_function igfun_t; - typedef typename igfun_t::parameter_list_t parameter_list_t; - typedef typename igfun_t::generic_type generic_type; - typedef typename generic_type::vector_view vector_t; - - using exprtk::igeneric_function::operator(); - - all_true() - : exprtk::igeneric_function("V|VTT") - /* - Overloads: - 0. V - vector - 1. VTT - vector, r0, r1 - */ - {} - - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) - { - const vector_t vec(parameters[0]); - - std::size_t r0 = 0; - std::size_t r1 = vec.size() - 1; - - if ( - (1 == ps_index) && - !helper::load_vector_range::process(parameters, r0, r1, 1, 2, 0) - ) - return std::numeric_limits::quiet_NaN(); - - for (std::size_t i = r0; i <= r1; ++i) - { - if (vec[i] == T(0)) - { - return T(0); - } - } - - return T(1); - } - }; - - template - class all_false : public exprtk::igeneric_function - { - public: - - typedef typename exprtk::igeneric_function igfun_t; - typedef typename igfun_t::parameter_list_t parameter_list_t; - typedef typename igfun_t::generic_type generic_type; - typedef typename generic_type::vector_view vector_t; - - using exprtk::igeneric_function::operator(); - - all_false() - : exprtk::igeneric_function("V|VTT") - /* - Overloads: - 0. V - vector - 1. VTT - vector, r0, r1 - */ - {} - - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) - { - const vector_t vec(parameters[0]); - - std::size_t r0 = 0; - std::size_t r1 = vec.size() - 1; - - if ( - (1 == ps_index) && - !helper::load_vector_range::process(parameters, r0, r1, 1, 2, 0) - ) - return std::numeric_limits::quiet_NaN(); - - for (std::size_t i = r0; i <= r1; ++i) - { - if (vec[i] != T(0)) - { - return T(0); - } - } - - return T(1); - } - }; - - template - class any_true : public exprtk::igeneric_function - { - public: - - typedef typename exprtk::igeneric_function igfun_t; - typedef typename igfun_t::parameter_list_t parameter_list_t; - typedef typename igfun_t::generic_type generic_type; - typedef typename generic_type::vector_view vector_t; - - using exprtk::igeneric_function::operator(); - - any_true() - : exprtk::igeneric_function("V|VTT") - /* - Overloads: - 0. V - vector - 1. VTT - vector, r0, r1 - */ - {} - - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) - { - const vector_t vec(parameters[0]); - - std::size_t r0 = 0; - std::size_t r1 = vec.size() - 1; - - if ( - (1 == ps_index) && - !helper::load_vector_range::process(parameters, r0, r1, 1, 2, 0) - ) - return std::numeric_limits::quiet_NaN(); - - for (std::size_t i = r0; i <= r1; ++i) - { - if (vec[i] != T(0)) - { - return T(1); - } - } - - return T(0); - } - }; - - template - class any_false : public exprtk::igeneric_function - { - public: - - typedef typename exprtk::igeneric_function igfun_t; - typedef typename igfun_t::parameter_list_t parameter_list_t; - typedef typename igfun_t::generic_type generic_type; - typedef typename generic_type::vector_view vector_t; - - using exprtk::igeneric_function::operator(); - - any_false() - : exprtk::igeneric_function("V|VTT") - /* - Overloads: - 0. V - vector - 1. VTT - vector, r0, r1 - */ - {} - - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) - { - const vector_t vec(parameters[0]); - - std::size_t r0 = 0; - std::size_t r1 = vec.size() - 1; - - if ( - (1 == ps_index) && - !helper::load_vector_range::process(parameters, r0, r1, 1, 2, 0) - ) - return std::numeric_limits::quiet_NaN(); - - for (std::size_t i = r0; i <= r1; ++i) - { - if (vec[i] == T(0)) - { - return T(1); - } - } - - return T(0); - } - }; - - template - class count : public exprtk::igeneric_function - { - public: - - typedef typename exprtk::igeneric_function igfun_t; - typedef typename igfun_t::parameter_list_t parameter_list_t; - typedef typename igfun_t::generic_type generic_type; - typedef typename generic_type::vector_view vector_t; - - using exprtk::igeneric_function::operator(); - - count() - : exprtk::igeneric_function("V|VTT") - /* - Overloads: - 0. V - vector - 1. VTT - vector, r0, r1 - */ - {} - - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) - { - const vector_t vec(parameters[0]); - - std::size_t r0 = 0; - std::size_t r1 = vec.size() - 1; - - if ( - (1 == ps_index) && - !helper::load_vector_range::process(parameters, r0, r1, 1, 2, 0) - ) - return std::numeric_limits::quiet_NaN(); - - std::size_t cnt = 0; - - for (std::size_t i = r0; i <= r1; ++i) - { - if (vec[i] != T(0)) ++cnt; - } - - return T(cnt); - } - }; - - template - class copy : public exprtk::igeneric_function - { - public: - - typedef typename exprtk::igeneric_function igfun_t; - typedef typename igfun_t::parameter_list_t parameter_list_t; - typedef typename igfun_t::generic_type generic_type; - typedef typename generic_type::scalar_view scalar_t; - typedef typename generic_type::vector_view vector_t; - - using exprtk::igeneric_function::operator(); - - copy() - : exprtk::igeneric_function("VV|VTTVTT") - /* - Overloads: - 0. VV - x(vector), y(vector) - 1. VTTVTT - x(vector), xr0, xr1, y(vector), yr0, yr1, - */ - {} - - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) - { - const vector_t x(parameters[0]); - vector_t y(parameters[(0 == ps_index) ? 1 : 3]); - - std::size_t xr0 = 0; - std::size_t xr1 = x.size() - 1; - - std::size_t yr0 = 0; - std::size_t yr1 = y.size() - 1; - - if (1 == ps_index) - { - if ( - !helper::load_vector_range::process(parameters, xr0, xr1, 1, 2, 0) || - !helper::load_vector_range::process(parameters, yr0, yr1, 4, 5, 3) - ) - return T(0); - } - - const std::size_t n = std::min(xr1 - xr0 + 1, yr1 - yr0 + 1); - - std::copy(x.begin() + xr0, x.begin() + xr0 + n, y.begin() + yr0); - - return T(n); - } - }; - - template - class rol : public exprtk::igeneric_function - { - public: - - typedef typename exprtk::igeneric_function igfun_t; - typedef typename igfun_t::parameter_list_t parameter_list_t; - typedef typename igfun_t::generic_type generic_type; - typedef typename generic_type::scalar_view scalar_t; - typedef typename generic_type::vector_view vector_t; - - using exprtk::igeneric_function::operator(); - - rol() - : exprtk::igeneric_function("VT|VTTT") - /* - Overloads: - 0. VT - vector, N - 1. VTTT - vector, N, r0, r1 - */ - {} - - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) - { - vector_t vec(parameters[0]); - - std::size_t n = 0; - std::size_t r0 = 0; - std::size_t r1 = vec.size() - 1; - - if (!scalar_t(parameters[1]).to_uint(n)) - return T(0); - - if ( - (1 == ps_index) && - !helper::load_vector_range::process(parameters, r0, r1, 2, 3, 0) - ) - return T(0); - - const std::size_t dist = r1 - r0 + 1; - const std::size_t shift = n % dist; - - std::rotate( - vec.begin() + r0, - vec.begin() + r0 + shift, - vec.begin() + r1 + 1); - - return T(1); - } - }; - - template - class ror : public exprtk::igeneric_function - { - public: - - typedef typename exprtk::igeneric_function igfun_t; - typedef typename igfun_t::parameter_list_t parameter_list_t; - typedef typename igfun_t::generic_type generic_type; - typedef typename generic_type::scalar_view scalar_t; - typedef typename generic_type::vector_view vector_t; - - using exprtk::igeneric_function::operator(); - - ror() - : exprtk::igeneric_function("VT|VTTT") - /* - Overloads: - 0. VT - vector, N - 1. VTTT - vector, N, r0, r1 - */ - {} - - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) - { - vector_t vec(parameters[0]); - - std::size_t n = 0; - std::size_t r0 = 0; - std::size_t r1 = vec.size() - 1; - - if (!scalar_t(parameters[1]).to_uint(n)) - return T(0); - - if ( - (1 == ps_index) && - !helper::load_vector_range::process(parameters, r0, r1, 2, 3, 0) - ) - return T(0); - - std::size_t dist = r1 - r0 + 1; - std::size_t shift = (dist - (n % dist)) % dist; - - std::rotate( - vec.begin() + r0, - vec.begin() + r0 + shift, - vec.begin() + r1 + 1); - - return T(1); - } - }; - - template - class shift_left : public exprtk::igeneric_function - { - public: - - typedef typename exprtk::igeneric_function igfun_t; - typedef typename igfun_t::parameter_list_t parameter_list_t; - typedef typename igfun_t::generic_type generic_type; - typedef typename generic_type::scalar_view scalar_t; - typedef typename generic_type::vector_view vector_t; - - using exprtk::igeneric_function::operator(); - - shift_left() - : exprtk::igeneric_function("VT|VTTT") - /* - Overloads: - 0. VT - vector, N - 1. VTTT - vector, N, r0, r1 - */ - {} - - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) - { - vector_t vec(parameters[0]); - - std::size_t n = 0; - std::size_t r0 = 0; - std::size_t r1 = vec.size() - 1; - - if (!scalar_t(parameters[1]).to_uint(n)) - return T(0); - - if ( - (1 == ps_index) && - !helper::load_vector_range::process(parameters, r0, r1, 2, 3, 0) - ) - return T(0); - - const std::size_t dist = r1 - r0 + 1; - - if (n > dist) - return T(0); - - std::rotate( - vec.begin() + r0, - vec.begin() + r0 + n, - vec.begin() + r1 + 1); - - for (std::size_t i = r1 - n + 1; i <= r1; ++i) - { - vec[i] = T(0); - } - - return T(1); - } - }; - - template - class shift_right : public exprtk::igeneric_function - { - public: - - typedef typename exprtk::igeneric_function igfun_t; - typedef typename igfun_t::parameter_list_t parameter_list_t; - typedef typename igfun_t::generic_type generic_type; - typedef typename generic_type::scalar_view scalar_t; - typedef typename generic_type::vector_view vector_t; - - using exprtk::igeneric_function::operator(); - - shift_right() - : exprtk::igeneric_function("VT|VTTT") - /* - Overloads: - 0. VT - vector, N - 1. VTTT - vector, N, r0, r1 - */ - {} - - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) - { - vector_t vec(parameters[0]); - - std::size_t n = 0; - std::size_t r0 = 0; - std::size_t r1 = vec.size() - 1; - - if (!scalar_t(parameters[1]).to_uint(n)) - return T(0); - - if ( - (1 == ps_index) && - !helper::load_vector_range::process(parameters, r0, r1, 2, 3, 0) - ) - return T(0); - - const std::size_t dist = r1 - r0 + 1; - - if (n > dist) - return T(0); - - const std::size_t shift = (dist - (n % dist)) % dist; - - std::rotate( - vec.begin() + r0, - vec.begin() + r0 + shift, - vec.begin() + r1 + 1); - - for (std::size_t i = r0; i < r0 + n; ++i) - { - vec[i] = T(0); - } - - return T(1); - } - }; - - template - class sort : public exprtk::igeneric_function - { - public: - - typedef typename exprtk::igeneric_function igfun_t; - typedef typename igfun_t::parameter_list_t parameter_list_t; - typedef typename igfun_t::generic_type generic_type; - typedef typename generic_type::string_view string_t; - typedef typename generic_type::vector_view vector_t; - - using exprtk::igeneric_function::operator(); - - sort() - : exprtk::igeneric_function("V|VTT|VS|VSTT") - /* - Overloads: - 0. V - vector - 1. VTT - vector, r0, r1 - 2. VS - vector, string - 3. VSTT - vector, string, r0, r1 - */ - {} - - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) - { - vector_t vec(parameters[0]); - - std::size_t r0 = 0; - std::size_t r1 = vec.size() - 1; - - if ((1 == ps_index) && !helper::load_vector_range::process(parameters, r0, r1, 1, 2, 0)) - return T(0); - if ((3 == ps_index) && !helper::load_vector_range::process(parameters, r0, r1, 2, 3, 0)) - return T(0); - - bool ascending = true; - - if ((2 == ps_index) || (3 == ps_index)) - { - if (exprtk::details::imatch(to_str(string_t(parameters[1])),"ascending")) - ascending = true; - else if (exprtk::details::imatch(to_str(string_t(parameters[1])),"descending")) - ascending = false; - else - return T(0); - } - - if (ascending) - std::sort(vec.begin() + r0, vec.begin() + r1 + 1, std::less ()); - else - std::sort(vec.begin() + r0, vec.begin() + r1 + 1, std::greater()); - - return T(1); - } - }; - - template - class nthelement : public exprtk::igeneric_function - { - public: - - typedef typename exprtk::igeneric_function igfun_t; - typedef typename igfun_t::parameter_list_t parameter_list_t; - typedef typename igfun_t::generic_type generic_type; - typedef typename generic_type::scalar_view scalar_t; - typedef typename generic_type::vector_view vector_t; - - using exprtk::igeneric_function::operator(); - - nthelement() - : exprtk::igeneric_function("VT|VTTT") - /* - Overloads: - 0. VT - vector, nth-element - 1. VTTT - vector, nth-element, r0, r1 - */ - {} - - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) - { - vector_t vec(parameters[0]); - - std::size_t n = 0; - std::size_t r0 = 0; - std::size_t r1 = vec.size() - 1; - - if (!scalar_t(parameters[1]).to_uint(n)) - return T(0); - - if ((1 == ps_index) && !helper::load_vector_range::process(parameters, r0, r1, 2, 3, 0)) - return std::numeric_limits::quiet_NaN(); - - std::nth_element(vec.begin() + r0, vec.begin() + r0 + n , vec.begin() + r1 + 1); - - return T(1); - } - }; - - template - class iota : public exprtk::igeneric_function - { - public: - - typedef typename exprtk::igeneric_function igfun_t; - typedef typename igfun_t::parameter_list_t parameter_list_t; - typedef typename igfun_t::generic_type generic_type; - typedef typename generic_type::scalar_view scalar_t; - typedef typename generic_type::vector_view vector_t; - - using exprtk::igeneric_function::operator(); - - iota() - : exprtk::igeneric_function("VT|VTT|VTTT|VTTTT") - /* - Overloads: - 0. VT - vector, increment - 1. VTT - vector, increment, base - 2. VTTTT - vector, increment, r0, r1 - 3. VTTTT - vector, increment, base, r0, r1 - */ - {} - - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) - { - vector_t vec(parameters[0]); - - T increment = scalar_t(parameters[1])(); - T base = ((1 == ps_index) || (3 == ps_index)) ? scalar_t(parameters[2])() : T(0); - - std::size_t r0 = 0; - std::size_t r1 = vec.size() - 1; - - if ((2 == ps_index) && !helper::load_vector_range::process(parameters, r0, r1, 2, 3, 0)) - return std::numeric_limits::quiet_NaN(); - else if ((3 == ps_index) && !helper::load_vector_range::process(parameters, r0, r1, 3, 4, 0)) - return std::numeric_limits::quiet_NaN(); - else - { - long long j = 0; - - for (std::size_t i = r0; i <= r1; ++i, ++j) - { - vec[i] = base + (increment * j); - } - } - - return T(1); - } - }; - - template - class sumk : public exprtk::igeneric_function - { - public: - - typedef typename exprtk::igeneric_function igfun_t; - typedef typename igfun_t::parameter_list_t parameter_list_t; - typedef typename igfun_t::generic_type generic_type; - typedef typename generic_type::vector_view vector_t; - - using exprtk::igeneric_function::operator(); - - sumk() - : exprtk::igeneric_function("V|VTT") - /* - Overloads: - 0. V - vector - 1. VTT - vector, r0, r1 - */ - {} - - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) - { - const vector_t vec(parameters[0]); - - std::size_t r0 = 0; - std::size_t r1 = vec.size() - 1; - - if ((1 == ps_index) && !helper::load_vector_range::process(parameters, r0, r1, 1, 2, 0)) - return std::numeric_limits::quiet_NaN(); - - T result = T(0); - T error = T(0); - - for (std::size_t i = r0; i <= r1; ++i) - { - details::kahan_sum(result, error, vec[i]); - } - - return result; - } - }; - - template - class axpy : public exprtk::igeneric_function - { - public: - - typedef typename exprtk::igeneric_function igfun_t; - typedef typename igfun_t::parameter_list_t parameter_list_t; - typedef typename igfun_t::generic_type generic_type; - typedef typename generic_type::scalar_view scalar_t; - typedef typename generic_type::vector_view vector_t; - - using exprtk::igeneric_function::operator(); - - axpy() - : exprtk::igeneric_function("TVV|TVVTT") - /* - y <- ax + y - Overloads: - 0. TVV - a, x(vector), y(vector) - 1. TVVTT - a, x(vector), y(vector), r0, r1 - */ - {} - - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) - { - const vector_t x(parameters[1]); - vector_t y(parameters[2]); - - std::size_t r0 = 0; - std::size_t r1 = std::min(x.size(),y.size()) - 1; - - if ((1 == ps_index) && !helper::load_vector_range::process(parameters, r0, r1, 3, 4, 1)) - return std::numeric_limits::quiet_NaN(); - else if (helper::invalid_range(y, r0, r1)) - return std::numeric_limits::quiet_NaN(); - - const T a = scalar_t(parameters[0])(); - - for (std::size_t i = r0; i <= r1; ++i) - { - y[i] = (a * x[i]) + y[i]; - } - - return T(1); - } - }; - - template - class axpby : public exprtk::igeneric_function - { - public: - - typedef typename exprtk::igeneric_function igfun_t; - typedef typename igfun_t::parameter_list_t parameter_list_t; - typedef typename igfun_t::generic_type generic_type; - typedef typename generic_type::scalar_view scalar_t; - typedef typename generic_type::vector_view vector_t; - - using exprtk::igeneric_function::operator(); - - axpby() - : exprtk::igeneric_function("TVTV|TVTVTT") - /* - y <- ax + by - Overloads: - 0. TVTV - a, x(vector), b, y(vector) - 1. TVTVTT - a, x(vector), b, y(vector), r0, r1 - */ - {} - - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) - { - const vector_t x(parameters[1]); - vector_t y(parameters[3]); - - std::size_t r0 = 0; - std::size_t r1 = std::min(x.size(),y.size()) - 1; - - if ((1 == ps_index) && !helper::load_vector_range::process(parameters, r0, r1, 4, 5, 1)) - return std::numeric_limits::quiet_NaN(); - else if (helper::invalid_range(y, r0, r1)) - return std::numeric_limits::quiet_NaN(); - - const T a = scalar_t(parameters[0])(); - const T b = scalar_t(parameters[2])(); - - for (std::size_t i = r0; i <= r1; ++i) - { - y[i] = (a * x[i]) + (b * y[i]); - } - - return T(1); - } - }; - - template - class axpyz : public exprtk::igeneric_function - { - public: - - typedef typename exprtk::igeneric_function igfun_t; - typedef typename igfun_t::parameter_list_t parameter_list_t; - typedef typename igfun_t::generic_type generic_type; - typedef typename generic_type::scalar_view scalar_t; - typedef typename generic_type::vector_view vector_t; - - using exprtk::igeneric_function::operator(); - - axpyz() - : exprtk::igeneric_function("TVVV|TVVVTT") - /* - z <- ax + y - Overloads: - 0. TVVV - a, x(vector), y(vector), z(vector) - 1. TVVVTT - a, x(vector), y(vector), z(vector), r0, r1 - */ - {} - - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) - { - const vector_t x(parameters[1]); - const vector_t y(parameters[2]); - vector_t z(parameters[3]); - - std::size_t r0 = 0; - std::size_t r1 = std::min(x.size(),y.size()) - 1; - - if ((1 == ps_index) && !helper::load_vector_range::process(parameters, r0, r1, 3, 4, 1)) - return std::numeric_limits::quiet_NaN(); - else if (helper::invalid_range(y, r0, r1)) - return std::numeric_limits::quiet_NaN(); - else if (helper::invalid_range(z, r0, r1)) - return std::numeric_limits::quiet_NaN(); - - const T a = scalar_t(parameters[0])(); - - for (std::size_t i = r0; i <= r1; ++i) - { - z[i] = (a * x[i]) + y[i]; - } - - return T(1); - } - }; - - template - class axpbyz : public exprtk::igeneric_function - { - public: - - typedef typename exprtk::igeneric_function igfun_t; - typedef typename igfun_t::parameter_list_t parameter_list_t; - typedef typename igfun_t::generic_type generic_type; - typedef typename generic_type::scalar_view scalar_t; - typedef typename generic_type::vector_view vector_t; - - using exprtk::igeneric_function::operator(); - - axpbyz() - : exprtk::igeneric_function("TVTVV|TVTVVTT") - /* - z <- ax + by - Overloads: - 0. TVTVV - a, x(vector), b, y(vector), z(vector) - 1. TVTVVTT - a, x(vector), b, y(vector), z(vector), r0, r1 - */ - {} - - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) - { - const vector_t x(parameters[1]); - const vector_t y(parameters[3]); - vector_t z(parameters[4]); - - std::size_t r0 = 0; - std::size_t r1 = std::min(x.size(),y.size()) - 1; - - if ((1 == ps_index) && !helper::load_vector_range::process(parameters, r0, r1, 4, 5, 1)) - return std::numeric_limits::quiet_NaN(); - else if (helper::invalid_range(y, r0, r1)) - return std::numeric_limits::quiet_NaN(); - else if (helper::invalid_range(z, r0, r1)) - return std::numeric_limits::quiet_NaN(); - - const T a = scalar_t(parameters[0])(); - const T b = scalar_t(parameters[2])(); - - for (std::size_t i = r0; i <= r1; ++i) - { - z[i] = (a * x[i]) + (b * y[i]); - } - - return T(1); - } - }; - - template - class axpbz : public exprtk::igeneric_function - { - public: - - typedef typename exprtk::igeneric_function igfun_t; - typedef typename igfun_t::parameter_list_t parameter_list_t; - typedef typename igfun_t::generic_type generic_type; - typedef typename generic_type::scalar_view scalar_t; - typedef typename generic_type::vector_view vector_t; - - using exprtk::igeneric_function::operator(); - - axpbz() - : exprtk::igeneric_function("TVTV|TVTVTT") - /* - z <- ax + b - Overloads: - 0. TVTV - a, x(vector), b, z(vector) - 1. TVTVTT - a, x(vector), b, z(vector), r0, r1 - */ - {} - - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) - { - const vector_t x(parameters[1]); - vector_t z(parameters[3]); - - std::size_t r0 = 0; - std::size_t r1 = x.size() - 1; - - if ((1 == ps_index) && !helper::load_vector_range::process(parameters, r0, r1, 4, 5, 1)) - return std::numeric_limits::quiet_NaN(); - else if (helper::invalid_range(z, r0, r1)) - return std::numeric_limits::quiet_NaN(); - - const T a = scalar_t(parameters[0])(); - const T b = scalar_t(parameters[2])(); - - for (std::size_t i = r0; i <= r1; ++i) - { - z[i] = (a * x[i]) + b; - } - - return T(1); - } - }; - - template - class dot : public exprtk::igeneric_function - { - public: - - typedef typename exprtk::igeneric_function igfun_t; - typedef typename igfun_t::parameter_list_t parameter_list_t; - typedef typename igfun_t::generic_type generic_type; - typedef typename generic_type::scalar_view scalar_t; - typedef typename generic_type::vector_view vector_t; - - using exprtk::igeneric_function::operator(); - - dot() - : exprtk::igeneric_function("VV|VVTT") - /* - Overloads: - 0. VV - x(vector), y(vector) - 1. VVTT - x(vector), y(vector), r0, r1 - */ - {} - - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) - { - const vector_t x(parameters[0]); - const vector_t y(parameters[1]); - - std::size_t r0 = 0; - std::size_t r1 = std::min(x.size(),y.size()) - 1; - - if ((1 == ps_index) && !helper::load_vector_range::process(parameters, r0, r1, 2, 3, 0)) - return std::numeric_limits::quiet_NaN(); - else if (helper::invalid_range(y, r0, r1)) - return std::numeric_limits::quiet_NaN(); - - T result = T(0); - - for (std::size_t i = r0; i <= r1; ++i) - { - result += (x[i] * y[i]); - } - - return result; - } - }; - - template - class dotk : public exprtk::igeneric_function - { - public: - - typedef typename exprtk::igeneric_function igfun_t; - typedef typename igfun_t::parameter_list_t parameter_list_t; - typedef typename igfun_t::generic_type generic_type; - typedef typename generic_type::scalar_view scalar_t; - typedef typename generic_type::vector_view vector_t; - - using exprtk::igeneric_function::operator(); - - dotk() - : exprtk::igeneric_function("VV|VVTT") - /* - Overloads: - 0. VV - x(vector), y(vector) - 1. VVTT - x(vector), y(vector), r0, r1 - */ - {} - - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) - { - const vector_t x(parameters[0]); - const vector_t y(parameters[1]); - - std::size_t r0 = 0; - std::size_t r1 = std::min(x.size(),y.size()) - 1; - - if ((1 == ps_index) && !helper::load_vector_range::process(parameters, r0, r1, 2, 3, 0)) - return std::numeric_limits::quiet_NaN(); - else if (helper::invalid_range(y, r0, r1)) - return std::numeric_limits::quiet_NaN(); - - T result = T(0); - T error = T(0); - - for (std::size_t i = r0; i <= r1; ++i) - { - details::kahan_sum(result, error, (x[i] * y[i])); - } - - return result; - } - }; - - template - struct package - { - all_true at; - all_false af; - any_true nt; - any_false nf; - count c; - copy cp; - rol rl; - ror rr; - shift_left sl; - shift_right sr; - sort st; - nthelement ne; - iota ia; - sumk sk; - axpy b1_axpy; - axpby b1_axpby; - axpyz b1_axpyz; - axpbyz b1_axpbyz; - axpbz b1_axpbz; - dot dt; - dotk dtk; - - bool register_package(exprtk::symbol_table& symtab) - { - #define exprtk_register_function(FunctionName,FunctionType) \ - if (!symtab.add_function(FunctionName,FunctionType)) \ - { \ - exprtk_debug(( \ - "exprtk::rtl::vecops::register_package - Failed to add function: %s\n", \ - FunctionName)); \ - return false; \ - } \ - - exprtk_register_function("all_true" , at ) - exprtk_register_function("all_false" , af ) - exprtk_register_function("any_true" , nt ) - exprtk_register_function("any_false" , nf ) - exprtk_register_function("count" , c ) - exprtk_register_function("copy" , cp ) - exprtk_register_function("rotate_left" , rl ) - exprtk_register_function("rol" , rl ) - exprtk_register_function("rotate_right" , rr ) - exprtk_register_function("ror" , rr ) - exprtk_register_function("shftl" , sl ) - exprtk_register_function("shftr" , sr ) - exprtk_register_function("sort" , st ) - exprtk_register_function("nth_element" , ne ) - exprtk_register_function("iota" , ia ) - exprtk_register_function("sumk" , sk ) - exprtk_register_function("axpy" , b1_axpy ) - exprtk_register_function("axpby" , b1_axpby ) - exprtk_register_function("axpyz" , b1_axpyz ) - exprtk_register_function("axpbyz" , b1_axpbyz) - exprtk_register_function("axpbz" , b1_axpbz ) - exprtk_register_function("dot" , dt ) - exprtk_register_function("dotk" , dtk ) - #undef exprtk_register_function - - return true; - } - }; - - } // namespace exprtk::rtl::vecops - } // namespace exprtk::rtl -} // namespace exprtk -#endif - -namespace exprtk -{ - namespace information - { - static const char* library = "Mathematical Expression Toolkit"; - static const char* version = "2.718281828459045235360287471352" - "66249775724709369995957496696762" - "77240766303535475945713821785251" - "66427427466391932003059921817413"; - static const char* date = "20210101"; - - static inline std::string data() - { - static const std::string info_str = std::string(library) + - std::string(" v") + std::string(version) + - std::string(" (") + date + std::string(")"); - return info_str; - } - - } // namespace information - - #ifdef exprtk_debug - #undef exprtk_debug - #endif - - #ifdef exprtk_error_location - #undef exprtk_error_location - #endif - - #ifdef exprtk_disable_fallthrough_begin - #undef exprtk_disable_fallthrough_begin - #endif - - #ifdef exprtk_disable_fallthrough_end - #undef exprtk_disable_fallthrough_end - #endif - - #ifdef exprtk_override - #undef exprtk_override - #endif - - #ifdef exprtk_final - #undef exprtk_final - #endif - -} // namespace exprtk - -#endif diff --git a/gui/main.cpp b/gui/main.cpp deleted file mode 100644 index 81146ee..0000000 --- a/gui/main.cpp +++ /dev/null @@ -1,13 +0,0 @@ -/** - * @file main.cpp - * @brief Program entry point. - * - * Written by Clyne Sullivan. - */ - -#include "wxapp.hpp" - -#include - -wxIMPLEMENT_APP(MainApp); - diff --git a/gui/serial b/gui/serial deleted file mode 160000 index cbcca7c..0000000 --- a/gui/serial +++ /dev/null @@ -1 +0,0 @@ -Subproject commit cbcca7c83745fedd75afb7a0a27ee5c4112435c2 diff --git a/gui/stmdsp.cpp b/gui/stmdsp.cpp deleted file mode 100644 index 7a55562..0000000 --- a/gui/stmdsp.cpp +++ /dev/null @@ -1,208 +0,0 @@ -/** - * @file stmdsp.cpp - * @brief Interface for communication with stmdsp device over serial. - * - * Copyright (C) 2021 Clyne Sullivan - * - * Distributed under the GNU GPL v3 or later. You should have received a copy of - * the GNU General Public License along with this program. - * If not, see . - */ - -#include "stmdsp.hpp" - -#include - -namespace stmdsp -{ - std::list& scanner::scan() - { - auto devices = serial::list_ports(); - for (auto& device : devices) { - if (device.hardware_id.find(STMDSP_USB_ID) != std::string::npos) - m_available_devices.emplace_front(device.port); - } - - return m_available_devices; - } - - device::device(const std::string& file) : - m_serial(file, 1000000/*230400*/, serial::Timeout::simpleTimeout(50)) - { - if (m_serial.isOpen()) { - m_serial.flush(); - m_serial.write("i"); - if (auto id = m_serial.read(7); id.starts_with("stmdsp")) { - if (id.back() == 'h') - m_platform = platform::H7; - else if (id.back() == 'l') - m_platform = platform::L4; - else - m_serial.close(); - } else { - m_serial.close(); - } - } - } - - void device::continuous_set_buffer_size(unsigned int size) { - if (connected()) { - m_buffer_size = size; - - uint8_t request[3] = { - 'B', - static_cast(size), - static_cast(size >> 8) - }; - m_serial.write(request, 3); - } - } - - void device::set_sample_rate(unsigned int id) { - if (connected()) { - uint8_t request[2] = { - 'r', - static_cast(id) - }; - m_serial.write(request, 2); - } - } - - unsigned int device::get_sample_rate() { - unsigned char result = 0xFF; - - if (connected()) { - uint8_t request[2] = { - 'r', 0xFF - }; - m_serial.write(request, 2); - m_serial.read(&result, 1); - } - - return result; - } - - void device::continuous_start() { - if (connected()) - m_serial.write("R"); - } - - void device::continuous_start_measure() { - if (connected()) - m_serial.write("M"); - } - - uint32_t device::continuous_start_get_measurement() { - uint32_t count = 0; - if (connected()) { - m_serial.write("m"); - m_serial.read(reinterpret_cast(&count), sizeof(uint32_t)); - } - - return count / 2; - } - - std::vector device::continuous_read() { - if (connected()) { - m_serial.write("s"); - unsigned char sizebytes[2]; - m_serial.read(sizebytes, 2); - unsigned int size = sizebytes[0] | (sizebytes[1] << 8); - if (size > 0) { - std::vector data (size); - unsigned int total = size * sizeof(adcsample_t); - unsigned int offset = 0; - - while (total > 512) { - m_serial.read(reinterpret_cast(&data[0]) + offset, 512); - m_serial.write("n"); - offset += 512; - total -= 512; - } - m_serial.read(reinterpret_cast(&data[0]) + offset, total); - m_serial.write("n"); - return data; - - } - } - - return {}; - } - - std::vector device::continuous_read_input() { - if (connected()) { - m_serial.write("t"); - unsigned char sizebytes[2]; - m_serial.read(sizebytes, 2); - unsigned int size = sizebytes[0] | (sizebytes[1] << 8); - if (size > 0) { - std::vector data (size); - unsigned int total = size * sizeof(adcsample_t); - unsigned int offset = 0; - - while (total > 512) { - m_serial.read(reinterpret_cast(&data[0]) + offset, 512); - m_serial.write("n"); - offset += 512; - total -= 512; - } - m_serial.read(reinterpret_cast(&data[0]) + offset, total); - m_serial.write("n"); - return data; - - } - } - - return {}; - } - - void device::continuous_stop() { - if (connected()) - m_serial.write("S"); - } - - void device::siggen_upload(dacsample_t *buffer, unsigned int size) { - if (connected()) { - uint8_t request[3] = { - 'D', - static_cast(size), - static_cast(size >> 8) - }; - m_serial.write(request, 3); - - m_serial.write((uint8_t *)buffer, size * sizeof(dacsample_t)); - } - } - - void device::siggen_start() { - if (connected()) { - m_is_siggening = true; - m_serial.write("W"); - } - } - - void device::siggen_stop() { - if (connected()) { - m_is_siggening = false; - m_serial.write("w"); - } - } - - void device::upload_filter(unsigned char *buffer, size_t size) { - if (connected()) { - uint8_t request[3] = { - 'E', - static_cast(size), - static_cast(size >> 8) - }; - m_serial.write(request, 3); - - m_serial.write(buffer, size); - } - } - - void device::unload_filter() { - if (connected()) - m_serial.write("e"); - } -} diff --git a/gui/stmdsp.hpp b/gui/stmdsp.hpp deleted file mode 100644 index c15633a..0000000 --- a/gui/stmdsp.hpp +++ /dev/null @@ -1,97 +0,0 @@ -/** - * @file stmdsp.hpp - * @brief Interface for communication with stmdsp device over serial. - * - * Copyright (C) 2021 Clyne Sullivan - * - * Distributed under the GNU GPL v3 or later. You should have received a copy of - * the GNU General Public License along with this program. - * If not, see . - */ - -#ifndef STMDSP_HPP_ -#define STMDSP_HPP_ - -#include -#include -#include -#include - -namespace stmdsp -{ - constexpr unsigned int SAMPLES_MAX = 4096; - - class scanner - { - private: - constexpr static const char *STMDSP_USB_ID = -#ifndef STMDSP_WIN32 - "USB VID:PID=0483:5740"; -#else - "USB\\VID_0483&PID_5740"; -#endif - - public: - std::list& scan(); - auto& devices() { - return m_available_devices; - } - - private: - std::list m_available_devices; - }; - - using adcsample_t = uint16_t; - using dacsample_t = uint16_t; - - enum class platform { - Unknown, - H7, - L4, - G4 - }; - - class device - { - public: - device(const std::string& file); - - ~device() { - m_serial.close(); - } - - bool connected() { - return m_serial.isOpen(); - } - - auto get_platform() const { return m_platform; } - void continuous_set_buffer_size(unsigned int size); - unsigned int get_buffer_size() const { return m_buffer_size; } - void set_sample_rate(unsigned int id); - unsigned int get_sample_rate(); - void continuous_start(); - void continuous_start_measure(); - uint32_t continuous_start_get_measurement(); - std::vector continuous_read(); - std::vector continuous_read_input(); - void continuous_stop(); - - void siggen_upload(dacsample_t *buffer, unsigned int size); - void siggen_start(); - void siggen_stop(); - bool is_siggening() const { return m_is_siggening; } - - // buffer is ELF binary - void upload_filter(unsigned char *buffer, size_t size); - void unload_filter(); - - private: - serial::Serial m_serial; - platform m_platform = platform::Unknown; - unsigned int m_buffer_size = SAMPLES_MAX; - bool m_is_siggening = false; - }; -} - -#endif // STMDSP_HPP_ - diff --git a/gui/templates/1_convolve_simple.cpp b/gui/templates/1_convolve_simple.cpp deleted file mode 100644 index 0f1973d..0000000 --- a/gui/templates/1_convolve_simple.cpp +++ /dev/null @@ -1,29 +0,0 @@ -/** - * 1_convolve_simple.cpp - * Written by Clyne Sullivan. - * - * Computes a convolution in the simplest way possible. While the code is brief, it lacks many - * possible optimizations. The convolution's result will not fill the output buffer either, as the - * transient response is not calculated. - */ - -adcsample_t *process_data(adcsample_t *samples, unsigned int size) -{ - // Define our output buffer. SIZE is the largest size of the 'samples' buffer. - static adcsample_t buffer[SIZE]; - - // Define our filter - constexpr unsigned int filter_size = 3; - float filter[filter_size] = { - 0.3333, 0.3333, 0.3333 - }; - - // Begin convolving: - for (int n = 0; n < size - (filter_size - 1); n++) { - buffer[n] = 0; - for (int k = 0; k < filter_size; k++) - buffer[n] += samples[n + k] * filter[k]; - } - - return buffer; -} diff --git a/gui/templates/2_convolve_overlap_save.cpp b/gui/templates/2_convolve_overlap_save.cpp deleted file mode 100644 index 1387d7f..0000000 --- a/gui/templates/2_convolve_overlap_save.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/** - * 2_convolve_overlap_save.cpp - * Written by Clyne Sullivan. - * - * This convolution examples takes an overlap-save approach, where samples from the previous run - * are saved so that the overall operation is not interrupted (i.e. the observed output will - * transition smoothly between processed "chunks"). - * - * Note that there are still improvements that can be made to the code; for example, notice every - * spot where an integer/float conversion is necessary. Operations like these may slow down the - * computation. - */ - -adcsample_t *process_data(adcsample_t *samples, unsigned int size) -{ - static adcsample_t buffer[SIZE]; - - constexpr unsigned int filter_size = 3; - float filter[filter_size] = { - 0.3333, 0.3333, 0.3333 - }; - - // Keep a buffer of extra samples for overlap-save - static adcsample_t prev[filter_size]; - - for (int n = 0; n < size; n++) { - buffer[n] = 0; - - for (int k = 0; k < filter_size; k++) { - int i = n - (filter_size - 1) + k; - - // If i is >= 0, access current sample buffer. - // If i is < 0, provide the previous samples from the 'prev' buffer - if (i >= 0) - buffer[n] += samples[i] * filter[k]; - else - buffer[n] += prev[filter_size - 1 + i] * filter[k]; - } - } - - // Save samples for the next convolution run - for (int i = 0; i < filter_size; i++) - prev[i] = samples[size - filter_size + i]; - - return buffer; -} - diff --git a/gui/templates/3_fir.cpp b/gui/templates/3_fir.cpp deleted file mode 100644 index 7af66a8..0000000 --- a/gui/templates/3_fir.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/** - * 3_fir.cpp - * Written by Clyne Sullivan. - * - * The below code was written for applying FIR filters. While this is still essentially an overlap- - * save convolution, other optimizations have been made to allow for larger filters to be applied - * within the available execution time. Samples are also normalized so that they center around zero. - */ - -adcsample_t *process_data(adcsample_t *samples, unsigned int size) -{ - static adcsample_t buffer[SIZE]; - - // Define the filter: - constexpr unsigned int filter_size = 3; - static float filter[filter_size] = { - // Put filter values here (note: precision will be truncated for 'float' size). - 0.3333, 0.3333, 0.3333 - }; - - // Do an overlap-save convolution - static adcsample_t prev[filter_size]; - - for (int n = 0; n < size; n++) { - // Using a float variable for accumulation allows for better code optimization - float v = 0; - - for (int k = 0; k < filter_size; k++) { - int i = n - (filter_size - 1) + k; - - auto s = i >= 0 ? samples[i] : prev[filter_size - 1 + i]; - // Sample values are 0 to 4095. Below, the original sample is normalized to a -1.0 to - // 1.0 range for calculation. - v += (s / 2048.f - 1) * filter[k]; - } - - // Return value to sample range of 0-4095. - buffer[n] = (v + 1) * 2048.f; - } - - // Save samples for next convolution - for (int i = 0; i < filter_size; i++) - prev[i] = samples[size - filter_size + i]; - - return buffer; -} - diff --git a/gui/templates/4_fir_pro.cpp b/gui/templates/4_fir_pro.cpp deleted file mode 100644 index 379b83b..0000000 --- a/gui/templates/4_fir_pro.cpp +++ /dev/null @@ -1,478 +0,0 @@ -#include -using float32_t = float; - -typedef struct -{ - uint16_t numTaps; /**< number of filter coefficients in the filter. */ - float32_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ - float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ -} arm_fir_instance_f32; - -static void arm_fir_f32(const arm_fir_instance_f32 * S, float32_t * pSrc, float32_t * pDst, uint32_t blockSize); - -adcsample_t *process_data(adcsample_t *samples, unsigned int size) -{ - // 1. Define our array sizes (Be sure to set Run > Set buffer size... to below value!) - constexpr unsigned int buffer_size = 500; - constexpr unsigned int filter_size = 100; - - // 2. Define our filter and the working arrays - static float filter[filter_size] = { - .01f,.01f,.01f,.01f,.01f,.01f,.01f,.01f,.01f,.01f, - .01f,.01f,.01f,.01f,.01f,.01f,.01f,.01f,.01f,.01f, - .01f,.01f,.01f,.01f,.01f,.01f,.01f,.01f,.01f,.01f, - .01f,.01f,.01f,.01f,.01f,.01f,.01f,.01f,.01f,.01f, - .01f,.01f,.01f,.01f,.01f,.01f,.01f,.01f,.01f,.01f, - .01f,.01f,.01f,.01f,.01f,.01f,.01f,.01f,.01f,.01f, - .01f,.01f,.01f,.01f,.01f,.01f,.01f,.01f,.01f,.01f, - .01f,.01f,.01f,.01f,.01f,.01f,.01f,.01f,.01f,.01f, - .01f,.01f,.01f,.01f,.01f,.01f,.01f,.01f,.01f,.01f, - .01f,.01f,.01f,.01f,.01f,.01f,.01f,.01f,.01f,.01f - }; - static float input[buffer_size]; - static float output[buffer_size]; - static float working[buffer_size + filter_size]; - - // 3. Scale 0-4095 interger sample values to +/- 1.0 floats - for (unsigned int i = 0; i < size; i++) - input[i] = (samples[i] - 2048) / 2048.f; - - // 4. Compute the FIR - arm_fir_instance_f32 fir { filter_size, working, filter }; - arm_fir_f32(&fir, input, output, size); - - // 5. Convert float results back to 0-4095 range for output - for (unsigned int i = 0; i < size; i++) - samples[i] = output[i] * 2048.f + 2048; - - return samples; -} - -// Below taken from the CMSIS DSP Library (find it on GitHub) -void arm_fir_f32( - const arm_fir_instance_f32 * S, - float32_t * pSrc, - float32_t * pDst, - uint32_t blockSize) -{ - float32_t *pState = S->pState; /* State pointer */ - float32_t *pCoeffs = S->pCoeffs; /* Coefficient pointer */ - float32_t *pStateCurnt; /* Points to the current sample of the state */ - float32_t *px, *pb; /* Temporary pointers for state and coefficient buffers */ - float32_t acc0, acc1, acc2, acc3, acc4, acc5, acc6, acc7; /* Accumulators */ - float32_t x0, x1, x2, x3, x4, x5, x6, x7, c0; /* Temporary variables to hold state and coefficient values */ - uint32_t numTaps = S->numTaps; /* Number of filter coefficients in the filter */ - uint32_t i, tapCnt, blkCnt; /* Loop counters */ - float32_t p0,p1,p2,p3,p4,p5,p6,p7; /* Temporary product values */ - - /* S->pState points to state array which contains previous frame (numTaps - 1) samples */ - /* pStateCurnt points to the location where the new input data should be written */ - pStateCurnt = &(S->pState[(numTaps - 1u)]); - - /* Apply loop unrolling and compute 8 output values simultaneously. - * The variables acc0 ... acc7 hold output values that are being computed: - * - * acc0 = b[numTaps-1] * x[n-numTaps-1] + b[numTaps-2] * x[n-numTaps-2] + b[numTaps-3] * x[n-numTaps-3] +...+ b[0] * x[0] - * acc1 = b[numTaps-1] * x[n-numTaps] + b[numTaps-2] * x[n-numTaps-1] + b[numTaps-3] * x[n-numTaps-2] +...+ b[0] * x[1] - * acc2 = b[numTaps-1] * x[n-numTaps+1] + b[numTaps-2] * x[n-numTaps] + b[numTaps-3] * x[n-numTaps-1] +...+ b[0] * x[2] - * acc3 = b[numTaps-1] * x[n-numTaps+2] + b[numTaps-2] * x[n-numTaps+1] + b[numTaps-3] * x[n-numTaps] +...+ b[0] * x[3] - */ - blkCnt = blockSize >> 3; - - /* First part of the processing with loop unrolling. Compute 8 outputs at a time. - ** a second loop below computes the remaining 1 to 7 samples. */ - while(blkCnt > 0u) - { - /* Copy four new input samples into the state buffer */ - *pStateCurnt++ = *pSrc++; - *pStateCurnt++ = *pSrc++; - *pStateCurnt++ = *pSrc++; - *pStateCurnt++ = *pSrc++; - - /* Set all accumulators to zero */ - acc0 = 0.0f; - acc1 = 0.0f; - acc2 = 0.0f; - acc3 = 0.0f; - acc4 = 0.0f; - acc5 = 0.0f; - acc6 = 0.0f; - acc7 = 0.0f; - - /* Initialize state pointer */ - px = pState; - - /* Initialize coeff pointer */ - pb = (pCoeffs); - - /* This is separated from the others to avoid - * a call to __aeabi_memmove which would be slower - */ - *pStateCurnt++ = *pSrc++; - *pStateCurnt++ = *pSrc++; - *pStateCurnt++ = *pSrc++; - *pStateCurnt++ = *pSrc++; - - /* Read the first seven samples from the state buffer: x[n-numTaps], x[n-numTaps-1], x[n-numTaps-2] */ - x0 = *px++; - x1 = *px++; - x2 = *px++; - x3 = *px++; - x4 = *px++; - x5 = *px++; - x6 = *px++; - - /* Loop unrolling. Process 8 taps at a time. */ - tapCnt = numTaps >> 3u; - - /* Loop over the number of taps. Unroll by a factor of 8. - ** Repeat until we've computed numTaps-8 coefficients. */ - while(tapCnt > 0u) - { - /* Read the b[numTaps-1] coefficient */ - c0 = *(pb++); - - /* Read x[n-numTaps-3] sample */ - x7 = *(px++); - - /* acc0 += b[numTaps-1] * x[n-numTaps] */ - p0 = x0 * c0; - - /* acc1 += b[numTaps-1] * x[n-numTaps-1] */ - p1 = x1 * c0; - - /* acc2 += b[numTaps-1] * x[n-numTaps-2] */ - p2 = x2 * c0; - - /* acc3 += b[numTaps-1] * x[n-numTaps-3] */ - p3 = x3 * c0; - - /* acc4 += b[numTaps-1] * x[n-numTaps-4] */ - p4 = x4 * c0; - - /* acc1 += b[numTaps-1] * x[n-numTaps-5] */ - p5 = x5 * c0; - - /* acc2 += b[numTaps-1] * x[n-numTaps-6] */ - p6 = x6 * c0; - - /* acc3 += b[numTaps-1] * x[n-numTaps-7] */ - p7 = x7 * c0; - - /* Read the b[numTaps-2] coefficient */ - c0 = *(pb++); - - /* Read x[n-numTaps-4] sample */ - x0 = *(px++); - - acc0 += p0; - acc1 += p1; - acc2 += p2; - acc3 += p3; - acc4 += p4; - acc5 += p5; - acc6 += p6; - acc7 += p7; - - - /* Perform the multiply-accumulate */ - p0 = x1 * c0; - p1 = x2 * c0; - p2 = x3 * c0; - p3 = x4 * c0; - p4 = x5 * c0; - p5 = x6 * c0; - p6 = x7 * c0; - p7 = x0 * c0; - - /* Read the b[numTaps-3] coefficient */ - c0 = *(pb++); - - /* Read x[n-numTaps-5] sample */ - x1 = *(px++); - - acc0 += p0; - acc1 += p1; - acc2 += p2; - acc3 += p3; - acc4 += p4; - acc5 += p5; - acc6 += p6; - acc7 += p7; - - /* Perform the multiply-accumulates */ - p0 = x2 * c0; - p1 = x3 * c0; - p2 = x4 * c0; - p3 = x5 * c0; - p4 = x6 * c0; - p5 = x7 * c0; - p6 = x0 * c0; - p7 = x1 * c0; - - /* Read the b[numTaps-4] coefficient */ - c0 = *(pb++); - - /* Read x[n-numTaps-6] sample */ - x2 = *(px++); - - acc0 += p0; - acc1 += p1; - acc2 += p2; - acc3 += p3; - acc4 += p4; - acc5 += p5; - acc6 += p6; - acc7 += p7; - - /* Perform the multiply-accumulates */ - p0 = x3 * c0; - p1 = x4 * c0; - p2 = x5 * c0; - p3 = x6 * c0; - p4 = x7 * c0; - p5 = x0 * c0; - p6 = x1 * c0; - p7 = x2 * c0; - - /* Read the b[numTaps-4] coefficient */ - c0 = *(pb++); - - /* Read x[n-numTaps-6] sample */ - x3 = *(px++); - - acc0 += p0; - acc1 += p1; - acc2 += p2; - acc3 += p3; - acc4 += p4; - acc5 += p5; - acc6 += p6; - acc7 += p7; - - /* Perform the multiply-accumulates */ - p0 = x4 * c0; - p1 = x5 * c0; - p2 = x6 * c0; - p3 = x7 * c0; - p4 = x0 * c0; - p5 = x1 * c0; - p6 = x2 * c0; - p7 = x3 * c0; - - /* Read the b[numTaps-4] coefficient */ - c0 = *(pb++); - - /* Read x[n-numTaps-6] sample */ - x4 = *(px++); - - acc0 += p0; - acc1 += p1; - acc2 += p2; - acc3 += p3; - acc4 += p4; - acc5 += p5; - acc6 += p6; - acc7 += p7; - - /* Perform the multiply-accumulates */ - p0 = x5 * c0; - p1 = x6 * c0; - p2 = x7 * c0; - p3 = x0 * c0; - p4 = x1 * c0; - p5 = x2 * c0; - p6 = x3 * c0; - p7 = x4 * c0; - - /* Read the b[numTaps-4] coefficient */ - c0 = *(pb++); - - /* Read x[n-numTaps-6] sample */ - x5 = *(px++); - - acc0 += p0; - acc1 += p1; - acc2 += p2; - acc3 += p3; - acc4 += p4; - acc5 += p5; - acc6 += p6; - acc7 += p7; - - /* Perform the multiply-accumulates */ - p0 = x6 * c0; - p1 = x7 * c0; - p2 = x0 * c0; - p3 = x1 * c0; - p4 = x2 * c0; - p5 = x3 * c0; - p6 = x4 * c0; - p7 = x5 * c0; - - /* Read the b[numTaps-4] coefficient */ - c0 = *(pb++); - - /* Read x[n-numTaps-6] sample */ - x6 = *(px++); - - acc0 += p0; - acc1 += p1; - acc2 += p2; - acc3 += p3; - acc4 += p4; - acc5 += p5; - acc6 += p6; - acc7 += p7; - - /* Perform the multiply-accumulates */ - p0 = x7 * c0; - p1 = x0 * c0; - p2 = x1 * c0; - p3 = x2 * c0; - p4 = x3 * c0; - p5 = x4 * c0; - p6 = x5 * c0; - p7 = x6 * c0; - - tapCnt--; - - acc0 += p0; - acc1 += p1; - acc2 += p2; - acc3 += p3; - acc4 += p4; - acc5 += p5; - acc6 += p6; - acc7 += p7; - } - - /* If the filter length is not a multiple of 8, compute the remaining filter taps */ - tapCnt = numTaps % 0x8u; - - while(tapCnt > 0u) - { - /* Read coefficients */ - c0 = *(pb++); - - /* Fetch 1 state variable */ - x7 = *(px++); - - /* Perform the multiply-accumulates */ - p0 = x0 * c0; - p1 = x1 * c0; - p2 = x2 * c0; - p3 = x3 * c0; - p4 = x4 * c0; - p5 = x5 * c0; - p6 = x6 * c0; - p7 = x7 * c0; - - /* Reuse the present sample states for next sample */ - x0 = x1; - x1 = x2; - x2 = x3; - x3 = x4; - x4 = x5; - x5 = x6; - x6 = x7; - - acc0 += p0; - acc1 += p1; - acc2 += p2; - acc3 += p3; - acc4 += p4; - acc5 += p5; - acc6 += p6; - acc7 += p7; - - /* Decrement the loop counter */ - tapCnt--; - } - - /* Advance the state pointer by 8 to process the next group of 8 samples */ - pState = pState + 8; - - /* The results in the 8 accumulators, store in the destination buffer. */ - *pDst++ = acc0; - *pDst++ = acc1; - *pDst++ = acc2; - *pDst++ = acc3; - *pDst++ = acc4; - *pDst++ = acc5; - *pDst++ = acc6; - *pDst++ = acc7; - - blkCnt--; - } - - /* If the blockSize is not a multiple of 8, compute any remaining output samples here. - ** No loop unrolling is used. */ - blkCnt = blockSize % 0x8u; - - while(blkCnt > 0u) - { - /* Copy one sample at a time into state buffer */ - *pStateCurnt++ = *pSrc++; - - /* Set the accumulator to zero */ - acc0 = 0.0f; - - /* Initialize state pointer */ - px = pState; - - /* Initialize Coefficient pointer */ - pb = (pCoeffs); - - i = numTaps; - - /* Perform the multiply-accumulates */ - do - { - acc0 += *px++ * *pb++; - i--; - - } while(i > 0u); - - /* The result is store in the destination buffer. */ - *pDst++ = acc0; - - /* Advance state pointer by 1 for the next sample */ - pState = pState + 1; - - blkCnt--; - } - - /* Processing is complete. - ** Now copy the last numTaps - 1 samples to the start of the state buffer. - ** This prepares the state buffer for the next function call. */ - - /* Points to the start of the state buffer */ - pStateCurnt = S->pState; - - tapCnt = (numTaps - 1u) >> 2u; - - /* copy data */ - while(tapCnt > 0u) - { - *pStateCurnt++ = *pState++; - *pStateCurnt++ = *pState++; - *pStateCurnt++ = *pState++; - *pStateCurnt++ = *pState++; - - /* Decrement the loop counter */ - tapCnt--; - } - - /* Calculate remaining number of copies */ - tapCnt = (numTaps - 1u) % 0x4u; - - /* Copy the remaining q31_t data */ - while(tapCnt > 0u) - { - *pStateCurnt++ = *pState++; - - /* Decrement the loop counter */ - tapCnt--; - } -} diff --git a/gui/templates/5_fir_differentiator.cpp b/gui/templates/5_fir_differentiator.cpp deleted file mode 100644 index a3a7d4f..0000000 --- a/gui/templates/5_fir_differentiator.cpp +++ /dev/null @@ -1,30 +0,0 @@ -/** - * 5_fir_differentiator.cpp - * Written by Clyne Sullivan. - * - * Does an FIR differentiation on the incoming signal, so that the output is representative of the - * rate of change of the input. - * A scaling factor is applied so that the output's form is more clearly visible. - */ - -adcsample_t *process_data(adcsample_t *samples, unsigned int size) -{ - constexpr int scaling_factor = 4; - static adcsample_t output[SIZE]; - static adcsample_t prev = 2048; - - // Compute the first output value using the saved sample. - output[0] = 2048 + ((samples[0] - prev) * scaling_factor); - - for (unsigned int i = 1; i < size; i++) { - // Take the rate of change and scale it. - // 2048 is added as the output should be centered in the voltage range. - output[i] = 2048 + ((samples[i] - samples[i - 1]) * scaling_factor); - } - - // Save the last sample for the next iteration. - prev = samples[size - 1]; - - return output; -} - diff --git a/gui/templates/6_iir_test.cpp b/gui/templates/6_iir_test.cpp deleted file mode 100644 index cdb4ab3..0000000 --- a/gui/templates/6_iir_test.cpp +++ /dev/null @@ -1,13 +0,0 @@ -adcsample_t *process_data(adcsample_t *samples, unsigned int size) -{ - constexpr float alpha = 0.7; - - static adcsample_t prev = 2048; - - samples[0] = (1 - alpha) * samples[0] + alpha * prev; - for (unsigned int i = 1; i < size; i++) - samples[i] = (1 - alpha) * samples[i] + alpha * samples[i - 1]; - prev = samples[size - 1]; - - return samples; -} diff --git a/gui/templates/7_iir_echo.cpp b/gui/templates/7_iir_echo.cpp deleted file mode 100644 index 8e93b35..0000000 --- a/gui/templates/7_iir_echo.cpp +++ /dev/null @@ -1,22 +0,0 @@ -adcsample_t *process_data(adcsample_t *samples, unsigned int size) -{ - constexpr float alpha = 0.75; - constexpr unsigned int D = 100; - - static adcsample_t output[SIZE]; - static adcsample_t prev[D]; // prev[0] = output[0 - D] - - // Do calculations with previous output - for (unsigned int i = 0; i < D; i++) - output[i] = samples[i] + alpha * (prev[i] - 2048); - - // Do calculations with current samples - for (unsigned int i = D; i < size; i++) - output[i] = samples[i] + alpha * (output[i - D] - 2048); - - // Save outputs for next computation - for (unsigned int i = 0; i < D; i++) - prev[i] = output[size - (D - i)]; - - return output; -} diff --git a/gui/wav.hpp b/gui/wav.hpp deleted file mode 100644 index a87efb1..0000000 --- a/gui/wav.hpp +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef WAV_HPP_ -#define WAV_HPP_ - -#include -#include -#include - -namespace wav -{ - struct header { - char riff[4]; // "RIFF" - uint32_t filesize; // Total file size minus eight bytes - char wave[4]; // "WAVE" - - bool valid() const { - return strncmp(riff, "RIFF", 4) == 0 && filesize > 8 && strncmp(wave, "WAVE", 4) == 0; - } - } __attribute__ ((packed)); - - struct format { - char fmt_[4]; // "fmt " - uint32_t size; - uint16_t type; - uint16_t channelcount; - uint32_t samplerate; - uint32_t byterate; - uint16_t unused; - uint16_t bps; - - bool valid() const { - return strncmp(fmt_, "fmt ", 4) == 0; - } - } __attribute__ ((packed)); - - struct data { - char data[4]; // "data" - uint32_t size; - - bool valid() const { - return strncmp(data, "data", 4) == 0; - } - } __attribute__ ((packed)); - - class clip { - public: - clip(const char *path) { - std::ifstream file (path); - if (!file.good()) - return; - { - header h; - file.read(reinterpret_cast(&h), sizeof(header)); - if (!h.valid()) - return; - } - { - format f; - file.read(reinterpret_cast(&f), sizeof(format)); - if (!f.valid() || f.type != 1) // ensure PCM - return; - } - { - wav::data d; - file.read(reinterpret_cast(&d), sizeof(wav::data)); - if (!d.valid()) - return; - m_data = new char[d.size + 4096 - (d.size % 4096)]; - m_size = d.size; - file.read(m_data, d.size); - } - } - - bool valid() const { - return m_data != nullptr && m_size > 0; - } - auto data() const { - return m_data; - } - auto next(unsigned int chunksize = 3000) { - if (m_pos == m_size) { - m_pos = 0; - } - auto ret = m_data + m_pos; - m_pos = std::min(m_pos + chunksize, m_size); - return ret; - } - private: - char *m_data = nullptr; - uint32_t m_size = 0; - uint32_t m_pos = 0; - }; -} - -#endif // WAV_HPP_ - diff --git a/gui/wxapp.hpp b/gui/wxapp.hpp deleted file mode 100644 index ef6a68c..0000000 --- a/gui/wxapp.hpp +++ /dev/null @@ -1,37 +0,0 @@ -/** - * @file wxapp.hpp - * @brief Main application object for the stmdsp gui. - * - * Copyright (C) 2021 Clyne Sullivan - * - * Distributed under the GNU GPL v3 or later. You should have received a copy of - * the GNU General Public License along with this program. - * If not, see . - */ - -#ifndef WXAPP_HPP_ -#define WXAPP_HPP_ - -#include "wxmain.hpp" - -#include -#include - -class MainApp : public wxApp -{ -public: - virtual bool OnInit() final { - //wxFont::AddPrivateFont("./Hack-Regular.ttf"); - - m_main_frame = new MainFrame; - m_main_frame->Show(true); - SetTopWindow(m_main_frame); - return true; - } - -private: - MainFrame *m_main_frame = nullptr; -}; - -#endif // WXAPP_HPP_ - diff --git a/gui/wxmain.cpp b/gui/wxmain.cpp deleted file mode 100644 index c526157..0000000 --- a/gui/wxmain.cpp +++ /dev/null @@ -1,476 +0,0 @@ -/** - * @file wxmain.cpp - * @brief Main window definition. - * - * Copyright (C) 2021 Clyne Sullivan - * - * Distributed under the GNU GPL v3 or later. You should have received a copy of - * the GNU General Public License along with this program. - * If not, see . - */ - -#include "wxmain.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#ifndef STMDSP_WIN32 -#include -#include -#endif - -#include "wxmain_devdata.h" - -enum Id { - TimerPerformance = 1, - TimerRecord, - TimerWavClip, - - MFileNew, - MFileOpen, - MFileOpenTemplate, - MFileSave, - MFileSaveAs, - MFileQuit, - MRunConnect, - MRunStart, - MRunMeasure, - MRunDrawSamples, - MRunLogResults, - MRunUpload, - MRunUnload, - MRunEditBSize, - MRunGenUpload, - MRunGenStart, - MCodeCompile, - MCodeDisassemble, - CompileOutput -}; - -MainFrame::MainFrame() : - wxFrame(nullptr, wxID_ANY, "stmdspgui", wxDefaultPosition, wxSize(640, 800)) -{ - // Main frame structure: - // Begin with a main splitter for the code and terminal panes - auto mainSplitter = new wxSplitterWindow(this, wxID_ANY); - auto panelCode = new wxPanel(mainSplitter, wxID_ANY); - auto panelOutput = new wxPanel(mainSplitter, wxID_ANY); - // Additional panel for the toolbar - auto panelToolbar = new wxPanel(panelCode, wxID_ANY); - // Sizers for the controls - auto sizerToolbar = new wxBoxSizer(wxHORIZONTAL); - auto sizerCode = new wxBoxSizer(wxVERTICAL); - auto sizerOutput = new wxBoxSizer(wxVERTICAL); - auto sizerMain = new wxBoxSizer(wxVERTICAL); - // Menu objects - auto menuFile = new wxMenu; - auto menuRun = new wxMenu; - auto menuCode = new wxMenu; - - // Member initialization - m_status_bar = new wxStatusBar(this); - m_text_editor = new wxStyledTextCtrl(panelCode, wxID_ANY, - wxDefaultPosition, wxSize(620, 440)); - m_compile_output = new wxTextCtrl(panelOutput, Id::CompileOutput, - wxEmptyString, - wxDefaultPosition, wxSize(620, 250), - wxTE_READONLY | wxTE_MULTILINE | wxHSCROLL | wxTE_RICH2); - m_timer_performance = new wxTimer(this, Id::TimerPerformance); - m_timer_record = new wxTimer(this, Id::TimerRecord); - m_timer_wavclip = new wxTimer(this, Id::TimerWavClip); - m_menu_bar = new wxMenuBar; - m_rate_select = new wxComboBox(panelToolbar, wxID_ANY, - wxEmptyString, - wxDefaultPosition, wxDefaultSize, - srateValues.size(), srateValues.data(), - wxCB_READONLY); -#ifndef STMDSP_WIN32 - m_device_samples = reinterpret_cast(::mmap( - nullptr, stmdsp::SAMPLES_MAX * sizeof(stmdsp::adcsample_t), - PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0)); - m_device_samples_input = reinterpret_cast(::mmap( - nullptr, stmdsp::SAMPLES_MAX * sizeof(stmdsp::adcsample_t), - PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0)); -#else - m_device_samples = new stmdsp::adcsample_t[stmdsp::SAMPLES_MAX]; - m_device_samples_input = new stmdsp::adcsample_t[stmdsp::SAMPLES_MAX]; -#endif - - m_menu_bar->Append(menuFile, "&File"); - m_menu_bar->Append(menuRun, "&Run"); - m_menu_bar->Append(menuCode, "&Code"); - SetMenuBar(m_menu_bar); - - // Toolbar initialization - auto comp = new wxButton(panelToolbar, wxID_ANY, "Compile"); - sizerToolbar->Add(comp, 0, wxLEFT | wxTOP, 4); - sizerToolbar->Add(m_rate_select, 0, wxLEFT | wxTOP, 4); - panelToolbar->SetSizer(sizerToolbar); - - // Code panel init. - prepareEditor(); - sizerCode->Add(panelToolbar, 0, wxBOTTOM, 4); - sizerCode->Add(m_text_editor, 1, wxEXPAND, 0); - panelCode->SetSizer(sizerCode); - - // Output panel init. - m_compile_output->SetBackgroundColour(wxColour(0, 0, 0)); - m_compile_output->SetDefaultStyle(wxTextAttr(*wxWHITE, *wxBLACK, wxFont("Hack"))); - sizerOutput->Add(m_compile_output, 1, wxEXPAND | wxALL, 0); - panelOutput->SetSizer(sizerOutput); - - // Main splitter init. - mainSplitter->SetSashGravity(0.5); - mainSplitter->SetMinimumPaneSize(20); - mainSplitter->SplitHorizontally(panelCode, panelOutput, 100); - sizerMain->Add(mainSplitter, 1, wxEXPAND, 5); - sizerMain->SetSizeHints(this); - SetSizer(sizerMain); - - m_status_bar->SetStatusText("Ready."); - SetStatusBar(m_status_bar); - - // Binds: - - // General - Bind(wxEVT_TIMER, &MainFrame::onTimerPerformance, this, Id::TimerPerformance); - Bind(wxEVT_TIMER, &MainFrame::onTimerRecord, this, Id::TimerRecord); - Bind(wxEVT_TIMER, &MainFrame::onTimerWavClip, this, Id::TimerWavClip); - Bind(wxEVT_CLOSE_WINDOW, &MainFrame::onCloseEvent, this, wxID_ANY); -// m_compile_output-> -// Bind(wxEVT_PAINT, &MainFrame::onPaint, this, Id::CompileOutput); - Bind(wxEVT_PAINT, &MainFrame::onPaint, this, wxID_ANY); - - // Toolbar actions - Bind(wxEVT_BUTTON, &MainFrame::onRunCompile, this, wxID_ANY, wxID_ANY, comp); - Bind(wxEVT_COMBOBOX, &MainFrame::onToolbarSampleRate, this, wxID_ANY, wxID_ANY, m_rate_select); - - // File menu actions - Bind(wxEVT_MENU, &MainFrame::onFileNew, this, Id::MFileNew, wxID_ANY, menuFile->Append(MFileNew, "&New")); - Bind(wxEVT_MENU, &MainFrame::onFileOpen, this, Id::MFileOpen, wxID_ANY, menuFile->Append(MFileOpen, "&Open")); - menuFile->Append(MFileOpenTemplate, "Open &Template", loadTemplates()); - Bind(wxEVT_MENU, &MainFrame::onFileSave, this, Id::MFileSave, wxID_ANY, menuFile->Append(MFileSave, "&Save")); - Bind(wxEVT_MENU, &MainFrame::onFileSaveAs, this, Id::MFileSaveAs, wxID_ANY, menuFile->Append(MFileSaveAs, "Save &As")); - menuFile->AppendSeparator(); - Bind(wxEVT_MENU, &MainFrame::onFileQuit, this, Id::MFileQuit, wxID_ANY, menuFile->Append(MFileQuit, "&Quit")); - - // Run menu actions - Bind(wxEVT_MENU, &MainFrame::onRunConnect, this, Id::MRunConnect, wxID_ANY, menuRun->Append(MRunConnect, "&Connect")); - menuRun->AppendSeparator(); - Bind(wxEVT_MENU, &MainFrame::onRunStart, this, Id::MRunStart, wxID_ANY, menuRun->Append(MRunStart, "&Start")); - m_run_measure = menuRun->AppendCheckItem(MRunMeasure, "&Measure code time"); - m_run_draw_samples = menuRun->AppendCheckItem(MRunDrawSamples, "&Draw samples"); - Bind(wxEVT_MENU, &MainFrame::onRunLogResults, this, Id::MRunLogResults, wxID_ANY, menuRun->AppendCheckItem(MRunLogResults, "&Log results...")); - menuRun->AppendSeparator(); - Bind(wxEVT_MENU, &MainFrame::onRunUpload, this, Id::MRunUpload, wxID_ANY, menuRun->Append(MRunUpload, "&Upload code")); - Bind(wxEVT_MENU, &MainFrame::onRunUnload, this, Id::MRunUnload, wxID_ANY, menuRun->Append(MRunUnload, "U&nload code")); - Bind(wxEVT_MENU, &MainFrame::onRunEditBSize, this, Id::MRunEditBSize, wxID_ANY, menuRun->Append(MRunEditBSize, "Set &buffer size...")); - menuRun->AppendSeparator(); - Bind(wxEVT_MENU, &MainFrame::onRunGenUpload, this, Id::MRunGenUpload, wxID_ANY, menuRun->Append(MRunGenUpload, "&Load signal generator...")); - Bind(wxEVT_MENU, &MainFrame::onRunGenStart, this, Id::MRunGenStart, wxID_ANY, menuRun->AppendCheckItem(MRunGenStart, "Start &generator")); - - // Code menu actions - Bind(wxEVT_MENU, &MainFrame::onRunCompile, this, Id::MCodeCompile, wxID_ANY, menuCode->Append(MCodeCompile, "&Compile code")); - Bind(wxEVT_MENU, &MainFrame::onCodeDisassemble, this, Id::MCodeDisassemble, wxID_ANY, menuCode->Append(MCodeDisassemble, "Show &Disassembly")); - - updateMenuOptions(); -} - -// Closes the window -// Needs to clean things up -void MainFrame::onCloseEvent(wxCloseEvent& event) -{ - SetMenuBar(nullptr); - //delete m_menu_bar->Remove(2); - //delete m_menu_bar->Remove(1); - //delete m_menu_bar->Remove(0); - //delete m_menu_bar; - delete m_timer_performance; - delete m_timer_record; - delete m_timer_wavclip; - delete m_device; - - Unbind(wxEVT_COMBOBOX, &MainFrame::onToolbarSampleRate, this, wxID_ANY, wxID_ANY); - Unbind(wxEVT_BUTTON, &MainFrame::onRunCompile, this, wxID_ANY, wxID_ANY); - - event.Skip(); -} - -void MainFrame::onTimerPerformance(wxTimerEvent&) -{ - // Show execution time - m_status_bar->SetStatusText(wxString::Format(wxT("Execution time: %u cycles"), - m_device->continuous_start_get_measurement())); -} - -void MainFrame::onTimerRecord(wxTimerEvent&) -{ - auto samples = m_device->continuous_read(); - if (samples.size() > 0) { - std::copy(samples.cbegin(), samples.cend(), m_device_samples); - - if (m_conv_result_log) { - for (auto& s : samples) { - auto str = std::to_string(s) + ','; - m_conv_result_log->Write(str.c_str(), str.size()); - } - m_conv_result_log->Write("\n", 1); - } - - if (m_run_draw_samples->IsChecked()) { - samples = m_device->continuous_read_input(); - std::copy(samples.cbegin(), samples.cend(), m_device_samples_input); - /*m_compile_output->*/Refresh(); - } - } -} - -void MainFrame::onTimerWavClip(wxTimerEvent&) -{ - // Stream out next WAV chunk - auto size = m_device->get_buffer_size(); - auto chunk = new stmdsp::adcsample_t[size]; - auto src = reinterpret_cast(m_wav_clip->next(size)); - for (unsigned int i = 0; i < size; i++) - chunk[i] = ((uint32_t)*src++) / 16 + 2048; - m_device->siggen_upload(chunk, size); - delete[] chunk; -} - -void MainFrame::onPaint(wxPaintEvent&) -{ - if (!m_is_running || !m_run_draw_samples->IsChecked()) { - if (!m_compile_output->IsShown()) - m_compile_output->Show(); - return; - } else if (m_compile_output->IsShown()) { - m_compile_output->Hide(); - } - - auto py = m_compile_output->GetScreenPosition().y - this->GetScreenPosition().y - 28; - wxRect rect { - 0, py, - this->GetSize().GetWidth(), - this->GetSize().GetHeight() - py - 60 - }; - - auto *dc = new wxBufferedPaintDC(this); - dc->SetBrush(*wxBLACK_BRUSH); - dc->SetPen(*wxBLACK_PEN); - dc->DrawRectangle(rect); - auto stoy = [&](stmdsp::adcsample_t s) { - return static_cast(py) + rect.GetHeight() - - (static_cast(rect.GetHeight()) * s / 4095.f); - }; - auto scount = m_device->get_buffer_size(); - float dx = static_cast(rect.GetWidth()) / scount; - float x = 0; - float lasty = stoy(2048); - dc->SetBrush(wxBrush(wxColour(0xFF, 0, 0, 0x80))); - dc->SetPen(wxPen(wxColour(0xFF, 0, 0, 0x80))); - for (decltype(scount) i = 0; i < scount; i++) { - auto y = stoy(m_device_samples[i]); - dc->DrawLine(x, lasty, x + dx, y); - x += dx, lasty = y; - } - x = 0; - lasty = stoy(2048); - dc->SetBrush(wxBrush(wxColour(0, 0, 0xFF, 0x80))); - dc->SetPen(wxPen(wxColour(0, 0, 0xFF, 0x80))); - for (decltype(scount) i = 0; i < scount; i++) { - auto y = stoy(m_device_samples_input[i]); - dc->DrawLine(x, lasty, x + dx, y); - x += dx, lasty = y; - } - delete dc; -} - -void MainFrame::prepareEditor() -{ - m_text_editor->SetLexer(wxSTC_LEX_CPP); - m_text_editor->SetMarginWidth(0, 30); - m_text_editor->SetMarginType(0, wxSTC_MARGIN_NUMBER); - m_text_editor->StyleSetFaceName(wxSTC_STYLE_DEFAULT, "Hack"); - m_text_editor->StyleClearAll(); - m_text_editor->SetTabWidth(4); - m_text_editor->StyleSetForeground(wxSTC_STYLE_LINENUMBER, wxColor(75, 75, 75)); - m_text_editor->StyleSetBackground(wxSTC_STYLE_LINENUMBER, wxColor(220, 220, 220)); - - m_text_editor->StyleSetForeground(wxSTC_C_STRING, wxColour(150,0,0)); - m_text_editor->StyleSetForeground(wxSTC_C_PREPROCESSOR, wxColour(165,105,0)); - m_text_editor->StyleSetForeground(wxSTC_C_IDENTIFIER, wxColour(40,0,60)); - m_text_editor->StyleSetForeground(wxSTC_C_NUMBER, wxColour(0,150,0)); - m_text_editor->StyleSetForeground(wxSTC_C_CHARACTER, wxColour(150,0,0)); - m_text_editor->StyleSetForeground(wxSTC_C_WORD, wxColour(0,0,150)); - m_text_editor->StyleSetForeground(wxSTC_C_WORD2, wxColour(0,150,0)); - m_text_editor->StyleSetForeground(wxSTC_C_COMMENT, wxColour(150,150,150)); - m_text_editor->StyleSetForeground(wxSTC_C_COMMENTLINE, wxColour(150,150,150)); - m_text_editor->StyleSetForeground(wxSTC_C_COMMENTDOC, wxColour(150,150,150)); - m_text_editor->StyleSetForeground(wxSTC_C_COMMENTDOCKEYWORD, wxColour(0,0,200)); - m_text_editor->StyleSetForeground(wxSTC_C_COMMENTDOCKEYWORDERROR, wxColour(0,0,200)); - m_text_editor->StyleSetBold(wxSTC_C_WORD, true); - m_text_editor->StyleSetBold(wxSTC_C_WORD2, true); - m_text_editor->StyleSetBold(wxSTC_C_COMMENTDOCKEYWORD, true); - - // a sample list of keywords, I haven't included them all to keep it short... - m_text_editor->SetKeyWords(0, - wxT("return for while do break continue if else goto asm")); - m_text_editor->SetKeyWords(1, - wxT("void char short int long auto float double unsigned signed " - "volatile static const constexpr constinit consteval " - "virtual final noexcept public private protected")); - wxCommandEvent dummy; - onFileNew(dummy); -} - -wxString MainFrame::compileEditorCode() -{ - stmdsp::platform platform; - if (m_device != nullptr) { - platform = m_device->get_platform(); - } else { - m_status_bar->SetStatusText("Assuming L4 platform..."); - platform = stmdsp::platform::L4; - } - - if (m_temp_file_name.IsEmpty()) - m_temp_file_name = wxFileName::CreateTempFileName("stmdspgui"); - - wxFile file (m_temp_file_name, wxFile::write); - wxString file_text (platform == stmdsp::platform::L4 ? file_header_l4 - : file_header_h7); - file_text.Replace("$0", std::to_string(m_device ? m_device->get_buffer_size() - : stmdsp::SAMPLES_MAX)); - file.Write(wxString(file_text) + m_text_editor->GetText()); - file.Close(); - - constexpr const char *script_ext = -#ifndef STMDSP_WIN32 - ".sh"; -#else - ".bat"; -#endif - - wxFile makefile (m_temp_file_name + script_ext, wxFile::write); - wxString make_text (platform == stmdsp::platform::L4 ? makefile_text_l4 - : makefile_text_h7); - make_text.Replace("$0", m_temp_file_name); - char cwd[PATH_MAX]; - make_text.Replace("$1", getcwd(cwd, sizeof(cwd))); - makefile.Write(make_text); - makefile.Close(); - - wxString make_output = m_temp_file_name + script_ext + ".log"; - wxString make_command = m_temp_file_name + script_ext + " > " + - make_output + " 2>&1"; - -#ifndef STMDSP_WIN32 - system(wxString("chmod +x ") + m_temp_file_name + script_ext); -#endif - int result = system(make_command.ToAscii()); - wxFile result_file (make_output); - wxString result_text; - result_file.ReadAll(&result_text); - result_file.Close(); - m_compile_output->Clear(); - m_compile_output->WriteText(result_text); - - wxRemoveFile(m_temp_file_name); - wxRemoveFile(m_temp_file_name + script_ext); - wxRemoveFile(make_output); - - if (result == 0) { - m_status_bar->SetStatusText("Compilation succeeded."); - return m_temp_file_name + ".o"; - } else { - m_status_bar->SetStatusText("Compilation failed."); - return ""; - } -} - -void MainFrame::onToolbarSampleRate(wxCommandEvent& ce) -{ - auto combo = dynamic_cast(ce.GetEventUserData()); - m_device->set_sample_rate(combo->GetCurrentSelection()); - m_status_bar->SetStatusText("Ready."); -} - -void MainFrame::onCodeDisassemble(wxCommandEvent&) -{ - auto output = m_temp_file_name + ".asm.log"; - if (!m_temp_file_name.IsEmpty()) { - wxString command = wxString("arm-none-eabi-objdump -d --no-show-raw-insn ") + - m_temp_file_name + ".orig.o" // + - " > " + output + " 2>&1"; - - if (system(command.ToAscii()) == 0) { - wxFile result_file (output); - wxString result_text; - result_file.ReadAll(&result_text); - result_file.Close(); - m_compile_output->Clear(); - m_compile_output->WriteText(result_text); - wxRemoveFile(output); - m_status_bar->SetStatusText(wxString::Format(wxT("Done. Line count: %u."), - m_compile_output->GetNumberOfLines())); - } else { - m_status_bar->SetStatusText("Failed to load disassembly."); - } - } else { - m_status_bar->SetStatusText("Need to compile code before analyzing."); - } -} - -wxMenu *MainFrame::loadTemplates() -{ - wxMenu *menu = new wxMenu; - - wxArrayString files; - if (wxDir::GetAllFiles(wxGetCwd() + "/templates", &files, "*.cpp", wxDIR_FILES) > 0) { - files.Sort(); - int id = 1000; - for (auto file : files) { - Bind(wxEVT_MENU, &MainFrame::onFileOpenTemplate, this, id, wxID_ANY, - menu->Append(id, file.AfterLast('/'))); - id++; - } - } - - return menu; -} - -void MainFrame::updateMenuOptions() -{ - bool connected = m_device != nullptr; - m_menu_bar->Enable(MRunStart, connected); - m_menu_bar->Enable(MRunGenUpload, connected); - m_menu_bar->Enable(MRunGenStart, connected); - - m_menu_bar->Enable(MRunConnect, !m_is_running); - - bool nrunning = connected && !m_is_running; - m_menu_bar->Enable(MRunUpload, nrunning); - m_menu_bar->Enable(MRunUnload, nrunning); - m_menu_bar->Enable(MRunEditBSize, nrunning); - m_menu_bar->Enable(MRunMeasure, nrunning); - m_menu_bar->Enable(MRunDrawSamples, nrunning); - m_menu_bar->Enable(MRunLogResults, nrunning); - m_menu_bar->Enable(MRunGenUpload, nrunning); - m_rate_select->Enable(nrunning); -} - diff --git a/gui/wxmain.hpp b/gui/wxmain.hpp deleted file mode 100644 index 11131eb..0000000 --- a/gui/wxmain.hpp +++ /dev/null @@ -1,111 +0,0 @@ -/** - * @file wxmain.hpp - * @brief Main window definition. - * - * Copyright (C) 2021 Clyne Sullivan - * - * Distributed under the GNU GPL v3 or later. You should have received a copy of - * the GNU General Public License along with this program. - * If not, see . - */ - -#ifndef WXMAIN_HPP_ -#define WXMAIN_HPP_ - -#include "stmdsp.hpp" -#include "wav.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class MainFrame : public wxFrame -{ -public: - MainFrame(); - - void onCloseEvent(wxCloseEvent&); - - void onFileNew(wxCommandEvent&); - void onFileOpen(wxCommandEvent&); - void onFileOpenTemplate(wxCommandEvent&); - void onFileSave(wxCommandEvent&); - void onFileSaveAs(wxCommandEvent&); - void onFileQuit(wxCommandEvent&); - - void onRunConnect(wxCommandEvent&); - void onRunStart(wxCommandEvent&); - void onRunLogResults(wxCommandEvent&); - void onRunUpload(wxCommandEvent&); - void onRunUnload(wxCommandEvent&); - void onRunEditBSize(wxCommandEvent&); - void onRunGenUpload(wxCommandEvent&); - void onRunGenStart(wxCommandEvent&); - - void onToolbarSampleRate(wxCommandEvent&); - - void onRunCompile(wxCommandEvent&); - void onCodeDisassemble(wxCommandEvent&); - - void onPaint(wxPaintEvent&); - void onTimerPerformance(wxTimerEvent&); - void onTimerRecord(wxTimerEvent&); - void onTimerWavClip(wxTimerEvent&); - -private: - // Set to true if connected and running - bool m_is_running = false; - - wxComboBox *m_device_combo = nullptr; - wxStyledTextCtrl *m_text_editor = nullptr; - wxTextCtrl *m_compile_output = nullptr; - wxControl *m_signal_area = nullptr; - wxMenuItem *m_run_measure = nullptr; - wxMenuItem *m_run_draw_samples = nullptr; - wxTimer *m_timer_performance = nullptr; - wxTimer *m_timer_record = nullptr; - wxTimer *m_timer_wavclip = nullptr; - wxStatusBar *m_status_bar = nullptr; - wxMenuBar *m_menu_bar = nullptr; - wxComboBox *m_rate_select = nullptr; - - // File handle for logging output samples - // Not null when logging is enabled - wxFileOutputStream *m_conv_result_log = nullptr; - // File path of currently opened file - // Empty if new file - wxString m_open_file_path; - // File path for temporary files (e.g. compiled ELF) - // Set by compile action - wxString m_temp_file_name; - - // Device interface - // Not null if connected - stmdsp::device *m_device = nullptr; - stmdsp::adcsample_t *m_device_samples = nullptr; - stmdsp::adcsample_t *m_device_samples_input = nullptr; - // WAV data for signal generator - // Not null when a WAV is loaded - wav::clip *m_wav_clip = nullptr; - - bool tryDevice(); - void prepareEditor(); - wxString compileEditorCode(); - wxMenu *loadTemplates(); - // Updates control availabilities based on device connection - void updateMenuOptions(); -}; - -#endif // WXMAIN_HPP_ - diff --git a/gui/wxmain_devdata.cpp b/gui/wxmain_devdata.cpp deleted file mode 100644 index 7f736a2..0000000 --- a/gui/wxmain_devdata.cpp +++ /dev/null @@ -1,198 +0,0 @@ -#include "wxmain_devdata.h" - -const std::array srateValues { - "8 kS/s", - "16 kS/s", - "20 kS/s", - "32 kS/s", - "48 kS/s", - "96 kS/s" -}; -const std::array srateNums { - 8000, - 16000, - 20000, - 32000, - 48000, - 96000 -}; - -#ifdef STMDSP_WIN32 -#define NEWLINE "\r\n" -#define COPY "copy" -#else -#define NEWLINE "\n" -#define COPY "cp" -#endif - -// $0 = temp file name -// TODO try -ffunction-sections -fdata-sections -Wl,--gc-sections -const char *makefile_text_h7 = -#ifdef STMDSP_WIN32 - "echo off" NEWLINE -#endif - "arm-none-eabi-g++ -x c++ -Os -std=c++20 -fno-exceptions -fno-rtti " - "-mcpu=cortex-m7 -mthumb -mfloat-abi=hard -mfpu=fpv5-d16 -mtune=cortex-m7 " - "-nostartfiles " - "-Wl,-Ttext-segment=0x00000000 -Wl,-zmax-page-size=512 -Wl,-eprocess_data_entry " - "$0 -o $0.o" NEWLINE - COPY " $0.o $0.orig.o" NEWLINE - "arm-none-eabi-strip -s -S --strip-unneeded $0.o" NEWLINE - "arm-none-eabi-objcopy --remove-section .ARM.attributes " - "--remove-section .comment " - "--remove-section .noinit " - "$0.o" NEWLINE - "arm-none-eabi-size $0.o" NEWLINE; -const char *makefile_text_l4 = -#ifdef STMDSP_WIN32 - "echo off" NEWLINE -#endif - "arm-none-eabi-g++ -x c++ -Os -std=c++20 -fno-exceptions -fno-rtti " - "-mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mtune=cortex-m4 " - "-nostartfiles -I$1/cmsis " - "-Wl,-Ttext-segment=0x10000000 -Wl,-zmax-page-size=512 -Wl,-eprocess_data_entry " - "$0 -o $0.o" NEWLINE - COPY " $0.o $0.orig.o" NEWLINE - "arm-none-eabi-strip -s -S --strip-unneeded $0.o" NEWLINE - "arm-none-eabi-objcopy --remove-section .ARM.attributes " - "--remove-section .comment " - "--remove-section .noinit " - "$0.o" NEWLINE - "arm-none-eabi-size $0.o" NEWLINE; - -// $0 = buffer size -const char *file_header_h7 = R"cpp( -#include -#include - -using Sample = uint16_t; -using Samples = std::span; - -Sample *process_data(Samples samples); -extern "C" void process_data_entry() -{ - Sample *samples; - asm("mov %0, r0" : "=r" (samples)); - process_data(Samples(samples, $0)); -} - -constexpr double PI = 3.14159265358979323846L; -__attribute__((naked)) -auto sin(double x) { -asm("vmov.f64 r1, r2, d0;" - "eor r0, r0;" - "svc 1;" - "vmov.f64 d0, r1, r2;" - "bx lr"); -return 0; -} -__attribute__((naked)) -auto cos(double x) { -asm("vmov.f64 r1, r2, d0;" - "mov r0, #1;" - "svc 1;" - "vmov.f64 d0, r1, r2;" - "bx lr"); -return 0; -} -__attribute__((naked)) -auto tan(double x) { -asm("vmov.f64 r1, r2, d0;" - "mov r0, #2;" - "svc 1;" - "vmov.f64 d0, r1, r2;" - "bx lr"); -return 0; -} -__attribute__((naked)) -auto sqrt(double x) { -asm("vsqrt.f64 d0, d0; bx lr"); -return 0; -} - -auto readalt() { -Sample s; -asm("svc 3; mov %0, r0" : "=&r"(s)); -return s; -} - -// End stmdspgui header code - -)cpp"; -const char *file_header_l4 = R"cpp( -#include -#include - -using Sample = uint16_t; -using Samples = std::span; - -Sample *process_data(Samples samples); -extern "C" void process_data_entry() -{ - Sample *samples; - asm("mov %0, r0" : "=r" (samples)); - process_data(Samples(samples, $0)); -} - -constexpr float PI = 3.14159265358979L; -__attribute__((naked)) -auto sin(float x) { -asm("vmov.f32 r1, s0;" - "eor r0, r0;" - "svc 1;" - "vmov.f32 s0, r1;" - "bx lr"); -return 0; -} -__attribute__((naked)) -auto cos(float x) { -asm("vmov.f32 r1, s0;" - "mov r0, #1;" - "svc 1;" - "vmov.f32 s0, r1;" - "bx lr"); -return 0; -} -__attribute__((naked)) -auto tan(float x) { -asm("vmov.f32 r1, s0;" - "mov r0, #2;" - "svc 1;" - "vmov.f32 s0, r1;" - "bx lr"); -return 0; -} -__attribute__((naked)) -auto sqrt(float) { -asm("vsqrt.f32 s0, s0; bx lr"); -return 0; -} - -auto readpot1() { -Sample s; -asm("push {r4-r6}; eor r0, r0; svc 3; mov %0, r0; pop {r4-r6}" : "=&r"(s)); -return s; -} -auto readpot2() { -Sample s; -asm("push {r4-r6}; mov r0, #1; svc 3; mov %0, r0; pop {r4-r6}" : "=&r"(s)); -return s; -} - -void puts(const char *s) { -// 's' will already be in r0. -asm("push {r4-r6}; svc 4; pop {r4-r6}"); -} - -// End stmdspgui header code - -)cpp"; - - -const char *file_content = -R"cpp(Sample *process_data(Samples samples) -{ - return samples.data(); -} -)cpp"; - diff --git a/gui/wxmain_devdata.h b/gui/wxmain_devdata.h deleted file mode 100644 index 898c756..0000000 --- a/gui/wxmain_devdata.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef WXMAIN_DEVDATA_H_ -#define WXMAIN_DEVDATA_H_ - -#include -#include - -extern const std::array srateValues; -extern const std::array srateNums; -extern const char *makefile_text_h7; -extern const char *makefile_text_l4; -extern const char *file_header_h7; -extern const char *file_header_l4; -extern const char *file_content; - -#endif // WXMAIN_DEVDATA_H_ - diff --git a/gui/wxmain_mfile.cpp b/gui/wxmain_mfile.cpp deleted file mode 100644 index 78b97f8..0000000 --- a/gui/wxmain_mfile.cpp +++ /dev/null @@ -1,113 +0,0 @@ -#include "wxmain.hpp" -#include "wxmain_devdata.h" - -#include - -void MainFrame::onFileNew(wxCommandEvent&) -{ - m_open_file_path = ""; - m_text_editor->SetText(file_content); - m_text_editor->DiscardEdits(); - m_status_bar->SetStatusText("Ready."); -} - -void MainFrame::onFileOpen(wxCommandEvent&) -{ - wxFileDialog openDialog(this, "Open filter file", "", "", - "C++ source file (*.cpp)|*.cpp", - wxFD_OPEN | wxFD_FILE_MUST_EXIST); - - if (openDialog.ShowModal() != wxID_CANCEL) { - if (wxFileInputStream file_stream (openDialog.GetPath()); file_stream.IsOk()) { - auto size = file_stream.GetSize(); - auto buffer = new char[size + 1]; - buffer[size] = '\0'; - if (file_stream.ReadAll(buffer, size)) { - m_open_file_path = openDialog.GetPath(); - m_text_editor->SetText(buffer); - m_text_editor->DiscardEdits(); - m_compile_output->ChangeValue(""); - m_status_bar->SetStatusText("Ready."); - } else { - m_status_bar->SetStatusText("Failed to read file contents."); - } - delete[] buffer; - } else { - m_status_bar->SetStatusText("Failed to open file."); - } - } else { - m_status_bar->SetStatusText("Ready."); - } -} - -void MainFrame::onFileOpenTemplate(wxCommandEvent& event) -{ - auto file_path = wxGetCwd() + "/templates/" + m_menu_bar->GetLabel(event.GetId()); - - if (wxFileInputStream file_stream (file_path); file_stream.IsOk()) { - auto size = file_stream.GetSize(); - auto buffer = new char[size + 1]; - buffer[size] = '\0'; - if (file_stream.ReadAll(buffer, size)) { - m_open_file_path = ""; - m_text_editor->SetText(buffer); - //m_text_editor->DiscardEdits(); - m_status_bar->SetStatusText("Ready."); - } else { - m_status_bar->SetStatusText("Failed to read file contents."); - } - delete[] buffer; - } else { - m_status_bar->SetStatusText("Ready."); - } -} - - -void MainFrame::onFileSave(wxCommandEvent& ce) -{ - if (m_text_editor->IsModified()) { - if (m_open_file_path.IsEmpty()) { - onFileSaveAs(ce); - } else { - if (wxFile file (m_open_file_path, wxFile::write); file.IsOpened()) { - file.Write(m_text_editor->GetText()); - file.Close(); - m_text_editor->DiscardEdits(); - m_status_bar->SetStatusText("Saved."); - } else { - m_status_bar->SetStatusText("Save failed: couldn't open file."); - } - } - } else { - m_status_bar->SetStatusText("No modifications to save."); - } -} - -void MainFrame::onFileSaveAs(wxCommandEvent&) -{ - if (m_text_editor->IsModified()) { - wxFileDialog saveDialog(this, "Save filter file", "", "", - "C++ source file (*.cpp)|*.cpp", - wxFD_SAVE | wxFD_OVERWRITE_PROMPT); - - if (saveDialog.ShowModal() != wxID_CANCEL) { - if (wxFile file (saveDialog.GetPath(), wxFile::write); file.IsOpened()) { - file.Write(m_text_editor->GetText()); - file.Close(); - m_text_editor->DiscardEdits(); - m_open_file_path = saveDialog.GetPath(); - m_status_bar->SetStatusText("Saved."); - } else { - m_status_bar->SetStatusText("Save failed: couldn't open file."); - } - } - } else { - m_status_bar->SetStatusText("No modifications to save."); - } -} - -void MainFrame::onFileQuit(wxCommandEvent&) -{ - Close(true); -} - diff --git a/gui/wxmain_mrun.cpp b/gui/wxmain_mrun.cpp deleted file mode 100644 index 9fb307a..0000000 --- a/gui/wxmain_mrun.cpp +++ /dev/null @@ -1,240 +0,0 @@ -#include "wxmain.hpp" -#include "wxmain_devdata.h" -#include "wxsiggen.hpp" - -#include -#include - -void MainFrame::onRunConnect(wxCommandEvent& ce) -{ - auto menuItem = dynamic_cast(ce.GetEventUserData()); - - if (!m_device) { - stmdsp::scanner scanner; - if (auto devices = scanner.scan(); devices.size() > 0) { - m_device = new stmdsp::device(devices.front()); - if (m_device->connected()) { - auto rate = m_device->get_sample_rate(); - m_rate_select->SetSelection(rate); - - updateMenuOptions(); - menuItem->SetItemLabel("&Disconnect"); - m_status_bar->SetStatusText("Connected."); - } else { - delete m_device; - m_device = nullptr; - - menuItem->SetItemLabel("&Connect"); - m_status_bar->SetStatusText("Failed to connect."); - } - } else { - m_status_bar->SetStatusText("No devices found."); - } - } else { - delete m_device; - m_device = nullptr; - updateMenuOptions(); - menuItem->SetItemLabel("&Connect"); - m_status_bar->SetStatusText("Disconnected."); - } -} - -void MainFrame::onRunStart(wxCommandEvent& ce) -{ - auto menuItem = dynamic_cast(ce.GetEventUserData()); - - if (!m_is_running) { - if (m_run_measure->IsChecked()) { - m_device->continuous_start_measure(); - m_timer_performance->StartOnce(1000); - } else { - auto reqSpeedExact = - m_device->get_buffer_size() - / static_cast(srateNums[m_rate_select->GetSelection()]) - * 1000.f * 0.5f; - int reqSpeed = reqSpeedExact; - - if (m_device->is_siggening() && m_wav_clip) { - m_timer_wavclip->Start(reqSpeed); - // Cap refresh speed in case sample drawing runs too. - reqSpeed = std::max(reqSpeed, 500); - } - if (m_conv_result_log || m_run_draw_samples->IsChecked()) - m_timer_record->Start(std::max(reqSpeed, 200)); - - m_device->continuous_start(); - } - - m_rate_select->Enable(false); - menuItem->SetItemLabel("&Stop"); - m_status_bar->SetStatusText("Running."); - m_is_running = true; - } else { - m_device->continuous_stop(); - m_timer_performance->Stop(); - m_timer_record->Stop(); - m_timer_wavclip->Stop(); - - m_rate_select->Enable(true); - menuItem->SetItemLabel("&Start"); - m_status_bar->SetStatusText("Ready."); - m_is_running = false; - - if (m_run_draw_samples->IsChecked()) - m_compile_output->Refresh(); - } - - updateMenuOptions(); -} - -void MainFrame::onRunLogResults(wxCommandEvent& ce) -{ - auto menuItem = dynamic_cast(ce.GetEventUserData()); - if (menuItem->IsChecked()) { - wxFileDialog dialog (this, "Choose log file", "", "", "*.csv", - wxFD_SAVE | wxFD_OVERWRITE_PROMPT); - - if (dialog.ShowModal() != wxID_CANCEL) { - if (m_conv_result_log) { - m_conv_result_log->Close(); - delete m_conv_result_log; - m_conv_result_log = nullptr; - } - - m_conv_result_log = new wxFileOutputStream(dialog.GetPath()); - } - - m_status_bar->SetStatusText("Ready."); - } else if (m_conv_result_log) { - m_conv_result_log->Close(); - delete m_conv_result_log; - m_conv_result_log = nullptr; - } -} - -void MainFrame::onRunEditBSize(wxCommandEvent&) -{ - wxTextEntryDialog dialog (this, "Enter new buffer size (100-4096)", "Set Buffer Size"); - if (dialog.ShowModal() == wxID_OK) { - if (wxString value = dialog.GetValue(); !value.IsEmpty()) { - if (unsigned long n; value.ToULong(&n)) { - if (n >= 100 && n <= stmdsp::SAMPLES_MAX) { - if ((n & 1) == 1) - ++n; - m_device->continuous_set_buffer_size(n); - } else { - m_status_bar->SetStatusText("Error: Invalid buffer size."); - } - } else { - m_status_bar->SetStatusText("Error: Invalid buffer size."); - } - } else { - m_status_bar->SetStatusText("Ready."); - } - } else { - m_status_bar->SetStatusText("Ready."); - } -} - -void MainFrame::onRunGenUpload(wxCommandEvent&) -{ - if (SiggenDialog dialog (this); dialog.ShowModal() == wxID_OK) { - auto result = dialog.Result(); - if (result.Find(".wav") != wxNOT_FOUND) { - // Audio - m_wav_clip = new wav::clip(result/*.Mid(1)*/); - if (m_wav_clip->valid()) { - m_status_bar->SetStatusText("Generator ready."); - } else { - delete m_wav_clip; - m_wav_clip = nullptr; - m_status_bar->SetStatusText("Error: Bad WAV file."); - } - } else if (result.find_first_not_of("0123456789 \t\r\n") == wxString::npos) { - // List - std::vector samples; - while (!result.IsEmpty() && samples.size() <= stmdsp::SAMPLES_MAX * 2) { - if (auto number_end = result.find_first_not_of("0123456789"); - number_end != wxString::npos && number_end > 0) - { - auto number = result.Left(number_end); - if (unsigned long n; number.ToULong(&n)) - samples.push_back(n & 4095); - - if (auto next = result.find_first_of("0123456789", number_end + 1); - next != wxString::npos) - { - result = result.Mid(next); - } else { - break; - } - } else { - break; - } - } - - if (samples.size() <= stmdsp::SAMPLES_MAX * 2) { - // DAC buffer must be of even size - if ((samples.size() & 1) == 1) - samples.push_back(0); - m_device->siggen_upload(&samples[0], samples.size()); - m_status_bar->SetStatusText("Generator ready."); - } else { - m_status_bar->SetStatusText(wxString::Format("Error: Too many samples (max is %u).", - stmdsp::SAMPLES_MAX * 2)); - } - } else { - extern std::vector siggen_formula_parse(const std::string&); - auto samples = siggen_formula_parse(result.ToStdString()); - if (samples.size() > 0) { - m_device->siggen_upload(&samples[0], samples.size()); - m_status_bar->SetStatusText("Generator ready."); - } else { - m_status_bar->SetStatusText("Error: Bad formula."); - } - } - } else { - m_status_bar->SetStatusText("Ready."); - } -} - -void MainFrame::onRunGenStart(wxCommandEvent& ce) -{ - auto menuItem = dynamic_cast(ce.GetEventUserData()); - if (menuItem->IsChecked()) { - m_device->siggen_start(); - menuItem->SetItemLabel("Stop &generator"); - m_status_bar->SetStatusText("Generator running."); - } else { - m_device->siggen_stop(); - menuItem->SetItemLabel("Start &generator"); - m_status_bar->SetStatusText("Ready."); - } -} - -void MainFrame::onRunUpload(wxCommandEvent&) -{ - if (auto file = compileEditorCode(); !file.IsEmpty()) { - if (wxFileInputStream file_stream (file); file_stream.IsOk()) { - auto size = file_stream.GetSize(); - auto buffer = new unsigned char[size]; - file_stream.ReadAll(buffer, size); - m_device->upload_filter(buffer, size); - m_status_bar->SetStatusText("Code uploaded."); - } else { - m_status_bar->SetStatusText("Couldn't load compiled code."); - } - } -} - -void MainFrame::onRunUnload(wxCommandEvent&) -{ - m_device->unload_filter(); - m_status_bar->SetStatusText("Unloaded code."); -} - -void MainFrame::onRunCompile(wxCommandEvent&) -{ - compileEditorCode(); -} - diff --git a/gui/wxmain_mrun_genupload.cpp b/gui/wxmain_mrun_genupload.cpp deleted file mode 100644 index d1b82ef..0000000 --- a/gui/wxmain_mrun_genupload.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include "stmdsp.hpp" -//#include "exprtk.hpp" -#include -#include - -std::vector siggen_formula_parse(const std::string& formulaString) -{ - double x = 0; - - //exprtk::symbol_table symbol_table; - //symbol_table.add_variable("x", x); - //symbol_table.add_constants(); - - //exprtk::expression expression; - //expression.register_symbol_table(symbol_table); - - //exprtk::parser parser; - //parser.compile(formulaString, expression); - - std::vector samples; - for (x = 0; samples.size() < stmdsp::SAMPLES_MAX; x += 1) { - //auto y = static_cast(expression.value()); - samples.push_back(2048); - } - - return samples; -} - diff --git a/gui/wxsiggen.cpp b/gui/wxsiggen.cpp deleted file mode 100644 index 5151fb5..0000000 --- a/gui/wxsiggen.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/** - * @file wxsiggen.cpp - * @brief Dialog prompt for providing signal generator input. - * - * Copyright (C) 2021 Clyne Sullivan - * - * Distributed under the GNU GPL v3 or later. You should have received a copy of - * the GNU General Public License along with this program. - * If not, see . - */ - -#include "wxsiggen.hpp" - -#include -#include -#include - -static const std::array Sources {{ - "List", - "Formula", - "WAV audio" -}}; -static const std::array Instructions {{ - "Enter a list of numbers:", - "Enter a formula. f(x) = ", - wxEmptyString -}}; - -SiggenDialog::SiggenDialog(wxWindow *parent) : - wxDialog(parent, wxID_ANY, "stmdspgui signal generator", wxDefaultPosition, wxSize(300, 200)) -{ - m_instruction = new wxStaticText(this, wxID_ANY, wxEmptyString, wxPoint(10, 70)); - m_source_list = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxPoint(10, 100), wxSize(280, 30)); - m_source_math = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxPoint(10, 100), wxSize(280, 30)); - m_source_file = new wxButton(this, 42, "Choose file...", wxPoint(10, 75), wxSize(280, 50)); - - auto radio = new wxRadioBox(this, wxID_ANY, "Source", wxPoint(10, 10), wxSize(280, 50), - Sources.size(), Sources.data()); - auto save = new wxButton(this, 43, "Save", wxPoint(200, 150)); - - m_instruction->SetLabel(Instructions[0]); - m_source_math->Hide(); - m_source_file->Hide(); - - Bind(wxEVT_RADIOBOX, &SiggenDialog::onSourceChange, this, wxID_ANY, wxID_ANY, radio); - Bind(wxEVT_BUTTON, &SiggenDialog::onSourceFile, this, 42, 42, m_source_file); - Bind(wxEVT_BUTTON, &SiggenDialog::onSave, this, 43, 43, save); -} - -SiggenDialog::~SiggenDialog() -{ - Unbind(wxEVT_BUTTON, &SiggenDialog::onSave, this, 43, 43); - Unbind(wxEVT_BUTTON, &SiggenDialog::onSourceFile, this, 42, 42); - Unbind(wxEVT_RADIOBOX, &SiggenDialog::onSourceChange, this, wxID_ANY, wxID_ANY); -} - -void SiggenDialog::onSourceFile(wxCommandEvent&) -{ - wxFileDialog dialog (this, "Open audio file", "", "", - "Audio file (*.wav)|*.wav", - wxFD_OPEN | wxFD_FILE_MUST_EXIST); - if (dialog.ShowModal() != wxID_CANCEL) - m_result = dialog.GetPath(); -} - -void SiggenDialog::onSave(wxCommandEvent&) -{ - if (m_source_list->IsShown()) - m_result = m_source_list->GetValue(); - else if (m_source_math->IsShown()) - m_result = m_source_math->GetValue(); - - EndModal(!m_result.IsEmpty() ? wxID_OK : wxID_CANCEL); -} - -void SiggenDialog::onSourceChange(wxCommandEvent& ce) -{ - auto radio = dynamic_cast(ce.GetEventObject()); - if (radio == nullptr) - return; - - m_result.Clear(); - if (unsigned int selection = static_cast(radio->GetSelection()); - selection < Sources.size()) - { - m_instruction->SetLabel(Instructions[selection]); - m_source_list->Show(selection == 0); - m_source_math->Show(selection == 1); - m_source_file->Show(selection == 2); - } -} - diff --git a/gui/wxsiggen.hpp b/gui/wxsiggen.hpp deleted file mode 100644 index acf479e..0000000 --- a/gui/wxsiggen.hpp +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @file wxsiggen.hpp - * @brief Dialog prompt for providing signal generator input. - * - * Copyright (C) 2021 Clyne Sullivan - * - * Distributed under the GNU GPL v3 or later. You should have received a copy of - * the GNU General Public License along with this program. - * If not, see . - */ - -#ifndef WXSIGGEN_HPP_ -#define WXSIGGEN_HPP_ - -#include -#include -#include -#include - -class SiggenDialog : public wxDialog { -public: - SiggenDialog(wxWindow *parent); - ~SiggenDialog(); - - auto Result() const { - return m_result; - } - - void onSourceChange(wxCommandEvent&); - void onSourceFile(wxCommandEvent&); - void onSave(wxCommandEvent&); - -private: - wxStaticText *m_instruction = nullptr; - wxTextCtrl *m_source_list = nullptr; - wxTextCtrl *m_source_math = nullptr; - wxButton *m_source_file = nullptr; - wxString m_result; -}; - -#endif // WXSIGGEN_HPP_ - From ff2054f2cb8a780936d95741e1daa7df789fa246 Mon Sep 17 00:00:00 2001 From: Clyne Sullivan Date: Sat, 30 Oct 2021 16:49:20 -0400 Subject: [PATCH 11/13] fix fault handling; fix LEDs for rev2 --- source/board/board_l4.c | 7 +++++-- source/board/l4/board.h | 6 +++--- source/conversion.cpp | 6 +++--- source/conversion.hpp | 2 +- source/handlers.cpp | 2 +- source/monitor.cpp | 25 +++++++++++++------------ 6 files changed, 26 insertions(+), 22 deletions(-) diff --git a/source/board/board_l4.c b/source/board/board_l4.c index 31d1d51..55af697 100644 --- a/source/board/board_l4.c +++ b/source/board/board_l4.c @@ -277,9 +277,12 @@ bool mmc_lld_is_write_protected(MMCDriver *mmcp) { * @note You can add your board-specific code here. */ void boardInit(void) { - palSetLineMode(LINE_LED_GREEN, PAL_MODE_OUTPUT_PUSHPULL); - palSetLineMode(LINE_LED_YELLOW, PAL_MODE_OUTPUT_PUSHPULL); palSetLineMode(LINE_LED_RED, PAL_MODE_OUTPUT_PUSHPULL); + palSetLineMode(LINE_LED_GREEN, PAL_MODE_OUTPUT_PUSHPULL); + palSetLineMode(LINE_LED_BLUE, PAL_MODE_OUTPUT_PUSHPULL); + palClearLine(LINE_LED_RED); + palClearLine(LINE_LED_GREEN); + palClearLine(LINE_LED_BLUE); SCB->CPACR |= 0xF << 20; // Enable FPU diff --git a/source/board/l4/board.h b/source/board/l4/board.h index e4dcf03..4b2642a 100644 --- a/source/board/l4/board.h +++ b/source/board/l4/board.h @@ -1502,8 +1502,8 @@ extern "C" { #endif #endif /* _FROM_ASM_ */ -#define LINE_LED_GREEN PAL_LINE(GPIOC_BASE, 10U) -#define LINE_LED_YELLOW PAL_LINE(GPIOC_BASE, 11U) -#define LINE_LED_RED PAL_LINE(GPIOC_BASE, 12U) +#define LINE_LED_RED PAL_LINE(GPIOC_BASE, 10U) +#define LINE_LED_GREEN PAL_LINE(GPIOC_BASE, 11U) +#define LINE_LED_BLUE PAL_LINE(GPIOC_BASE, 12U) #endif /* BOARD_H */ diff --git a/source/conversion.cpp b/source/conversion.cpp index c9dc0c9..6fdea07 100644 --- a/source/conversion.cpp +++ b/source/conversion.cpp @@ -83,11 +83,11 @@ thread_t *ConversionManager::getMonitorHandle() return m_thread_monitor; } -void ConversionManager::abort() +void ConversionManager::abort(bool fpu_stacked) { ELFManager::unload(); EM.add(Error::ConversionAborted); - run_status = RunStatus::Recovering; + //run_status = RunStatus::Recovering; // Confirm that the exception return thread is the algorithm... uint32_t *psp; @@ -104,7 +104,7 @@ void ConversionManager::abort() // We do this by rebuilding the thread's stacked exception return. auto newpsp = reinterpret_cast(m_thread_runner_stack.data() + m_thread_runner_stack.size() - - 8 * sizeof(uint32_t)); + (fpu_stacked ? 26 : 8) * sizeof(uint32_t)); // Set the LR register to the thread's entry point. newpsp[5] = reinterpret_cast(threadRunner); // Overwrite the instruction we'll return to with "bx lr" (jump to address in LR). diff --git a/source/conversion.hpp b/source/conversion.hpp index 6af4972..a26dd19 100644 --- a/source/conversion.hpp +++ b/source/conversion.hpp @@ -39,7 +39,7 @@ public: static thread_t *getMonitorHandle(); // Internal only: Aborts a running conversion. - static void abort(); + static void abort(bool fpu_stacked = true); private: static void threadMonitor(void *); diff --git a/source/handlers.cpp b/source/handlers.cpp index 2ff948d..43e65c3 100644 --- a/source/handlers.cpp +++ b/source/handlers.cpp @@ -108,7 +108,7 @@ void MemManage_Handler() asm("mov %0, lr" : "=r" (lr)); // 2. Recover from the fault. - ConversionManager::abort(); + ConversionManager::abort((lr & (1 << 4)) ? false : true); // 3. Return. asm("mov lr, %0; bx lr" :: "r" (lr)); diff --git a/source/monitor.cpp b/source/monitor.cpp index 08a62d5..6ef97e9 100644 --- a/source/monitor.cpp +++ b/source/monitor.cpp @@ -39,30 +39,31 @@ void Monitor::threadMonitor(void *) #endif }; - palClearLine(LINE_LED_RED); - palClearLine(LINE_LED_YELLOW); + palSetLine(LINE_LED_RED); + palSetLine(LINE_LED_GREEN); + palSetLine(LINE_LED_BLUE); while (1) { bool isidle = run_status == RunStatus::Idle; - auto led = isidle ? LINE_LED_GREEN : LINE_LED_YELLOW; + auto led = isidle ? LINE_LED_GREEN : LINE_LED_BLUE; auto delay = isidle ? 500 : 250; - palSetLine(led); + palToggleLine(led); chThdSleepMilliseconds(delay); - palClearLine(led); + palToggleLine(led); chThdSleepMilliseconds(delay); - if (run_status == RunStatus::Idle && readButton()) { - palSetLine(LINE_LED_RED); - palSetLine(LINE_LED_YELLOW); + if (isidle && readButton()) { + palClearLine(LINE_LED_GREEN); + palClearLine(LINE_LED_BLUE); chSysLock(); while (readButton()) asm("nop"); while (!readButton()) asm("nop"); chSysUnlock(); - palClearLine(LINE_LED_RED); - palClearLine(LINE_LED_YELLOW); + palSetLine(LINE_LED_GREEN); + palSetLine(LINE_LED_BLUE); chThdSleepMilliseconds(500); } @@ -70,9 +71,9 @@ void Monitor::threadMonitor(void *) if (auto err = EM.hasError(); err ^ erroron) { erroron = err; if (err) - palSetLine(LINE_LED_RED); - else palClearLine(LINE_LED_RED); + else + palSetLine(LINE_LED_RED); } } } From 5944ae4d01eb27af7c86bedba5ee157f51ba78dd Mon Sep 17 00:00:00 2001 From: Clyne Sullivan Date: Sat, 30 Oct 2021 18:59:19 -0400 Subject: [PATCH 12/13] add rev2 hardware files --- doc/addon_rev2_board.pdf | 9079 ++++++++++++++++++++++++++++++++++ doc/addon_rev2_schematic.pdf | 8711 ++++++++++++++++++++++++++++++++ 2 files changed, 17790 insertions(+) create mode 100644 doc/addon_rev2_board.pdf create mode 100644 doc/addon_rev2_schematic.pdf diff --git a/doc/addon_rev2_board.pdf b/doc/addon_rev2_board.pdf new file mode 100644 index 0000000..ba0a727 --- /dev/null +++ b/doc/addon_rev2_board.pdf @@ -0,0 +1,9079 @@ +%PDF-1.4 +%ºß¬à +3 0 obj +<> +endobj +4 0 obj +<< +/Length 138637 +>> +stream +0.14 w +0 G +2 J +0 j +72 M +0.00 g +[] 0 d +0.00 181.37 213.05 -181.37 re +f +1 J +1 j +1.13 w +0.00 0.00 1.00 RG /a0 gs +170.136 89.568 m +146.736 66.168 l +146.736 52.128 l +S +1 J +1 j +1.13 w +0.00 0.00 1.00 RG /a0 gs +66.816 75.168 m +95.616 75.168 l +S +1 J +1 j +1.13 w +0.00 0.00 1.00 RG /a0 gs +92.157 95.328 m +63.933 95.328 l +S +1 J +1 j +1.13 w +0.00 0.00 1.00 RG /a0 gs +58.176 75.168 m +39.053 56.045 l +22.356 56.045 l +S +1 J +1 j +1.13 w +0.00 0.00 1.00 RG /a0 gs +166.176 118.728 m +175.496 128.048 l +188.068 128.048 l +S +1 J +1 j +1.13 w +0.00 0.00 1.00 RG /a0 gs +95.616 75.168 m +116.496 75.168 l +124.056 82.728 l +S +1 J +1 j +1.13 w +0.00 0.00 1.00 RG /a0 gs +178.056 113.328 m +182.016 117.288 l +190.296 117.288 l +193.856 120.848 l +195.268 120.848 l +S +1 J +1 j +1.13 w +0.00 0.00 1.00 RG /a0 gs +127.656 31.968 m +108.936 50.688 l +50.976 50.688 l +S +1 J +1 j +1.13 w +0.00 0.00 1.00 RG /a0 gs +134.856 31.968 m +106.776 60.048 l +93.456 60.048 l +S +1 J +1 j +1.13 w +0.00 0.00 1.00 RG /a0 gs +146.736 52.128 m +146.736 28.728 l +142.776 24.768 l +142.056 24.768 l +S +1 J +1 j +1.13 w +0.00 0.00 1.00 RG /a0 gs +122.256 95.328 m +92.157 95.328 l +S +1 J +1 j +1.13 w +0.00 0.00 1.00 RG /a0 gs +183.456 89.568 m +170.136 89.568 l +S +1 J +1 j +1.13 w +0.00 0.00 1.00 RG /a0 gs +98.022 155.088 m +94.782 151.848 l +32.256 151.848 l +22.853 142.445 l +22.356 142.445 l +S +1 J +1 j +1.13 w +0.00 0.00 1.00 RG /a0 gs +34.416 95.328 m +34.416 145.368 l +S +1 J +1 j +1.13 w +0.00 0.00 1.00 RG /a0 gs +111.456 79.848 m +49.896 79.848 l +34.416 95.328 l +S +1 J +1 j +0.72 w +1.00 0.00 0.00 RG /a0 gs +176.976 76.248 m +176.890 76.334 l +171.490 76.334 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +189.674 76.522 m +177.062 76.522 l +173.016 80.568 l +173.016 125.928 l +179.018 131.930 l +179.018 136.915 l +S +1 J +1 j +0.72 w +1.00 0.00 0.00 RG /a0 gs +142.056 24.768 m +158.976 24.768 l +S +1 J +1 j +0.72 w +1.00 0.00 0.00 RG /a0 gs +165.096 148.608 m +165.096 142.347 l +S +1 J +1 j +0.72 w +1.00 0.00 0.00 RG /a0 gs +144.392 92.808 m +136.296 92.808 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +74.016 79.909 m +74.016 73.947 l +76.035 71.928 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +104.976 72.288 m +102.843 74.421 l +102.843 80.989 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +37.296 71.928 m +37.992 72.624 l +37.992 82.069 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +47.599 138.888 m +67.650 138.888 l +83.850 155.088 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +83.850 155.088 m +83.850 154.974 l +87.336 151.488 l +111.570 151.488 l +115.170 155.088 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +129.343 155.088 m +125.023 159.408 l +102.342 159.408 l +98.022 155.088 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +22.356 113.645 m +47.599 138.888 l +47.578 160.294 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +159.311 152.928 m +157.151 155.088 l +129.343 155.088 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +90.079 42.134 m +90.934 42.134 l +104.976 56.176 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +107.654 42.134 m +104.976 44.813 l +104.976 59.901 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +162.000 129.888 m +148.644 116.568 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +148.536 116.568 m +148.536 116.568 l +61.056 116.568 l +52.776 108.288 l +52.776 101.808 l +48.816 97.848 l +48.816 95.627 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +161.997 129.888 m +161.997 132.408 l +165.096 135.507 l +165.096 136.869 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +167.475 129.888 m +173.421 135.834 l +173.421 139.608 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +172.774 139.608 m +161.496 139.608 l +158.976 142.128 l +158.976 142.128 l +159.109 153.130 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +92.157 95.328 m +92.456 95.627 l +95.502 95.627 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +63.933 95.328 m +64.232 95.627 l +66.816 95.627 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +34.416 95.328 m +34.715 95.627 l +38.016 95.627 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +77.616 79.906 m +81.216 79.848 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +111.456 79.848 m +106.301 79.906 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +70.416 95.630 m +70.416 107.208 l +79.776 116.568 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +99.102 95.627 m +98.856 95.873 l +98.856 113.688 l +101.588 116.420 l +101.588 116.568 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +159.109 153.130 m +159.311 152.928 l +169.776 152.928 l +174.816 147.888 l +174.992 147.888 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +95.616 75.168 m +95.502 75.282 l +95.502 79.909 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +66.816 79.909 m +66.816 75.168 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +111.816 89.904 m +106.302 95.417 l +106.302 95.627 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +99.102 79.909 m +99.216 80.023 l +99.216 83.088 l +101.760 85.632 l +111.816 85.632 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +189.674 87.371 m +187.477 89.568 l +183.456 89.568 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +191.722 70.999 m +198.835 78.084 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +191.724 89.420 m +189.674 87.371 l +189.674 83.892 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +198.838 91.691 m +196.567 89.420 l +191.724 89.420 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +198.838 91.691 m +198.838 68.725 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +188.071 135.252 m +191.628 131.688 l +197.136 131.688 l +202.176 126.648 l +202.176 94.968 l +198.835 91.692 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +165.096 142.344 m +179.021 142.301 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +188.068 135.248 m +183.709 139.608 l +172.774 139.608 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +179.021 142.301 m +178.963 147.888 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +188.068 142.448 m +187.921 142.301 l +179.018 142.301 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +189.674 78.365 m +182.419 78.365 l +178.056 82.728 l +178.056 113.328 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +189.674 80.208 m +183.096 80.208 l +180.216 83.088 l +180.216 120.528 l +184.176 124.488 l +190.656 124.488 l +194.216 128.048 l +195.268 128.048 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +35.460 166.628 m +43.794 166.628 l +47.578 162.844 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +35.472 157.248 m +38.516 160.292 l +42.853 160.292 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +35.460 161.928 m +36.376 162.844 l +42.853 162.844 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +15.156 156.845 m +11.016 160.985 l +11.016 166.248 l +13.176 168.408 l +29.016 168.408 l +30.796 166.628 l +31.190 166.628 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +15.156 164.045 m +18.713 160.488 l +25.776 160.488 l +29.016 157.248 l +31.200 157.248 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +22.356 164.045 m +27.216 164.088 l +29.376 161.928 l +31.190 161.928 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +93.456 60.048 m +93.280 59.872 l +84.816 59.872 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +84.096 85.992 m +83.352 85.248 l +72.936 85.248 l +70.416 82.728 l +70.416 79.909 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +77.616 95.627 m +82.979 90.264 l +84.096 90.264 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +99.357 71.208 m +99.102 71.463 l +99.102 79.909 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +70.557 70.848 m +70.416 70.989 l +70.416 79.909 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +104.976 62.355 m +104.835 62.496 l +104.835 71.208 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +76.176 61.995 m +76.035 62.136 l +76.035 70.848 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +22.356 70.445 m +26.856 74.945 l +26.856 86.688 l +30.456 90.288 l +38.376 90.288 l +41.616 93.528 l +41.616 95.627 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +53.273 24.322 m +57.146 20.448 l +123.336 20.448 l +127.656 24.768 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +90.058 23.962 m +91.411 22.608 l +105.336 22.608 l +106.690 23.962 l +107.633 23.962 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +62.338 23.962 m +63.691 22.608 l +77.616 22.608 l +78.970 23.962 l +79.913 23.962 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +35.698 24.322 m +37.771 22.248 l +51.336 22.248 l +53.273 24.185 l +53.273 24.322 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +90.058 23.962 m +85.154 28.865 l +84.816 28.865 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +35.719 33.422 m +35.719 42.494 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +53.294 33.422 m +53.294 42.494 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +62.359 42.134 m +76.176 55.951 l +76.176 59.541 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +62.359 33.062 m +62.359 42.134 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +76.176 59.541 m +76.507 59.872 l +84.816 59.872 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +79.935 42.134 m +76.176 45.893 l +76.176 59.541 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +79.934 33.062 m +79.934 42.134 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +107.654 33.062 m +107.654 42.134 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +90.079 42.134 m +90.079 33.062 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +112.176 59.872 m +112.147 59.901 l +104.976 59.901 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +134.856 24.768 m +142.056 24.768 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +107.633 23.962 m +112.039 28.368 l +130.896 28.368 l +134.496 24.768 l +134.856 24.768 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +107.633 23.962 m +112.176 28.505 l +112.176 55.904 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +79.913 23.962 m +84.816 28.865 l +84.816 55.904 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +170.136 89.568 m +151.056 89.568 l +148.536 87.048 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +148.536 87.048 m +148.536 84.888 l +147.096 83.448 l +144.567 83.448 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +144.567 86.141 m +131.443 86.141 l +122.256 95.328 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +144.567 80.755 m +152.505 80.755 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +152.505 80.755 m +152.692 80.568 l +173.016 80.568 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +152.505 86.141 m +153.596 87.232 l +160.056 87.232 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +160.056 83.264 m +159.872 83.448 l +152.505 83.448 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +144.567 86.141 m +144.392 86.316 l +144.392 92.808 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +148.360 92.808 m +151.056 90.112 l +151.056 89.568 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +137.736 82.912 m +138.272 83.448 l +144.567 83.448 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +137.736 82.912 m +137.552 82.728 l +124.056 82.728 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +111.456 79.848 m +135.216 79.848 l +136.120 78.944 l +137.736 78.944 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +144.567 80.755 m +142.756 78.944 l +137.736 78.944 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +50.976 50.688 m +45.036 50.753 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +35.719 42.494 m +35.856 42.631 l +35.856 55.149 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +112.176 59.872 m +114.152 59.872 l +142.056 31.968 l +S +1 J +1 j +0.72 w +1.00 0.00 0.00 RG /a0 gs +22.356 34.445 m +18.713 38.088 l +13.176 38.088 l +11.376 39.888 l +11.376 108.288 l +13.176 110.088 l +26.496 110.088 l +49.896 133.488 l +76.536 133.488 l +90.936 147.888 l +S +1 J +1 j +0.72 w +1.00 0.00 0.00 RG /a0 gs +22.356 41.645 m +18.936 45.065 l +18.936 100.728 l +21.096 102.888 l +27.216 102.888 l +52.776 128.448 l +121.896 128.448 l +122.256 128.808 l +122.256 147.888 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +34.416 145.368 m +30.139 149.645 l +22.356 149.645 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +58.176 75.168 m +58.176 79.872 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +58.176 84.144 m +58.512 84.144 l +63.216 88.848 l +71.136 88.848 l +74.016 91.728 l +74.016 95.627 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +35.856 60.627 m +41.592 66.362 l +41.592 69.768 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +41.594 69.768 m +41.616 79.906 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +38.016 79.909 m +37.333 80.592 l +32.256 80.592 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +32.256 84.866 m +34.416 87.048 l +41.976 87.048 l +45.216 90.288 l +45.216 95.630 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +41.616 95.627 m +41.280 95.962 l +41.280 103.248 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +45.216 95.627 m +45.552 95.962 l +45.552 103.248 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +74.016 95.630 m +74.038 102.528 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +77.616 95.627 m +78.312 96.322 l +78.312 102.528 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +102.702 95.627 m +102.702 100.728 l +103.560 101.586 l +103.560 102.528 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +103.560 102.528 m +103.560 109.368 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +107.832 109.368 m +156.816 109.368 l +166.176 118.728 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +106.302 95.627 m +106.302 99.288 l +107.832 100.817 l +107.832 102.528 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +53.294 42.494 m +40.640 55.149 l +35.856 55.149 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +53.273 24.322 m +57.816 28.865 l +57.816 50.688 l +45.216 63.288 l +45.216 80.269 l +S +1 J +1 j +1.13 w +1.00 0.00 0.00 RG /a0 gs +48.816 79.909 m +48.816 88.848 l +55.296 95.328 l +63.216 95.328 l +S +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +169.776 75.168 m +169.789 75.385 l +169.829 75.599 l +169.893 75.807 l +169.982 76.005 l +170.095 76.190 l +170.229 76.362 l +170.382 76.515 l +170.554 76.649 l +170.739 76.762 l +170.937 76.851 l +171.145 76.915 l +171.359 76.955 l +171.576 76.968 l +171.576 76.968 l +171.793 76.955 l +172.007 76.915 l +172.215 76.851 l +172.413 76.762 l +172.598 76.649 l +172.770 76.515 l +172.923 76.362 l +173.057 76.190 l +173.170 76.005 l +173.259 75.807 l +173.323 75.599 l +173.363 75.385 l +173.376 75.168 l +173.376 75.168 l +173.363 74.951 l +173.323 74.737 l +173.259 74.529 l +173.170 74.331 l +173.057 74.146 l +172.923 73.974 l +172.770 73.821 l +172.598 73.687 l +172.413 73.574 l +172.215 73.485 l +172.007 73.421 l +171.793 73.381 l +171.576 73.368 l +171.576 73.368 l +171.359 73.381 l +171.145 73.421 l +170.937 73.485 l +170.739 73.574 l +170.554 73.687 l +170.382 73.821 l +170.229 73.974 l +170.095 74.146 l +169.982 74.331 l +169.893 74.529 l +169.829 74.737 l +169.789 74.951 l +169.776 75.168 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +134.496 92.808 m +134.509 93.025 l +134.549 93.239 l +134.613 93.447 l +134.702 93.645 l +134.815 93.830 l +134.949 94.002 l +135.102 94.155 l +135.274 94.289 l +135.459 94.402 l +135.657 94.491 l +135.865 94.555 l +136.079 94.595 l +136.296 94.608 l +136.296 94.608 l +136.513 94.595 l +136.727 94.555 l +136.935 94.491 l +137.133 94.402 l +137.318 94.289 l +137.490 94.155 l +137.643 94.002 l +137.777 93.830 l +137.890 93.645 l +137.979 93.447 l +138.043 93.239 l +138.083 93.025 l +138.096 92.808 l +138.096 92.808 l +138.083 92.591 l +138.043 92.377 l +137.979 92.169 l +137.890 91.971 l +137.777 91.786 l +137.643 91.614 l +137.490 91.461 l +137.318 91.327 l +137.133 91.214 l +136.935 91.125 l +136.727 91.061 l +136.513 91.021 l +136.296 91.008 l +136.296 91.008 l +136.079 91.021 l +135.865 91.061 l +135.657 91.125 l +135.459 91.214 l +135.274 91.327 l +135.102 91.461 l +134.949 91.614 l +134.815 91.786 l +134.702 91.971 l +134.613 92.169 l +134.549 92.377 l +134.509 92.591 l +134.496 92.808 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +163.296 148.608 m +163.309 148.825 l +163.349 149.039 l +163.413 149.247 l +163.502 149.445 l +163.615 149.630 l +163.749 149.802 l +163.902 149.955 l +164.074 150.089 l +164.259 150.202 l +164.457 150.291 l +164.665 150.355 l +164.879 150.395 l +165.096 150.408 l +165.096 150.408 l +165.313 150.395 l +165.527 150.355 l +165.735 150.291 l +165.933 150.202 l +166.118 150.089 l +166.290 149.955 l +166.443 149.802 l +166.577 149.630 l +166.690 149.445 l +166.779 149.247 l +166.843 149.039 l +166.883 148.825 l +166.896 148.608 l +166.896 148.608 l +166.883 148.391 l +166.843 148.177 l +166.779 147.969 l +166.690 147.771 l +166.577 147.586 l +166.443 147.414 l +166.290 147.261 l +166.118 147.127 l +165.933 147.014 l +165.735 146.925 l +165.527 146.861 l +165.313 146.821 l +165.096 146.808 l +165.096 146.808 l +164.879 146.821 l +164.665 146.861 l +164.457 146.925 l +164.259 147.014 l +164.074 147.127 l +163.902 147.261 l +163.749 147.414 l +163.615 147.586 l +163.502 147.771 l +163.413 147.969 l +163.349 148.177 l +163.309 148.391 l +163.296 148.608 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +157.176 24.768 m +157.189 24.985 l +157.229 25.199 l +157.293 25.407 l +157.382 25.605 l +157.495 25.790 l +157.629 25.962 l +157.782 26.115 l +157.954 26.249 l +158.139 26.362 l +158.337 26.451 l +158.545 26.515 l +158.759 26.555 l +158.976 26.568 l +158.976 26.568 l +159.193 26.555 l +159.407 26.515 l +159.615 26.451 l +159.813 26.362 l +159.998 26.249 l +160.170 26.115 l +160.323 25.962 l +160.457 25.790 l +160.570 25.605 l +160.659 25.407 l +160.723 25.199 l +160.763 24.985 l +160.776 24.768 l +160.776 24.768 l +160.763 24.551 l +160.723 24.337 l +160.659 24.129 l +160.570 23.931 l +160.457 23.746 l +160.323 23.574 l +160.170 23.421 l +159.998 23.287 l +159.813 23.174 l +159.615 23.085 l +159.407 23.021 l +159.193 22.981 l +158.976 22.968 l +158.976 22.968 l +158.759 22.981 l +158.545 23.021 l +158.337 23.085 l +158.139 23.174 l +157.954 23.287 l +157.782 23.421 l +157.629 23.574 l +157.495 23.746 l +157.382 23.931 l +157.293 24.129 l +157.229 24.337 l +157.189 24.551 l +157.176 24.768 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +38.464 73.513 m +38.464 71.063 l +36.178 71.063 l +36.178 73.513 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +40.448 73.513 m +40.448 71.063 l +42.734 71.063 l +42.734 73.513 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +33.481 83.720 m +31.031 83.720 l +31.031 86.006 l +33.481 86.006 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +33.481 81.736 m +31.031 81.736 l +31.031 79.450 l +33.481 79.450 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +42.424 104.473 m +42.424 102.023 l +40.138 102.023 l +40.138 104.473 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +44.408 104.473 m +44.408 102.023 l +46.694 102.023 l +46.694 104.473 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +59.401 83.000 m +56.951 83.000 l +56.951 85.286 l +59.401 85.286 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +59.401 81.016 m +56.951 81.016 l +56.951 78.730 l +59.401 78.730 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +77.168 101.303 m +77.168 103.753 l +79.454 103.753 l +79.454 101.303 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +75.184 101.303 m +75.184 103.753 l +72.898 103.753 l +72.898 101.303 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +82.871 87.136 m +85.321 87.136 l +85.321 84.850 l +82.871 84.850 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +82.871 89.120 m +85.321 89.120 l +85.321 91.406 l +82.871 91.406 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +104.704 110.593 m +104.704 108.143 l +102.418 108.143 l +102.418 110.593 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +106.688 110.593 m +106.688 108.143 l +108.974 108.143 l +108.974 110.593 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +106.688 101.303 m +106.688 103.753 l +108.974 103.753 l +108.974 101.303 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +104.704 101.303 m +104.704 103.753 l +102.418 103.753 l +102.418 101.303 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +110.591 86.776 m +113.041 86.776 l +113.041 84.490 l +110.591 84.490 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +110.591 88.760 m +113.041 88.760 l +113.041 91.046 l +110.591 91.046 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +178.240 137.766 m +181.273 137.766 l +181.273 136.065 l +178.240 136.065 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +178.240 143.151 m +181.273 143.151 l +181.273 141.450 l +178.240 141.450 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +171.239 140.458 m +174.272 140.458 l +174.272 138.758 l +171.239 138.758 l + h +f +1 J +1 j +1 J +1.67 w +1.00 0.00 0.00 RG /a0 gs +[] 0 d +38.016 82.334 m +38.016 78.204 l +S +1 J +1 j +1 J +1.67 w +1.00 0.00 0.00 RG /a0 gs +[] 0 d +41.616 82.334 m +41.616 78.204 l +S +1 J +1 j +1 J +1.67 w +1.00 0.00 0.00 RG /a0 gs +[] 0 d +45.216 82.334 m +45.216 78.204 l +S +1 J +1 j +1 J +1.67 w +1.00 0.00 0.00 RG /a0 gs +[] 0 d +48.816 82.334 m +48.816 78.204 l +S +1 J +1 j +1 J +1.67 w +1.00 0.00 0.00 RG /a0 gs +[] 0 d +38.016 98.052 m +38.016 93.922 l +S +1 J +1 j +1 J +1.67 w +1.00 0.00 0.00 RG /a0 gs +[] 0 d +41.616 98.052 m +41.616 93.922 l +S +1 J +1 j +1 J +1.67 w +1.00 0.00 0.00 RG /a0 gs +[] 0 d +45.216 98.052 m +45.216 93.922 l +S +1 J +1 j +1 J +1.67 w +1.00 0.00 0.00 RG /a0 gs +[] 0 d +48.816 98.052 m +48.816 93.922 l +S +1 J +1 j +1 J +1.67 w +1.00 0.00 0.00 RG /a0 gs +[] 0 d +77.616 93.562 m +77.616 97.692 l +S +1 J +1 j +1 J +1.67 w +1.00 0.00 0.00 RG /a0 gs +[] 0 d +74.016 93.562 m +74.016 97.692 l +S +1 J +1 j +1 J +1.67 w +1.00 0.00 0.00 RG /a0 gs +[] 0 d +70.416 93.562 m +70.416 97.692 l +S +1 J +1 j +1 J +1.67 w +1.00 0.00 0.00 RG /a0 gs +[] 0 d +66.816 93.562 m +66.816 97.692 l +S +1 J +1 j +1 J +1.67 w +1.00 0.00 0.00 RG /a0 gs +[] 0 d +77.616 77.844 m +77.616 81.974 l +S +1 J +1 j +1 J +1.67 w +1.00 0.00 0.00 RG /a0 gs +[] 0 d +74.016 77.844 m +74.016 81.974 l +S +1 J +1 j +1 J +1.67 w +1.00 0.00 0.00 RG /a0 gs +[] 0 d +70.416 77.844 m +70.416 81.974 l +S +1 J +1 j +1 J +1.67 w +1.00 0.00 0.00 RG /a0 gs +[] 0 d +66.816 77.844 m +66.816 81.974 l +S +1 J +1 j +1 J +1.67 w +1.00 0.00 0.00 RG /a0 gs +[] 0 d +106.416 93.922 m +106.416 98.052 l +S +1 J +1 j +1 J +1.67 w +1.00 0.00 0.00 RG /a0 gs +[] 0 d +102.816 93.922 m +102.816 98.052 l +S +1 J +1 j +1 J +1.67 w +1.00 0.00 0.00 RG /a0 gs +[] 0 d +99.216 93.922 m +99.216 98.052 l +S +1 J +1 j +1 J +1.67 w +1.00 0.00 0.00 RG /a0 gs +[] 0 d +95.616 93.922 m +95.616 98.052 l +S +1 J +1 j +1 J +1.67 w +1.00 0.00 0.00 RG /a0 gs +[] 0 d +106.416 78.204 m +106.416 82.334 l +S +1 J +1 j +1 J +1.67 w +1.00 0.00 0.00 RG /a0 gs +[] 0 d +102.816 78.204 m +102.816 82.334 l +S +1 J +1 j +1 J +1.67 w +1.00 0.00 0.00 RG /a0 gs +[] 0 d +99.216 78.204 m +99.216 82.334 l +S +1 J +1 j +1 J +1.67 w +1.00 0.00 0.00 RG /a0 gs +[] 0 d +95.616 78.204 m +95.616 82.334 l +S +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +163.602 131.840 m +163.602 127.936 l +160.392 127.936 l +160.392 131.840 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +165.870 131.840 m +165.870 127.936 l +169.080 127.936 l +169.080 131.840 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +161.332 84.398 m +161.332 82.130 l +158.780 82.130 l +158.780 84.398 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +161.332 88.366 m +161.332 86.098 l +158.780 86.098 l +158.780 88.366 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +136.460 81.778 m +136.460 84.046 l +139.012 84.046 l +139.012 81.778 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +136.460 77.810 m +136.460 80.078 l +139.012 80.078 l +139.012 77.810 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +147.226 94.084 m +149.494 94.084 l +149.494 91.532 l +147.226 91.532 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +143.258 94.084 m +145.526 94.084 l +145.526 91.532 l +143.258 91.532 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +145.985 79.975 m +143.150 79.975 l +143.150 81.535 l +145.985 81.535 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +145.985 82.668 m +143.150 82.668 l +143.150 84.227 l +145.985 84.227 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +145.985 85.361 m +143.150 85.361 l +143.150 86.920 l +145.985 86.920 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +153.922 85.361 m +151.087 85.361 l +151.087 86.920 l +153.922 86.920 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +153.922 82.668 m +151.087 82.668 l +151.087 84.227 l +153.922 84.227 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +153.922 79.975 m +151.087 79.975 l +151.087 81.535 l +153.922 81.535 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +163.144 138.474 m +167.048 138.474 l +167.048 135.264 l +163.144 135.264 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +163.144 140.742 m +167.048 140.742 l +167.048 143.952 l +163.144 143.952 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +34.328 156.023 m +34.328 158.473 l +36.614 158.473 l +36.614 156.023 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +32.344 156.023 m +32.344 158.473 l +30.058 158.473 l +30.058 156.023 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +34.317 160.703 m +34.317 163.153 l +36.603 163.153 l +36.603 160.703 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +32.333 160.703 m +32.333 163.153 l +30.046 163.153 l +30.046 160.703 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +34.317 165.403 m +34.317 167.852 l +36.603 167.852 l +36.603 165.403 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +32.333 165.403 m +32.333 167.852 l +30.046 167.852 l +30.046 165.403 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +37.808 59.022 m +33.904 59.022 l +33.904 62.232 l +37.808 62.232 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +37.808 56.754 m +33.904 56.754 l +33.904 53.544 l +37.808 53.544 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +74.430 69.976 m +74.430 73.880 l +77.640 73.880 l +77.640 69.976 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +72.162 69.976 m +72.162 73.880 l +68.952 73.880 l +68.952 69.976 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +75.411 60.343 m +76.941 60.343 l +76.941 58.739 l +75.411 58.739 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +75.411 61.193 m +76.941 61.193 l +76.941 62.797 l +75.411 62.797 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +103.230 70.336 m +103.230 74.240 l +106.440 74.240 l +106.440 70.336 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +100.962 70.336 m +100.962 74.240 l +97.752 74.240 l +97.752 70.336 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +104.211 60.703 m +105.741 60.703 l +105.741 59.099 l +104.211 59.099 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +104.211 61.553 m +105.741 61.553 l +105.741 63.157 l +104.211 63.157 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +176.126 146.612 m +173.858 146.612 l +173.858 149.164 l +176.126 149.164 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +180.094 146.612 m +177.826 146.612 l +177.826 149.164 l +180.094 149.164 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +86.092 57.038 m +86.092 54.770 l +83.540 54.770 l +83.540 57.038 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +86.092 61.006 m +86.092 58.738 l +83.540 58.738 l +83.540 61.006 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +113.452 57.038 m +113.452 54.770 l +110.900 54.770 l +110.900 57.038 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +113.452 61.006 m +113.452 58.738 l +110.900 58.738 l +110.900 61.006 l + h +f +1 J +1 j +1 J +1.43 w +1.00 0.00 0.00 RG /a0 gs +[] 0 d +46.993 160.292 m +48.164 160.292 l +S +1 J +1 j +1 J +1.43 w +1.00 0.00 0.00 RG /a0 gs +[] 0 d +46.993 162.844 m +48.164 162.844 l +S +1 J +1 j +1 J +1.43 w +1.00 0.00 0.00 RG /a0 gs +[] 0 d +42.268 162.844 m +43.438 162.844 l +S +1 J +1 j +1 J +1.43 w +1.00 0.00 0.00 RG /a0 gs +[] 0 d +42.268 160.292 m +43.438 160.292 l +S +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +37.824 22.550 m +33.571 22.550 l +33.571 26.094 l +37.824 26.094 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +37.845 40.722 m +33.593 40.722 l +33.593 44.266 l +37.845 44.266 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +37.845 31.650 m +33.593 31.650 l +33.593 35.194 l +37.845 35.194 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +55.399 22.550 m +51.147 22.550 l +51.147 26.094 l +55.399 26.094 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +55.421 40.722 m +51.168 40.722 l +51.168 44.266 l +55.421 44.266 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +55.421 31.650 m +51.168 31.650 l +51.168 35.194 l +55.421 35.194 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +64.464 22.190 m +60.211 22.190 l +60.211 25.734 l +64.464 25.734 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +64.485 40.362 m +60.233 40.362 l +60.233 43.906 l +64.485 43.906 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +64.485 31.290 m +60.233 31.290 l +60.233 34.834 l +64.485 34.834 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +82.039 22.190 m +77.787 22.190 l +77.787 25.734 l +82.039 25.734 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +82.061 40.362 m +77.808 40.362 l +77.808 43.906 l +82.061 43.906 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +82.061 31.290 m +77.808 31.290 l +77.808 34.834 l +82.061 34.834 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +92.184 22.190 m +87.931 22.190 l +87.931 25.734 l +92.184 25.734 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +92.205 40.362 m +87.953 40.362 l +87.953 43.906 l +92.205 43.906 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +92.205 31.290 m +87.953 31.290 l +87.953 34.834 l +92.205 34.834 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +109.759 22.190 m +105.507 22.190 l +105.507 25.734 l +109.759 25.734 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +109.781 40.362 m +105.528 40.362 l +105.528 43.906 l +109.781 43.906 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +109.781 31.290 m +105.528 31.290 l +105.528 34.834 l +109.781 34.834 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +187.406 77.089 m +191.942 77.089 l +191.942 75.955 l +187.406 75.955 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +187.406 78.932 m +191.942 78.932 l +191.942 77.798 l +187.406 77.798 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +187.406 80.775 m +191.942 80.775 l +191.942 79.641 l +187.406 79.641 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +187.406 82.617 m +191.942 82.617 l +191.942 81.483 l +187.406 81.483 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +187.406 84.459 m +191.942 84.459 l +191.942 83.326 l +187.406 83.326 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +190.023 87.436 m +190.023 91.404 l +193.424 91.404 l +193.424 87.436 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +190.023 69.011 m +190.023 72.980 l +193.424 72.980 l +193.424 69.011 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +200.964 66.740 m +196.712 66.740 l +196.712 70.709 l +200.964 70.709 l + h +f +2 J +0 j +72 M +1.00 0.00 0.00 rg /a0 gs +[] 0 d +200.964 89.707 m +196.712 89.707 l +196.712 93.675 l +200.964 93.675 l + h +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +17.71 99.24 m 17.71 100.65 16.56 101.80 15.16 101.80 c +13.75 101.80 12.60 100.65 12.60 99.24 c +12.60 97.84 13.75 96.69 15.16 96.69 c +16.56 96.69 17.71 97.84 17.71 99.24 c +f +0.13 g +[] 0 d +16.57 99.24 m 16.57 100.03 15.94 100.66 15.16 100.66 c +14.37 100.66 13.74 100.03 13.74 99.24 c +13.74 98.46 14.37 97.83 15.16 97.83 c +15.94 97.83 16.57 98.46 16.57 99.24 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +24.91 99.24 m 24.91 100.65 23.76 101.80 22.36 101.80 c +20.95 101.80 19.80 100.65 19.80 99.24 c +19.80 97.84 20.95 96.69 22.36 96.69 c +23.76 96.69 24.91 97.84 24.91 99.24 c +f +0.13 g +[] 0 d +23.77 99.24 m 23.77 100.03 23.14 100.66 22.36 100.66 c +21.57 100.66 20.94 100.03 20.94 99.24 c +20.94 98.46 21.57 97.83 22.36 97.83 c +23.14 97.83 23.77 98.46 23.77 99.24 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +17.71 106.44 m 17.71 107.85 16.56 109.00 15.16 109.00 c +13.75 109.00 12.60 107.85 12.60 106.44 c +12.60 105.04 13.75 103.89 15.16 103.89 c +16.56 103.89 17.71 105.04 17.71 106.44 c +f +0.13 g +[] 0 d +16.57 106.44 m 16.57 107.23 15.94 107.86 15.16 107.86 c +14.37 107.86 13.74 107.23 13.74 106.44 c +13.74 105.66 14.37 105.03 15.16 105.03 c +15.94 105.03 16.57 105.66 16.57 106.44 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +24.91 106.44 m 24.91 107.85 23.76 109.00 22.36 109.00 c +20.95 109.00 19.80 107.85 19.80 106.44 c +19.80 105.04 20.95 103.89 22.36 103.89 c +23.76 103.89 24.91 105.04 24.91 106.44 c +f +0.13 g +[] 0 d +23.77 106.44 m 23.77 107.23 23.14 107.86 22.36 107.86 c +21.57 107.86 20.94 107.23 20.94 106.44 c +20.94 105.66 21.57 105.03 22.36 105.03 c +23.14 105.03 23.77 105.66 23.77 106.44 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +17.71 113.64 m 17.71 115.05 16.56 116.20 15.16 116.20 c +13.75 116.20 12.60 115.05 12.60 113.64 c +12.60 112.24 13.75 111.09 15.16 111.09 c +16.56 111.09 17.71 112.24 17.71 113.64 c +f +0.13 g +[] 0 d +16.57 113.64 m 16.57 114.43 15.94 115.06 15.16 115.06 c +14.37 115.06 13.74 114.43 13.74 113.64 c +13.74 112.86 14.37 112.23 15.16 112.23 c +15.94 112.23 16.57 112.86 16.57 113.64 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +24.91 113.64 m 24.91 115.05 23.76 116.20 22.36 116.20 c +20.95 116.20 19.80 115.05 19.80 113.64 c +19.80 112.24 20.95 111.09 22.36 111.09 c +23.76 111.09 24.91 112.24 24.91 113.64 c +f +0.13 g +[] 0 d +23.77 113.64 m 23.77 114.43 23.14 115.06 22.36 115.06 c +21.57 115.06 20.94 114.43 20.94 113.64 c +20.94 112.86 21.57 112.23 22.36 112.23 c +23.14 112.23 23.77 112.86 23.77 113.64 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +17.71 120.84 m 17.71 122.25 16.56 123.40 15.16 123.40 c +13.75 123.40 12.60 122.25 12.60 120.84 c +12.60 119.44 13.75 118.29 15.16 118.29 c +16.56 118.29 17.71 119.44 17.71 120.84 c +f +0.13 g +[] 0 d +16.57 120.84 m 16.57 121.63 15.94 122.26 15.16 122.26 c +14.37 122.26 13.74 121.63 13.74 120.84 c +13.74 120.06 14.37 119.43 15.16 119.43 c +15.94 119.43 16.57 120.06 16.57 120.84 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +24.91 120.84 m 24.91 122.25 23.76 123.40 22.36 123.40 c +20.95 123.40 19.80 122.25 19.80 120.84 c +19.80 119.44 20.95 118.29 22.36 118.29 c +23.76 118.29 24.91 119.44 24.91 120.84 c +f +0.13 g +[] 0 d +23.77 120.84 m 23.77 121.63 23.14 122.26 22.36 122.26 c +21.57 122.26 20.94 121.63 20.94 120.84 c +20.94 120.06 21.57 119.43 22.36 119.43 c +23.14 119.43 23.77 120.06 23.77 120.84 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +17.71 128.04 m 17.71 129.45 16.56 130.60 15.16 130.60 c +13.75 130.60 12.60 129.45 12.60 128.04 c +12.60 126.64 13.75 125.49 15.16 125.49 c +16.56 125.49 17.71 126.64 17.71 128.04 c +f +0.13 g +[] 0 d +16.57 128.04 m 16.57 128.83 15.94 129.46 15.16 129.46 c +14.37 129.46 13.74 128.83 13.74 128.04 c +13.74 127.26 14.37 126.63 15.16 126.63 c +15.94 126.63 16.57 127.26 16.57 128.04 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +24.91 128.04 m 24.91 129.45 23.76 130.60 22.36 130.60 c +20.95 130.60 19.80 129.45 19.80 128.04 c +19.80 126.64 20.95 125.49 22.36 125.49 c +23.76 125.49 24.91 126.64 24.91 128.04 c +f +0.13 g +[] 0 d +23.77 128.04 m 23.77 128.83 23.14 129.46 22.36 129.46 c +21.57 129.46 20.94 128.83 20.94 128.04 c +20.94 127.26 21.57 126.63 22.36 126.63 c +23.14 126.63 23.77 127.26 23.77 128.04 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +17.71 135.24 m 17.71 136.65 16.56 137.80 15.16 137.80 c +13.75 137.80 12.60 136.65 12.60 135.24 c +12.60 133.84 13.75 132.69 15.16 132.69 c +16.56 132.69 17.71 133.84 17.71 135.24 c +f +0.13 g +[] 0 d +16.57 135.24 m 16.57 136.03 15.94 136.66 15.16 136.66 c +14.37 136.66 13.74 136.03 13.74 135.24 c +13.74 134.46 14.37 133.83 15.16 133.83 c +15.94 133.83 16.57 134.46 16.57 135.24 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +24.91 135.24 m 24.91 136.65 23.76 137.80 22.36 137.80 c +20.95 137.80 19.80 136.65 19.80 135.24 c +19.80 133.84 20.95 132.69 22.36 132.69 c +23.76 132.69 24.91 133.84 24.91 135.24 c +f +0.13 g +[] 0 d +23.77 135.24 m 23.77 136.03 23.14 136.66 22.36 136.66 c +21.57 136.66 20.94 136.03 20.94 135.24 c +20.94 134.46 21.57 133.83 22.36 133.83 c +23.14 133.83 23.77 134.46 23.77 135.24 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +17.71 142.44 m 17.71 143.85 16.56 145.00 15.16 145.00 c +13.75 145.00 12.60 143.85 12.60 142.44 c +12.60 141.04 13.75 139.89 15.16 139.89 c +16.56 139.89 17.71 141.04 17.71 142.44 c +f +0.13 g +[] 0 d +16.57 142.44 m 16.57 143.23 15.94 143.86 15.16 143.86 c +14.37 143.86 13.74 143.23 13.74 142.44 c +13.74 141.66 14.37 141.03 15.16 141.03 c +15.94 141.03 16.57 141.66 16.57 142.44 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +24.91 142.44 m 24.91 143.85 23.76 145.00 22.36 145.00 c +20.95 145.00 19.80 143.85 19.80 142.44 c +19.80 141.04 20.95 139.89 22.36 139.89 c +23.76 139.89 24.91 141.04 24.91 142.44 c +f +0.13 g +[] 0 d +23.77 142.44 m 23.77 143.23 23.14 143.86 22.36 143.86 c +21.57 143.86 20.94 143.23 20.94 142.44 c +20.94 141.66 21.57 141.03 22.36 141.03 c +23.14 141.03 23.77 141.66 23.77 142.44 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +17.71 149.64 m 17.71 151.05 16.56 152.20 15.16 152.20 c +13.75 152.20 12.60 151.05 12.60 149.64 c +12.60 148.24 13.75 147.09 15.16 147.09 c +16.56 147.09 17.71 148.24 17.71 149.64 c +f +0.13 g +[] 0 d +16.57 149.64 m 16.57 150.43 15.94 151.06 15.16 151.06 c +14.37 151.06 13.74 150.43 13.74 149.64 c +13.74 148.86 14.37 148.23 15.16 148.23 c +15.94 148.23 16.57 148.86 16.57 149.64 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +24.91 149.64 m 24.91 151.05 23.76 152.20 22.36 152.20 c +20.95 152.20 19.80 151.05 19.80 149.64 c +19.80 148.24 20.95 147.09 22.36 147.09 c +23.76 147.09 24.91 148.24 24.91 149.64 c +f +0.13 g +[] 0 d +23.77 149.64 m 23.77 150.43 23.14 151.06 22.36 151.06 c +21.57 151.06 20.94 150.43 20.94 149.64 c +20.94 148.86 21.57 148.23 22.36 148.23 c +23.14 148.23 23.77 148.86 23.77 149.64 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +17.71 156.84 m 17.71 158.25 16.56 159.40 15.16 159.40 c +13.75 159.40 12.60 158.25 12.60 156.84 c +12.60 155.44 13.75 154.29 15.16 154.29 c +16.56 154.29 17.71 155.44 17.71 156.84 c +f +0.13 g +[] 0 d +16.57 156.84 m 16.57 157.63 15.94 158.26 15.16 158.26 c +14.37 158.26 13.74 157.63 13.74 156.84 c +13.74 156.06 14.37 155.43 15.16 155.43 c +15.94 155.43 16.57 156.06 16.57 156.84 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +24.91 156.84 m 24.91 158.25 23.76 159.40 22.36 159.40 c +20.95 159.40 19.80 158.25 19.80 156.84 c +19.80 155.44 20.95 154.29 22.36 154.29 c +23.76 154.29 24.91 155.44 24.91 156.84 c +f +0.13 g +[] 0 d +23.77 156.84 m 23.77 157.63 23.14 158.26 22.36 158.26 c +21.57 158.26 20.94 157.63 20.94 156.84 c +20.94 156.06 21.57 155.43 22.36 155.43 c +23.14 155.43 23.77 156.06 23.77 156.84 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +17.71 164.04 m 17.71 165.45 16.56 166.60 15.16 166.60 c +13.75 166.60 12.60 165.45 12.60 164.04 c +12.60 162.64 13.75 161.49 15.16 161.49 c +16.56 161.49 17.71 162.64 17.71 164.04 c +f +0.13 g +[] 0 d +16.57 164.04 m 16.57 164.83 15.94 165.46 15.16 165.46 c +14.37 165.46 13.74 164.83 13.74 164.04 c +13.74 163.26 14.37 162.63 15.16 162.63 c +15.94 162.63 16.57 163.26 16.57 164.04 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +24.91 164.04 m 24.91 165.45 23.76 166.60 22.36 166.60 c +20.95 166.60 19.80 165.45 19.80 164.04 c +19.80 162.64 20.95 161.49 22.36 161.49 c +23.76 161.49 24.91 162.64 24.91 164.04 c +f +0.13 g +[] 0 d +23.77 164.04 m 23.77 164.83 23.14 165.46 22.36 165.46 c +21.57 165.46 20.94 164.83 20.94 164.04 c +20.94 163.26 21.57 162.63 22.36 162.63 c +23.14 162.63 23.77 163.26 23.77 164.04 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +17.71 27.24 m 17.71 28.65 16.56 29.80 15.16 29.80 c +13.75 29.80 12.60 28.65 12.60 27.24 c +12.60 25.84 13.75 24.69 15.16 24.69 c +16.56 24.69 17.71 25.84 17.71 27.24 c +f +0.13 g +[] 0 d +16.57 27.24 m 16.57 28.03 15.94 28.66 15.16 28.66 c +14.37 28.66 13.74 28.03 13.74 27.24 c +13.74 26.46 14.37 25.83 15.16 25.83 c +15.94 25.83 16.57 26.46 16.57 27.24 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +24.91 27.24 m 24.91 28.65 23.76 29.80 22.36 29.80 c +20.95 29.80 19.80 28.65 19.80 27.24 c +19.80 25.84 20.95 24.69 22.36 24.69 c +23.76 24.69 24.91 25.84 24.91 27.24 c +f +0.13 g +[] 0 d +23.77 27.24 m 23.77 28.03 23.14 28.66 22.36 28.66 c +21.57 28.66 20.94 28.03 20.94 27.24 c +20.94 26.46 21.57 25.83 22.36 25.83 c +23.14 25.83 23.77 26.46 23.77 27.24 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +17.71 34.44 m 17.71 35.85 16.56 37.00 15.16 37.00 c +13.75 37.00 12.60 35.85 12.60 34.44 c +12.60 33.04 13.75 31.89 15.16 31.89 c +16.56 31.89 17.71 33.04 17.71 34.44 c +f +0.13 g +[] 0 d +16.57 34.44 m 16.57 35.23 15.94 35.86 15.16 35.86 c +14.37 35.86 13.74 35.23 13.74 34.44 c +13.74 33.66 14.37 33.03 15.16 33.03 c +15.94 33.03 16.57 33.66 16.57 34.44 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +24.91 34.44 m 24.91 35.85 23.76 37.00 22.36 37.00 c +20.95 37.00 19.80 35.85 19.80 34.44 c +19.80 33.04 20.95 31.89 22.36 31.89 c +23.76 31.89 24.91 33.04 24.91 34.44 c +f +0.13 g +[] 0 d +23.77 34.44 m 23.77 35.23 23.14 35.86 22.36 35.86 c +21.57 35.86 20.94 35.23 20.94 34.44 c +20.94 33.66 21.57 33.03 22.36 33.03 c +23.14 33.03 23.77 33.66 23.77 34.44 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +17.71 41.64 m 17.71 43.05 16.56 44.20 15.16 44.20 c +13.75 44.20 12.60 43.05 12.60 41.64 c +12.60 40.24 13.75 39.09 15.16 39.09 c +16.56 39.09 17.71 40.24 17.71 41.64 c +f +0.13 g +[] 0 d +16.57 41.64 m 16.57 42.43 15.94 43.06 15.16 43.06 c +14.37 43.06 13.74 42.43 13.74 41.64 c +13.74 40.86 14.37 40.23 15.16 40.23 c +15.94 40.23 16.57 40.86 16.57 41.64 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +24.91 41.64 m 24.91 43.05 23.76 44.20 22.36 44.20 c +20.95 44.20 19.80 43.05 19.80 41.64 c +19.80 40.24 20.95 39.09 22.36 39.09 c +23.76 39.09 24.91 40.24 24.91 41.64 c +f +0.13 g +[] 0 d +23.77 41.64 m 23.77 42.43 23.14 43.06 22.36 43.06 c +21.57 43.06 20.94 42.43 20.94 41.64 c +20.94 40.86 21.57 40.23 22.36 40.23 c +23.14 40.23 23.77 40.86 23.77 41.64 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +17.71 48.84 m 17.71 50.25 16.56 51.40 15.16 51.40 c +13.75 51.40 12.60 50.25 12.60 48.84 c +12.60 47.44 13.75 46.29 15.16 46.29 c +16.56 46.29 17.71 47.44 17.71 48.84 c +f +0.13 g +[] 0 d +16.57 48.84 m 16.57 49.63 15.94 50.26 15.16 50.26 c +14.37 50.26 13.74 49.63 13.74 48.84 c +13.74 48.06 14.37 47.43 15.16 47.43 c +15.94 47.43 16.57 48.06 16.57 48.84 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +24.91 48.84 m 24.91 50.25 23.76 51.40 22.36 51.40 c +20.95 51.40 19.80 50.25 19.80 48.84 c +19.80 47.44 20.95 46.29 22.36 46.29 c +23.76 46.29 24.91 47.44 24.91 48.84 c +f +0.13 g +[] 0 d +23.77 48.84 m 23.77 49.63 23.14 50.26 22.36 50.26 c +21.57 50.26 20.94 49.63 20.94 48.84 c +20.94 48.06 21.57 47.43 22.36 47.43 c +23.14 47.43 23.77 48.06 23.77 48.84 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +17.71 56.04 m 17.71 57.45 16.56 58.60 15.16 58.60 c +13.75 58.60 12.60 57.45 12.60 56.04 c +12.60 54.64 13.75 53.49 15.16 53.49 c +16.56 53.49 17.71 54.64 17.71 56.04 c +f +0.13 g +[] 0 d +16.57 56.04 m 16.57 56.83 15.94 57.46 15.16 57.46 c +14.37 57.46 13.74 56.83 13.74 56.04 c +13.74 55.26 14.37 54.63 15.16 54.63 c +15.94 54.63 16.57 55.26 16.57 56.04 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +24.91 56.04 m 24.91 57.45 23.76 58.60 22.36 58.60 c +20.95 58.60 19.80 57.45 19.80 56.04 c +19.80 54.64 20.95 53.49 22.36 53.49 c +23.76 53.49 24.91 54.64 24.91 56.04 c +f +0.13 g +[] 0 d +23.77 56.04 m 23.77 56.83 23.14 57.46 22.36 57.46 c +21.57 57.46 20.94 56.83 20.94 56.04 c +20.94 55.26 21.57 54.63 22.36 54.63 c +23.14 54.63 23.77 55.26 23.77 56.04 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +17.71 63.24 m 17.71 64.65 16.56 65.80 15.16 65.80 c +13.75 65.80 12.60 64.65 12.60 63.24 c +12.60 61.84 13.75 60.69 15.16 60.69 c +16.56 60.69 17.71 61.84 17.71 63.24 c +f +0.13 g +[] 0 d +16.57 63.24 m 16.57 64.03 15.94 64.66 15.16 64.66 c +14.37 64.66 13.74 64.03 13.74 63.24 c +13.74 62.46 14.37 61.83 15.16 61.83 c +15.94 61.83 16.57 62.46 16.57 63.24 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +24.91 63.24 m 24.91 64.65 23.76 65.80 22.36 65.80 c +20.95 65.80 19.80 64.65 19.80 63.24 c +19.80 61.84 20.95 60.69 22.36 60.69 c +23.76 60.69 24.91 61.84 24.91 63.24 c +f +0.13 g +[] 0 d +23.77 63.24 m 23.77 64.03 23.14 64.66 22.36 64.66 c +21.57 64.66 20.94 64.03 20.94 63.24 c +20.94 62.46 21.57 61.83 22.36 61.83 c +23.14 61.83 23.77 62.46 23.77 63.24 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +17.71 70.44 m 17.71 71.85 16.56 73.00 15.16 73.00 c +13.75 73.00 12.60 71.85 12.60 70.44 c +12.60 69.04 13.75 67.89 15.16 67.89 c +16.56 67.89 17.71 69.04 17.71 70.44 c +f +0.13 g +[] 0 d +16.57 70.44 m 16.57 71.23 15.94 71.86 15.16 71.86 c +14.37 71.86 13.74 71.23 13.74 70.44 c +13.74 69.66 14.37 69.03 15.16 69.03 c +15.94 69.03 16.57 69.66 16.57 70.44 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +24.91 70.44 m 24.91 71.85 23.76 73.00 22.36 73.00 c +20.95 73.00 19.80 71.85 19.80 70.44 c +19.80 69.04 20.95 67.89 22.36 67.89 c +23.76 67.89 24.91 69.04 24.91 70.44 c +f +0.13 g +[] 0 d +23.77 70.44 m 23.77 71.23 23.14 71.86 22.36 71.86 c +21.57 71.86 20.94 71.23 20.94 70.44 c +20.94 69.66 21.57 69.03 22.36 69.03 c +23.14 69.03 23.77 69.66 23.77 70.44 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +17.71 77.64 m 17.71 79.05 16.56 80.20 15.16 80.20 c +13.75 80.20 12.60 79.05 12.60 77.64 c +12.60 76.24 13.75 75.09 15.16 75.09 c +16.56 75.09 17.71 76.24 17.71 77.64 c +f +0.13 g +[] 0 d +16.57 77.64 m 16.57 78.43 15.94 79.06 15.16 79.06 c +14.37 79.06 13.74 78.43 13.74 77.64 c +13.74 76.86 14.37 76.23 15.16 76.23 c +15.94 76.23 16.57 76.86 16.57 77.64 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +24.91 77.64 m 24.91 79.05 23.76 80.20 22.36 80.20 c +20.95 80.20 19.80 79.05 19.80 77.64 c +19.80 76.24 20.95 75.09 22.36 75.09 c +23.76 75.09 24.91 76.24 24.91 77.64 c +f +0.13 g +[] 0 d +23.77 77.64 m 23.77 78.43 23.14 79.06 22.36 79.06 c +21.57 79.06 20.94 78.43 20.94 77.64 c +20.94 76.86 21.57 76.23 22.36 76.23 c +23.14 76.23 23.77 76.86 23.77 77.64 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +17.71 84.84 m 17.71 86.25 16.56 87.40 15.16 87.40 c +13.75 87.40 12.60 86.25 12.60 84.84 c +12.60 83.44 13.75 82.29 15.16 82.29 c +16.56 82.29 17.71 83.44 17.71 84.84 c +f +0.13 g +[] 0 d +16.57 84.84 m 16.57 85.63 15.94 86.26 15.16 86.26 c +14.37 86.26 13.74 85.63 13.74 84.84 c +13.74 84.06 14.37 83.43 15.16 83.43 c +15.94 83.43 16.57 84.06 16.57 84.84 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +24.91 84.84 m 24.91 86.25 23.76 87.40 22.36 87.40 c +20.95 87.40 19.80 86.25 19.80 84.84 c +19.80 83.44 20.95 82.29 22.36 82.29 c +23.76 82.29 24.91 83.44 24.91 84.84 c +f +0.13 g +[] 0 d +23.77 84.84 m 23.77 85.63 23.14 86.26 22.36 86.26 c +21.57 86.26 20.94 85.63 20.94 84.84 c +20.94 84.06 21.57 83.43 22.36 83.43 c +23.14 83.43 23.77 84.06 23.77 84.84 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +17.71 92.04 m 17.71 93.45 16.56 94.60 15.16 94.60 c +13.75 94.60 12.60 93.45 12.60 92.04 c +12.60 90.64 13.75 89.49 15.16 89.49 c +16.56 89.49 17.71 90.64 17.71 92.04 c +f +0.13 g +[] 0 d +16.57 92.04 m 16.57 92.83 15.94 93.46 15.16 93.46 c +14.37 93.46 13.74 92.83 13.74 92.04 c +13.74 91.26 14.37 90.63 15.16 90.63 c +15.94 90.63 16.57 91.26 16.57 92.04 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +24.91 92.04 m 24.91 93.45 23.76 94.60 22.36 94.60 c +20.95 94.60 19.80 93.45 19.80 92.04 c +19.80 90.64 20.95 89.49 22.36 89.49 c +23.76 89.49 24.91 90.64 24.91 92.04 c +f +0.13 g +[] 0 d +23.77 92.04 m 23.77 92.83 23.14 93.46 22.36 93.46 c +21.57 93.46 20.94 92.83 20.94 92.04 c +20.94 91.26 21.57 90.63 22.36 90.63 c +23.14 90.63 23.77 91.26 23.77 92.04 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +190.62 99.25 m 190.62 100.66 189.48 101.80 188.07 101.80 c +186.66 101.80 185.52 100.66 185.52 99.25 c +185.52 97.84 186.66 96.70 188.07 96.70 c +189.48 96.70 190.62 97.84 190.62 99.25 c +f +0.13 g +[] 0 d +189.49 99.25 m 189.49 100.03 188.85 100.67 188.07 100.67 c +187.29 100.67 186.65 100.03 186.65 99.25 c +186.65 98.47 187.29 97.83 188.07 97.83 c +188.85 97.83 189.49 98.47 189.49 99.25 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +197.82 99.25 m 197.82 100.66 196.68 101.80 195.27 101.80 c +193.86 101.80 192.72 100.66 192.72 99.25 c +192.72 97.84 193.86 96.70 195.27 96.70 c +196.68 96.70 197.82 97.84 197.82 99.25 c +f +0.13 g +[] 0 d +196.69 99.25 m 196.69 100.03 196.05 100.67 195.27 100.67 c +194.49 100.67 193.85 100.03 193.85 99.25 c +193.85 98.47 194.49 97.83 195.27 97.83 c +196.05 97.83 196.69 98.47 196.69 99.25 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +190.62 106.45 m 190.62 107.86 189.48 109.00 188.07 109.00 c +186.66 109.00 185.52 107.86 185.52 106.45 c +185.52 105.04 186.66 103.90 188.07 103.90 c +189.48 103.90 190.62 105.04 190.62 106.45 c +f +0.13 g +[] 0 d +189.49 106.45 m 189.49 107.23 188.85 107.87 188.07 107.87 c +187.29 107.87 186.65 107.23 186.65 106.45 c +186.65 105.67 187.29 105.03 188.07 105.03 c +188.85 105.03 189.49 105.67 189.49 106.45 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +197.82 106.45 m 197.82 107.86 196.68 109.00 195.27 109.00 c +193.86 109.00 192.72 107.86 192.72 106.45 c +192.72 105.04 193.86 103.90 195.27 103.90 c +196.68 103.90 197.82 105.04 197.82 106.45 c +f +0.13 g +[] 0 d +196.69 106.45 m 196.69 107.23 196.05 107.87 195.27 107.87 c +194.49 107.87 193.85 107.23 193.85 106.45 c +193.85 105.67 194.49 105.03 195.27 105.03 c +196.05 105.03 196.69 105.67 196.69 106.45 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +190.62 113.65 m 190.62 115.06 189.48 116.20 188.07 116.20 c +186.66 116.20 185.52 115.06 185.52 113.65 c +185.52 112.24 186.66 111.10 188.07 111.10 c +189.48 111.10 190.62 112.24 190.62 113.65 c +f +0.13 g +[] 0 d +189.49 113.65 m 189.49 114.43 188.85 115.07 188.07 115.07 c +187.29 115.07 186.65 114.43 186.65 113.65 c +186.65 112.87 187.29 112.23 188.07 112.23 c +188.85 112.23 189.49 112.87 189.49 113.65 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +197.82 113.65 m 197.82 115.06 196.68 116.20 195.27 116.20 c +193.86 116.20 192.72 115.06 192.72 113.65 c +192.72 112.24 193.86 111.10 195.27 111.10 c +196.68 111.10 197.82 112.24 197.82 113.65 c +f +0.13 g +[] 0 d +196.69 113.65 m 196.69 114.43 196.05 115.07 195.27 115.07 c +194.49 115.07 193.85 114.43 193.85 113.65 c +193.85 112.87 194.49 112.23 195.27 112.23 c +196.05 112.23 196.69 112.87 196.69 113.65 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +190.62 120.85 m 190.62 122.26 189.48 123.40 188.07 123.40 c +186.66 123.40 185.52 122.26 185.52 120.85 c +185.52 119.44 186.66 118.30 188.07 118.30 c +189.48 118.30 190.62 119.44 190.62 120.85 c +f +0.13 g +[] 0 d +189.49 120.85 m 189.49 121.63 188.85 122.27 188.07 122.27 c +187.29 122.27 186.65 121.63 186.65 120.85 c +186.65 120.07 187.29 119.43 188.07 119.43 c +188.85 119.43 189.49 120.07 189.49 120.85 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +197.82 120.85 m 197.82 122.26 196.68 123.40 195.27 123.40 c +193.86 123.40 192.72 122.26 192.72 120.85 c +192.72 119.44 193.86 118.30 195.27 118.30 c +196.68 118.30 197.82 119.44 197.82 120.85 c +f +0.13 g +[] 0 d +196.69 120.85 m 196.69 121.63 196.05 122.27 195.27 122.27 c +194.49 122.27 193.85 121.63 193.85 120.85 c +193.85 120.07 194.49 119.43 195.27 119.43 c +196.05 119.43 196.69 120.07 196.69 120.85 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +190.62 128.05 m 190.62 129.46 189.48 130.60 188.07 130.60 c +186.66 130.60 185.52 129.46 185.52 128.05 c +185.52 126.64 186.66 125.50 188.07 125.50 c +189.48 125.50 190.62 126.64 190.62 128.05 c +f +0.13 g +[] 0 d +189.49 128.05 m 189.49 128.83 188.85 129.47 188.07 129.47 c +187.29 129.47 186.65 128.83 186.65 128.05 c +186.65 127.27 187.29 126.63 188.07 126.63 c +188.85 126.63 189.49 127.27 189.49 128.05 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +197.82 128.05 m 197.82 129.46 196.68 130.60 195.27 130.60 c +193.86 130.60 192.72 129.46 192.72 128.05 c +192.72 126.64 193.86 125.50 195.27 125.50 c +196.68 125.50 197.82 126.64 197.82 128.05 c +f +0.13 g +[] 0 d +196.69 128.05 m 196.69 128.83 196.05 129.47 195.27 129.47 c +194.49 129.47 193.85 128.83 193.85 128.05 c +193.85 127.27 194.49 126.63 195.27 126.63 c +196.05 126.63 196.69 127.27 196.69 128.05 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +190.62 135.25 m 190.62 136.66 189.48 137.80 188.07 137.80 c +186.66 137.80 185.52 136.66 185.52 135.25 c +185.52 133.84 186.66 132.70 188.07 132.70 c +189.48 132.70 190.62 133.84 190.62 135.25 c +f +0.13 g +[] 0 d +189.49 135.25 m 189.49 136.03 188.85 136.67 188.07 136.67 c +187.29 136.67 186.65 136.03 186.65 135.25 c +186.65 134.47 187.29 133.83 188.07 133.83 c +188.85 133.83 189.49 134.47 189.49 135.25 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +197.82 135.25 m 197.82 136.66 196.68 137.80 195.27 137.80 c +193.86 137.80 192.72 136.66 192.72 135.25 c +192.72 133.84 193.86 132.70 195.27 132.70 c +196.68 132.70 197.82 133.84 197.82 135.25 c +f +0.13 g +[] 0 d +196.69 135.25 m 196.69 136.03 196.05 136.67 195.27 136.67 c +194.49 136.67 193.85 136.03 193.85 135.25 c +193.85 134.47 194.49 133.83 195.27 133.83 c +196.05 133.83 196.69 134.47 196.69 135.25 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +190.62 142.45 m 190.62 143.86 189.48 145.00 188.07 145.00 c +186.66 145.00 185.52 143.86 185.52 142.45 c +185.52 141.04 186.66 139.90 188.07 139.90 c +189.48 139.90 190.62 141.04 190.62 142.45 c +f +0.13 g +[] 0 d +189.49 142.45 m 189.49 143.23 188.85 143.87 188.07 143.87 c +187.29 143.87 186.65 143.23 186.65 142.45 c +186.65 141.67 187.29 141.03 188.07 141.03 c +188.85 141.03 189.49 141.67 189.49 142.45 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +197.82 142.45 m 197.82 143.86 196.68 145.00 195.27 145.00 c +193.86 145.00 192.72 143.86 192.72 142.45 c +192.72 141.04 193.86 139.90 195.27 139.90 c +196.68 139.90 197.82 141.04 197.82 142.45 c +f +0.13 g +[] 0 d +196.69 142.45 m 196.69 143.23 196.05 143.87 195.27 143.87 c +194.49 143.87 193.85 143.23 193.85 142.45 c +193.85 141.67 194.49 141.03 195.27 141.03 c +196.05 141.03 196.69 141.67 196.69 142.45 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +190.62 149.65 m 190.62 151.06 189.48 152.20 188.07 152.20 c +186.66 152.20 185.52 151.06 185.52 149.65 c +185.52 148.24 186.66 147.10 188.07 147.10 c +189.48 147.10 190.62 148.24 190.62 149.65 c +f +0.13 g +[] 0 d +189.49 149.65 m 189.49 150.43 188.85 151.07 188.07 151.07 c +187.29 151.07 186.65 150.43 186.65 149.65 c +186.65 148.87 187.29 148.23 188.07 148.23 c +188.85 148.23 189.49 148.87 189.49 149.65 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +197.82 149.65 m 197.82 151.06 196.68 152.20 195.27 152.20 c +193.86 152.20 192.72 151.06 192.72 149.65 c +192.72 148.24 193.86 147.10 195.27 147.10 c +196.68 147.10 197.82 148.24 197.82 149.65 c +f +0.13 g +[] 0 d +196.69 149.65 m 196.69 150.43 196.05 151.07 195.27 151.07 c +194.49 151.07 193.85 150.43 193.85 149.65 c +193.85 148.87 194.49 148.23 195.27 148.23 c +196.05 148.23 196.69 148.87 196.69 149.65 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +190.62 156.85 m 190.62 158.26 189.48 159.40 188.07 159.40 c +186.66 159.40 185.52 158.26 185.52 156.85 c +185.52 155.44 186.66 154.30 188.07 154.30 c +189.48 154.30 190.62 155.44 190.62 156.85 c +f +0.13 g +[] 0 d +189.49 156.85 m 189.49 157.63 188.85 158.27 188.07 158.27 c +187.29 158.27 186.65 157.63 186.65 156.85 c +186.65 156.07 187.29 155.43 188.07 155.43 c +188.85 155.43 189.49 156.07 189.49 156.85 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +197.82 156.85 m 197.82 158.26 196.68 159.40 195.27 159.40 c +193.86 159.40 192.72 158.26 192.72 156.85 c +192.72 155.44 193.86 154.30 195.27 154.30 c +196.68 154.30 197.82 155.44 197.82 156.85 c +f +0.13 g +[] 0 d +196.69 156.85 m 196.69 157.63 196.05 158.27 195.27 158.27 c +194.49 158.27 193.85 157.63 193.85 156.85 c +193.85 156.07 194.49 155.43 195.27 155.43 c +196.05 155.43 196.69 156.07 196.69 156.85 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +190.62 164.05 m 190.62 165.46 189.48 166.60 188.07 166.60 c +186.66 166.60 185.52 165.46 185.52 164.05 c +185.52 162.64 186.66 161.50 188.07 161.50 c +189.48 161.50 190.62 162.64 190.62 164.05 c +f +0.13 g +[] 0 d +189.49 164.05 m 189.49 164.83 188.85 165.47 188.07 165.47 c +187.29 165.47 186.65 164.83 186.65 164.05 c +186.65 163.27 187.29 162.63 188.07 162.63 c +188.85 162.63 189.49 163.27 189.49 164.05 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +197.82 164.05 m 197.82 165.46 196.68 166.60 195.27 166.60 c +193.86 166.60 192.72 165.46 192.72 164.05 c +192.72 162.64 193.86 161.50 195.27 161.50 c +196.68 161.50 197.82 162.64 197.82 164.05 c +f +0.13 g +[] 0 d +196.69 164.05 m 196.69 164.83 196.05 165.47 195.27 165.47 c +194.49 165.47 193.85 164.83 193.85 164.05 c +193.85 163.27 194.49 162.63 195.27 162.63 c +196.05 162.63 196.69 163.27 196.69 164.05 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +144.61 31.97 m 144.61 33.38 143.46 34.52 142.06 34.52 c +140.65 34.52 139.50 33.38 139.50 31.97 c +139.50 30.56 140.65 29.42 142.06 29.42 c +143.46 29.42 144.61 30.56 144.61 31.97 c +f +0.13 g +[] 0 d +143.54 31.97 m 143.54 32.79 142.88 33.46 142.06 33.46 c +141.23 33.46 140.57 32.79 140.57 31.97 c +140.57 31.15 141.23 30.48 142.06 30.48 c +142.88 30.48 143.54 31.15 143.54 31.97 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +144.61 24.77 m 144.61 26.18 143.46 27.32 142.06 27.32 c +140.65 27.32 139.50 26.18 139.50 24.77 c +139.50 23.36 140.65 22.22 142.06 22.22 c +143.46 22.22 144.61 23.36 144.61 24.77 c +f +0.13 g +[] 0 d +143.54 24.77 m 143.54 25.59 142.88 26.26 142.06 26.26 c +141.23 26.26 140.57 25.59 140.57 24.77 c +140.57 23.95 141.23 23.28 142.06 23.28 c +142.88 23.28 143.54 23.95 143.54 24.77 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +137.41 31.97 m 137.41 33.38 136.26 34.52 134.86 34.52 c +133.45 34.52 132.30 33.38 132.30 31.97 c +132.30 30.56 133.45 29.42 134.86 29.42 c +136.26 29.42 137.41 30.56 137.41 31.97 c +f +0.13 g +[] 0 d +136.34 31.97 m 136.34 32.79 135.68 33.46 134.86 33.46 c +134.03 33.46 133.37 32.79 133.37 31.97 c +133.37 31.15 134.03 30.48 134.86 30.48 c +135.68 30.48 136.34 31.15 136.34 31.97 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +137.41 24.77 m 137.41 26.18 136.26 27.32 134.86 27.32 c +133.45 27.32 132.30 26.18 132.30 24.77 c +132.30 23.36 133.45 22.22 134.86 22.22 c +136.26 22.22 137.41 23.36 137.41 24.77 c +f +0.13 g +[] 0 d +136.34 24.77 m 136.34 25.59 135.68 26.26 134.86 26.26 c +134.03 26.26 133.37 25.59 133.37 24.77 c +133.37 23.95 134.03 23.28 134.86 23.28 c +135.68 23.28 136.34 23.95 136.34 24.77 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +130.21 31.97 m 130.21 33.38 129.06 34.52 127.66 34.52 c +126.25 34.52 125.10 33.38 125.10 31.97 c +125.10 30.56 126.25 29.42 127.66 29.42 c +129.06 29.42 130.21 30.56 130.21 31.97 c +f +0.13 g +[] 0 d +129.14 31.97 m 129.14 32.79 128.48 33.46 127.66 33.46 c +126.83 33.46 126.17 32.79 126.17 31.97 c +126.17 31.15 126.83 30.48 127.66 30.48 c +128.48 30.48 129.14 31.15 129.14 31.97 c +f +2 J +0 j +72 M +0.75 g /a0 gs +[] 0 d +125.105 27.319 m +130.207 27.319 l +130.207 22.217 l +125.105 22.217 l + h +f +0.13 g +[] 0 d +129.14 24.77 m 129.14 25.59 128.48 26.26 127.66 26.26 c +126.83 26.26 126.17 25.59 126.17 24.77 c +126.17 23.95 126.83 23.28 127.66 23.28 c +128.48 23.28 129.14 23.95 129.14 24.77 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +100.18 155.09 m 100.18 156.28 99.22 157.25 98.02 157.25 c +96.83 157.25 95.86 156.28 95.86 155.09 c +95.86 153.90 96.83 152.93 98.02 152.93 c +99.22 152.93 100.18 153.90 100.18 155.09 c +f +0.13 g +[] 0 d +99.30 155.09 m 99.30 155.79 98.73 156.36 98.02 156.36 c +97.32 156.36 96.75 155.79 96.75 155.09 c +96.75 154.38 97.32 153.81 98.02 153.81 c +98.73 153.81 99.30 154.38 99.30 155.09 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +86.01 155.09 m 86.01 156.28 85.04 157.25 83.85 157.25 c +82.66 157.25 81.69 156.28 81.69 155.09 c +81.69 153.90 82.66 152.93 83.85 152.93 c +85.04 152.93 86.01 153.90 86.01 155.09 c +f +0.13 g +[] 0 d +85.12 155.09 m 85.12 155.79 84.55 156.36 83.85 156.36 c +83.14 156.36 82.57 155.79 82.57 155.09 c +82.57 154.38 83.14 153.81 83.85 153.81 c +84.55 153.81 85.12 154.38 85.12 155.09 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +93.10 147.89 m 93.10 149.08 92.13 150.05 90.94 150.05 c +89.74 150.05 88.78 149.08 88.78 147.89 c +88.78 146.70 89.74 145.73 90.94 145.73 c +92.13 145.73 93.10 146.70 93.10 147.89 c +f +0.13 g +[] 0 d +92.21 147.89 m 92.21 148.59 91.64 149.16 90.94 149.16 c +90.23 149.16 89.66 148.59 89.66 147.89 c +89.66 147.18 90.23 146.61 90.94 146.61 c +91.64 146.61 92.21 147.18 92.21 147.89 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +131.50 155.09 m 131.50 156.28 130.54 157.25 129.34 157.25 c +128.15 157.25 127.18 156.28 127.18 155.09 c +127.18 153.90 128.15 152.93 129.34 152.93 c +130.54 152.93 131.50 153.90 131.50 155.09 c +f +0.13 g +[] 0 d +130.62 155.09 m 130.62 155.79 130.05 156.36 129.34 156.36 c +128.64 156.36 128.07 155.79 128.07 155.09 c +128.07 154.38 128.64 153.81 129.34 153.81 c +130.05 153.81 130.62 154.38 130.62 155.09 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +117.33 155.09 m 117.33 156.28 116.36 157.25 115.17 157.25 c +113.98 157.25 113.01 156.28 113.01 155.09 c +113.01 153.90 113.98 152.93 115.17 152.93 c +116.36 152.93 117.33 153.90 117.33 155.09 c +f +0.13 g +[] 0 d +116.44 155.09 m 116.44 155.79 115.87 156.36 115.17 156.36 c +114.46 156.36 113.89 155.79 113.89 155.09 c +113.89 154.38 114.46 153.81 115.17 153.81 c +115.87 153.81 116.44 154.38 116.44 155.09 c +f +1 J +1 j +0.75 g /a0 gs +[] 0 d +124.42 147.89 m 124.42 149.08 123.45 150.05 122.26 150.05 c +121.06 150.05 120.10 149.08 120.10 147.89 c +120.10 146.70 121.06 145.73 122.26 145.73 c +123.45 145.73 124.42 146.70 124.42 147.89 c +f +0.13 g +[] 0 d +123.53 147.89 m 123.53 148.59 122.96 149.16 122.26 149.16 c +121.55 149.16 120.98 148.59 120.98 147.89 c +120.98 147.18 121.55 146.61 122.26 146.61 c +122.96 146.61 123.53 147.18 123.53 147.89 c +f +0.75 g /a0 gs +[] 0 d +94.45 60.05 m 94.45 60.60 94.00 61.04 93.46 61.04 c +92.91 61.04 92.46 60.60 92.46 60.05 c +92.46 59.50 92.91 59.06 93.46 59.06 c +94.00 59.06 94.45 59.50 94.45 60.05 c +f +0.13 g /a0 gs +[] 0 d +93.89 60.05 m 93.89 60.29 93.69 60.48 93.46 60.48 c +93.22 60.48 93.02 60.29 93.02 60.05 c +93.02 59.81 93.22 59.62 93.46 59.62 c +93.69 59.62 93.89 59.81 93.89 60.05 c +f +0.75 g /a0 gs +[] 0 d +51.97 50.69 m 51.97 51.24 51.52 51.68 50.98 51.68 c +50.43 51.68 49.98 51.24 49.98 50.69 c +49.98 50.14 50.43 49.70 50.98 49.70 c +51.52 49.70 51.97 50.14 51.97 50.69 c +f +0.13 g /a0 gs +[] 0 d +51.41 50.69 m 51.41 50.93 51.21 51.12 50.98 51.12 c +50.74 51.12 50.54 50.93 50.54 50.69 c +50.54 50.45 50.74 50.26 50.98 50.26 c +51.21 50.26 51.41 50.45 51.41 50.69 c +f +0.75 g /a0 gs +[] 0 d +179.05 113.33 m 179.05 113.88 178.60 114.32 178.06 114.32 c +177.51 114.32 177.06 113.88 177.06 113.33 c +177.06 112.78 177.51 112.34 178.06 112.34 c +178.60 112.34 179.05 112.78 179.05 113.33 c +f +0.13 g /a0 gs +[] 0 d +178.49 113.33 m 178.49 113.57 178.29 113.76 178.06 113.76 c +177.82 113.76 177.62 113.57 177.62 113.33 c +177.62 113.09 177.82 112.90 178.06 112.90 c +178.29 112.90 178.49 113.09 178.49 113.33 c +f +0.75 g /a0 gs +[] 0 d +184.45 89.57 m 184.45 90.12 184.00 90.56 183.46 90.56 c +182.91 90.56 182.46 90.12 182.46 89.57 c +182.46 89.02 182.91 88.58 183.46 88.58 c +184.00 88.58 184.45 89.02 184.45 89.57 c +f +0.13 g /a0 gs +[] 0 d +183.89 89.57 m 183.89 89.81 183.69 90.00 183.46 90.00 c +183.22 90.00 183.02 89.81 183.02 89.57 c +183.02 89.33 183.22 89.14 183.46 89.14 c +183.69 89.14 183.89 89.33 183.89 89.57 c +f +0.75 g /a0 gs +[] 0 d +171.13 89.57 m 171.13 90.12 170.68 90.56 170.14 90.56 c +169.59 90.56 169.14 90.12 169.14 89.57 c +169.14 89.02 169.59 88.58 170.14 88.58 c +170.68 88.58 171.13 89.02 171.13 89.57 c +f +0.13 g /a0 gs +[] 0 d +170.57 89.57 m 170.57 89.81 170.37 90.00 170.14 90.00 c +169.90 90.00 169.70 89.81 169.70 89.57 c +169.70 89.33 169.90 89.14 170.14 89.14 c +170.37 89.14 170.57 89.33 170.57 89.57 c +f +0.75 g /a0 gs +[] 0 d +67.81 75.17 m 67.81 75.72 67.36 76.16 66.82 76.16 c +66.27 76.16 65.82 75.72 65.82 75.17 c +65.82 74.62 66.27 74.18 66.82 74.18 c +67.36 74.18 67.81 74.62 67.81 75.17 c +f +0.13 g /a0 gs +[] 0 d +67.25 75.17 m 67.25 75.41 67.05 75.60 66.82 75.60 c +66.58 75.60 66.38 75.41 66.38 75.17 c +66.38 74.93 66.58 74.74 66.82 74.74 c +67.05 74.74 67.25 74.93 67.25 75.17 c +f +0.75 g /a0 gs +[] 0 d +96.61 75.17 m 96.61 75.72 96.16 76.16 95.62 76.16 c +95.07 76.16 94.62 75.72 94.62 75.17 c +94.62 74.62 95.07 74.18 95.62 74.18 c +96.16 74.18 96.61 74.62 96.61 75.17 c +f +0.13 g /a0 gs +[] 0 d +96.05 75.17 m 96.05 75.41 95.85 75.60 95.62 75.60 c +95.38 75.60 95.18 75.41 95.18 75.17 c +95.18 74.93 95.38 74.74 95.62 74.74 c +95.85 74.74 96.05 74.93 96.05 75.17 c +f +0.75 g /a0 gs +[] 0 d +125.05 82.73 m 125.05 83.28 124.60 83.72 124.06 83.72 c +123.51 83.72 123.06 83.28 123.06 82.73 c +123.06 82.18 123.51 81.74 124.06 81.74 c +124.60 81.74 125.05 82.18 125.05 82.73 c +f +0.13 g /a0 gs +[] 0 d +124.49 82.73 m 124.49 82.97 124.29 83.16 124.06 83.16 c +123.82 83.16 123.62 82.97 123.62 82.73 c +123.62 82.49 123.82 82.30 124.06 82.30 c +124.29 82.30 124.49 82.49 124.49 82.73 c +f +0.75 g /a0 gs +[] 0 d +167.17 118.73 m 167.17 119.28 166.72 119.72 166.18 119.72 c +165.63 119.72 165.18 119.28 165.18 118.73 c +165.18 118.18 165.63 117.74 166.18 117.74 c +166.72 117.74 167.17 118.18 167.17 118.73 c +f +0.13 g /a0 gs +[] 0 d +166.61 118.73 m 166.61 118.97 166.41 119.16 166.18 119.16 c +165.94 119.16 165.74 118.97 165.74 118.73 c +165.74 118.49 165.94 118.30 166.18 118.30 c +166.41 118.30 166.61 118.49 166.61 118.73 c +f +0.75 g /a0 gs +[] 0 d +59.17 75.17 m 59.17 75.72 58.72 76.16 58.18 76.16 c +57.63 76.16 57.18 75.72 57.18 75.17 c +57.18 74.62 57.63 74.18 58.18 74.18 c +58.72 74.18 59.17 74.62 59.17 75.17 c +f +0.13 g /a0 gs +[] 0 d +58.61 75.17 m 58.61 75.41 58.41 75.60 58.18 75.60 c +57.94 75.60 57.74 75.41 57.74 75.17 c +57.74 74.93 57.94 74.74 58.18 74.74 c +58.41 74.74 58.61 74.93 58.61 75.17 c +f +0.75 g /a0 gs +[] 0 d +112.45 79.85 m 112.45 80.40 112.00 80.84 111.46 80.84 c +110.91 80.84 110.46 80.40 110.46 79.85 c +110.46 79.30 110.91 78.86 111.46 78.86 c +112.00 78.86 112.45 79.30 112.45 79.85 c +f +0.13 g /a0 gs +[] 0 d +111.89 79.85 m 111.89 80.09 111.69 80.28 111.46 80.28 c +111.22 80.28 111.02 80.09 111.02 79.85 c +111.02 79.61 111.22 79.42 111.46 79.42 c +111.69 79.42 111.89 79.61 111.89 79.85 c +f +0.75 g /a0 gs +[] 0 d +35.41 145.37 m 35.41 145.92 34.96 146.36 34.42 146.36 c +33.87 146.36 33.42 145.92 33.42 145.37 c +33.42 144.82 33.87 144.38 34.42 144.38 c +34.96 144.38 35.41 144.82 35.41 145.37 c +f +0.13 g /a0 gs +[] 0 d +34.85 145.37 m 34.85 145.61 34.65 145.80 34.42 145.80 c +34.18 145.80 33.98 145.61 33.98 145.37 c +33.98 145.13 34.18 144.94 34.42 144.94 c +34.65 144.94 34.85 145.13 34.85 145.37 c +f +0.75 g /a0 gs +[] 0 d +82.21 79.85 m 82.21 80.40 81.76 80.84 81.22 80.84 c +80.67 80.84 80.22 80.40 80.22 79.85 c +80.22 79.30 80.67 78.86 81.22 78.86 c +81.76 78.86 82.21 79.30 82.21 79.85 c +f +0.13 g /a0 gs +[] 0 d +81.65 79.85 m 81.65 80.09 81.45 80.28 81.22 80.28 c +80.98 80.28 80.78 80.09 80.78 79.85 c +80.78 79.61 80.98 79.42 81.22 79.42 c +81.45 79.42 81.65 79.61 81.65 79.85 c +f +0.75 g /a0 gs +[] 0 d +35.41 95.33 m 35.41 95.88 34.96 96.32 34.42 96.32 c +33.87 96.32 33.42 95.88 33.42 95.33 c +33.42 94.78 33.87 94.34 34.42 94.34 c +34.96 94.34 35.41 94.78 35.41 95.33 c +f +0.13 g /a0 gs +[] 0 d +34.85 95.33 m 34.85 95.57 34.65 95.76 34.42 95.76 c +34.18 95.76 33.98 95.57 33.98 95.33 c +33.98 95.09 34.18 94.90 34.42 94.90 c +34.65 94.90 34.85 95.09 34.85 95.33 c +f +0.75 g /a0 gs +[] 0 d +64.21 95.33 m 64.21 95.88 63.76 96.32 63.22 96.32 c +62.67 96.32 62.22 95.88 62.22 95.33 c +62.22 94.78 62.67 94.34 63.22 94.34 c +63.76 94.34 64.21 94.78 64.21 95.33 c +f +0.13 g /a0 gs +[] 0 d +63.65 95.33 m 63.65 95.57 63.45 95.76 63.22 95.76 c +62.98 95.76 62.78 95.57 62.78 95.33 c +62.78 95.09 62.98 94.90 63.22 94.90 c +63.45 94.90 63.65 95.09 63.65 95.33 c +f +0.75 g /a0 gs +[] 0 d +93.15 95.33 m 93.15 95.88 92.71 96.32 92.16 96.32 c +91.61 96.32 91.16 95.88 91.16 95.33 c +91.16 94.78 91.61 94.34 92.16 94.34 c +92.71 94.34 93.15 94.78 93.15 95.33 c +f +0.13 g /a0 gs +[] 0 d +92.59 95.33 m 92.59 95.57 92.40 95.76 92.16 95.76 c +91.92 95.76 91.73 95.57 91.73 95.33 c +91.73 95.09 91.92 94.90 92.16 94.90 c +92.40 94.90 92.59 95.09 92.59 95.33 c +f +0.75 g /a0 gs +[] 0 d +123.25 95.33 m 123.25 95.88 122.80 96.32 122.26 96.32 c +121.71 96.32 121.26 95.88 121.26 95.33 c +121.26 94.78 121.71 94.34 122.26 94.34 c +122.80 94.34 123.25 94.78 123.25 95.33 c +f +0.13 g /a0 gs +[] 0 d +122.69 95.33 m 122.69 95.57 122.49 95.76 122.26 95.76 c +122.02 95.76 121.82 95.57 121.82 95.33 c +121.82 95.09 122.02 94.90 122.26 94.90 c +122.49 94.90 122.69 95.09 122.69 95.33 c +f +0.13 g +[] 0 d +46.76 26.31 m 46.76 27.56 45.74 28.58 44.49 28.58 c +43.24 28.58 42.22 27.56 42.22 26.31 c +42.22 25.06 43.24 24.04 44.49 24.04 c +45.74 24.04 46.76 25.06 46.76 26.31 c +f +0.13 g +[] 0 d +46.78 43.35 m 46.78 44.60 45.76 45.62 44.51 45.62 c +43.26 45.62 42.24 44.60 42.24 43.35 c +42.24 42.10 43.26 41.08 44.51 41.08 c +45.76 41.08 46.78 42.10 46.78 43.35 c +f +0.13 g +[] 0 d +73.40 25.95 m 73.40 27.20 72.38 28.22 71.13 28.22 c +69.88 28.22 68.86 27.20 68.86 25.95 c +68.86 24.70 69.88 23.68 71.13 23.68 c +72.38 23.68 73.40 24.70 73.40 25.95 c +f +0.13 g +[] 0 d +73.42 42.99 m 73.42 44.24 72.40 45.26 71.15 45.26 c +69.90 45.26 68.88 44.24 68.88 42.99 c +68.88 41.74 69.90 40.72 71.15 40.72 c +72.40 40.72 73.42 41.74 73.42 42.99 c +f +0.13 g +[] 0 d +101.12 25.95 m 101.12 27.20 100.10 28.22 98.85 28.22 c +97.60 28.22 96.58 27.20 96.58 25.95 c +96.58 24.70 97.60 23.68 98.85 23.68 c +100.10 23.68 101.12 24.70 101.12 25.95 c +f +0.13 g +[] 0 d +101.14 42.99 m 101.14 44.24 100.12 45.26 98.87 45.26 c +97.62 45.26 96.60 44.24 96.60 42.99 c +96.60 41.74 97.62 40.72 98.87 40.72 c +100.12 40.72 101.14 41.74 101.14 42.99 c +f +0.13 g +[] 0 d +193.14 85.88 m 193.14 86.35 192.76 86.73 192.29 86.73 c +191.82 86.73 191.44 86.35 191.44 85.88 c +191.44 85.41 191.82 85.03 192.29 85.03 c +192.76 85.03 193.14 85.41 193.14 85.88 c +f +0.13 g +[] 0 d +193.14 74.54 m 193.14 75.01 192.76 75.39 192.29 75.39 c +191.82 75.39 191.44 75.01 191.44 74.54 c +191.44 74.07 191.82 73.69 192.29 73.69 c +192.76 73.69 193.14 74.07 193.14 74.54 c +f +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +38.248 74.161 m +35.530 74.161 l +35.530 70.415 l +38.248 70.415 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +40.664 74.161 m +43.382 74.161 l +43.382 70.415 l +40.664 70.415 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +34.129 83.936 m +34.129 86.654 l +30.383 86.654 l +30.383 83.936 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +34.129 81.520 m +34.129 78.802 l +30.383 78.802 l +30.383 81.520 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +42.208 105.121 m +39.490 105.121 l +39.490 101.375 l +42.208 101.375 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +44.624 105.121 m +47.342 105.121 l +47.342 101.375 l +44.624 101.375 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +60.049 83.216 m +60.049 85.934 l +56.303 85.934 l +56.303 83.216 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +60.049 80.800 m +60.049 78.082 l +56.303 78.082 l +56.303 80.800 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +77.384 100.655 m +80.102 100.655 l +80.102 104.401 l +77.384 104.401 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +74.968 100.655 m +72.250 100.655 l +72.250 104.401 l +74.968 104.401 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +82.223 86.920 m +82.223 84.202 l +85.969 84.202 l +85.969 86.920 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +82.223 89.336 m +82.223 92.054 l +85.969 92.054 l +85.969 89.336 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +104.488 111.241 m +101.770 111.241 l +101.770 107.495 l +104.488 107.495 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +106.904 111.241 m +109.622 111.241 l +109.622 107.495 l +106.904 107.495 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +106.904 100.655 m +109.622 100.655 l +109.622 104.401 l +106.904 104.401 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +104.488 100.655 m +101.770 100.655 l +101.770 104.401 l +104.488 104.401 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +109.943 86.560 m +109.943 83.842 l +113.689 83.842 l +113.689 86.560 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +109.943 88.976 m +109.943 91.694 l +113.689 91.694 l +113.689 88.976 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +178.739 143.963 m +173.772 143.963 l +173.772 141.010 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +178.739 135.253 m +173.772 135.253 l +173.772 138.206 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +178.739 140.899 m +178.739 138.317 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +36.255 83.815 m +36.255 92.441 l +50.577 92.441 l +50.577 83.815 l +36.255 83.815 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +79.377 92.081 m +79.377 83.455 l +65.055 83.455 l +65.055 92.081 l +79.377 92.081 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +108.177 92.441 m +108.177 83.815 l +93.855 83.815 l +93.855 92.441 l +108.177 92.441 l +S +1 J +1 j +0.58 w +1.00 0.80 0.00 RG /a0 gs +145.656 21.168 m +145.656 35.568 l +124.056 35.568 l +124.056 21.168 l +145.656 21.168 l +131.856 21.168 l +S +1 J +1 j +0.58 w +1.00 0.80 0.00 RG /a0 gs +124.056 28.375 m +131.256 28.375 l +131.256 21.168 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +163.386 132.488 m +159.744 132.488 l +159.744 127.288 l +163.386 127.288 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +166.086 132.488 m +169.728 132.488 l +169.728 127.288 l +166.086 127.288 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +87.099 158.061 m +94.782 158.061 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +77.471 168.638 m +104.400 168.638 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +77.471 168.638 m +77.471 141.278 l +78.695 141.278 l +78.695 142.358 l +103.535 142.358 l +103.535 141.278 l +104.615 141.278 l +104.615 168.638 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +118.419 158.061 m +126.102 158.061 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +108.791 168.638 m +135.720 168.638 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +108.791 168.638 m +108.791 141.278 l +110.015 141.278 l +110.015 142.358 l +134.855 142.358 l +134.855 141.278 l +135.935 141.278 l +135.935 168.638 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +161.189 81.308 m +158.921 81.308 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +162.068 84.454 m +162.068 82.186 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +158.043 84.454 m +158.043 82.186 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +162.084 86.086 m +162.084 88.354 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +161.206 89.232 m +158.938 89.232 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +158.060 86.086 m +158.060 88.354 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +136.603 84.868 m +138.871 84.868 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +135.724 81.722 m +135.724 83.990 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +139.749 81.722 m +139.749 83.990 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +135.708 80.090 m +135.708 77.822 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +136.586 76.944 m +138.854 76.944 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +139.732 80.090 m +139.732 77.822 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +150.316 93.941 m +150.316 91.673 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +147.170 94.820 m +149.438 94.820 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +147.170 90.795 m +149.438 90.795 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +145.538 94.836 m +143.270 94.836 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +142.392 93.958 m +142.392 91.690 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +145.538 90.812 m +143.270 90.812 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +151.087 79.055 m +145.985 79.055 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +151.087 87.842 m +145.985 87.842 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +162.496 138.258 m +162.496 134.616 l +167.696 134.616 l +167.696 138.258 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +162.496 140.958 m +162.496 144.600 l +167.696 144.600 l +167.696 140.958 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +34.544 155.375 m +37.262 155.375 l +37.262 159.121 l +34.544 159.121 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +32.128 155.375 m +29.410 155.375 l +29.410 159.121 l +32.128 159.121 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +34.533 160.055 m +37.251 160.055 l +37.251 163.801 l +34.533 163.801 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +32.117 160.055 m +29.398 160.055 l +29.398 163.801 l +32.117 163.801 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +34.533 164.755 m +37.251 164.755 l +37.251 168.500 l +34.533 168.500 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +32.117 164.755 m +29.398 164.755 l +29.398 168.500 l +32.117 168.500 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +38.456 59.238 m +38.456 62.880 l +33.256 62.880 l +33.256 59.238 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +38.456 56.538 m +38.456 52.896 l +33.256 52.896 l +33.256 56.538 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +74.646 69.328 m +78.288 69.328 l +78.288 74.528 l +74.646 74.528 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +71.946 69.328 m +68.304 69.328 l +68.304 74.528 l +71.946 74.528 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +74.763 61.409 m +74.763 63.445 l +77.589 63.445 l +77.589 61.409 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +74.763 60.127 m +74.763 58.091 l +77.589 58.091 l +77.589 60.127 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +103.446 69.688 m +107.088 69.688 l +107.088 74.888 l +103.446 74.888 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +100.746 69.688 m +97.104 69.688 l +97.104 74.888 l +100.746 74.888 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +103.563 61.769 m +103.563 63.805 l +106.389 63.805 l +106.389 61.769 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +103.563 60.487 m +103.563 58.451 l +106.389 58.451 l +106.389 60.487 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +173.036 146.755 m +173.036 149.023 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +176.182 145.876 m +173.914 145.876 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +176.182 149.901 m +173.914 149.901 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +177.814 145.860 m +180.082 145.860 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +180.960 146.738 m +180.960 149.006 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +177.814 149.884 m +180.082 149.884 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +85.949 53.948 m +83.681 53.948 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +86.828 57.094 m +86.828 54.826 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +82.803 57.094 m +82.803 54.826 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +86.844 58.726 m +86.844 60.994 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +85.966 61.872 m +83.698 61.872 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +82.820 58.726 m +82.820 60.994 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +113.309 53.948 m +111.041 53.948 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +114.188 57.094 m +114.188 54.826 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +110.163 57.094 m +110.163 54.826 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +114.204 58.726 m +114.204 60.994 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +113.326 61.872 m +111.058 61.872 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +110.180 58.726 m +110.180 60.994 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +47.699 159.084 m +42.732 159.084 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +47.699 164.052 m +42.732 164.052 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +52.993 19.189 m +35.985 19.189 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +53.001 51.813 m +35.994 51.813 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +37.402 12.133 m +37.402 19.220 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +51.575 12.133 m +51.575 19.218 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +51.575 12.133 m +37.402 12.133 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +52.993 19.189 m +52.993 21.894 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +52.993 26.749 m +52.993 30.995 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +52.993 35.850 m +52.993 40.067 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +52.993 44.922 m +52.993 51.813 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +35.985 51.818 m +35.985 44.922 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +35.985 40.067 m +35.985 35.850 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +35.985 30.995 m +35.985 26.749 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +35.985 21.894 m +35.985 19.220 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +79.633 18.829 m +62.625 18.829 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +79.641 51.453 m +62.634 51.453 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +64.042 11.773 m +64.042 18.860 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +78.215 11.773 m +78.215 18.858 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +78.215 11.773 m +64.042 11.773 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +79.633 18.829 m +79.633 21.534 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +79.633 26.389 m +79.633 30.635 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +79.633 35.490 m +79.633 39.707 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +79.633 44.562 m +79.633 51.453 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +62.625 51.458 m +62.625 44.562 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +62.625 39.707 m +62.625 35.490 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +62.625 30.635 m +62.625 26.389 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +62.625 21.534 m +62.625 18.860 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +107.353 18.829 m +90.345 18.829 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +107.361 51.453 m +90.354 51.453 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +91.762 11.773 m +91.762 18.860 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +105.935 11.773 m +105.935 18.858 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +105.935 11.773 m +91.762 11.773 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +107.353 18.829 m +107.353 21.534 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +107.353 26.389 m +107.353 30.635 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +107.353 35.490 m +107.353 39.707 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +107.353 44.562 m +107.353 51.453 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +90.345 51.458 m +90.345 44.562 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +90.345 39.707 m +90.345 35.490 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +90.345 30.635 m +90.345 26.389 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +90.345 21.534 m +90.345 18.860 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +202.182 86.904 m +202.182 85.032 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +201.822 87.120 m +201.822 86.904 l +201.966 86.904 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +200.814 87.408 m +201.534 87.408 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +198.078 86.904 m +200.238 86.904 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +197.790 85.320 m +197.790 86.616 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +200.238 85.032 m +198.078 85.032 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +201.534 84.528 m +200.814 84.528 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +201.822 84.816 m +201.822 85.032 l +201.966 85.032 l +202.182 85.032 l +202.830 85.032 l +202.830 86.904 l +202.182 86.904 l +201.966 86.904 l +201.966 85.032 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +202.326 75.168 m +202.326 73.296 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +201.966 75.384 m +201.966 75.168 l +202.110 75.168 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +200.958 75.672 m +201.678 75.672 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +198.222 75.168 m +200.382 75.168 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +197.934 73.584 m +197.934 74.880 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +200.382 73.296 m +198.222 73.296 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +201.678 72.792 m +200.958 72.792 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +201.966 73.080 m +201.966 73.296 l +202.110 73.296 l +202.326 73.296 l +202.974 73.296 l +202.974 75.168 l +202.326 75.168 l +202.110 75.168 l +202.110 73.296 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +196.057 90.194 m +194.079 90.194 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +190.750 73.635 m +190.750 74.666 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +190.750 85.750 m +190.750 86.781 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +205.870 70.034 m +205.870 90.194 l +201.619 90.194 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +205.870 70.034 m +201.619 70.034 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +196.057 70.034 m +194.079 70.034 l +S +1 J +1 j +0.58 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +157.205 44.878 m +156.974 45.338 l +156.276 45.576 l +155.585 45.576 l +154.886 45.338 l +154.656 44.878 l +154.886 44.417 l +155.354 44.179 l +156.514 43.949 l +156.974 43.718 l +157.205 43.258 l +157.205 43.020 l +156.974 42.559 l +156.276 42.329 l +155.585 42.329 l +154.886 42.559 l +154.656 43.020 l +159.437 47.196 m +159.437 43.258 l +159.667 42.559 l +160.128 42.329 l +160.596 42.329 l +158.738 45.576 m +160.358 45.576 l +162.122 45.576 m +162.122 42.329 l +162.122 44.647 m +162.821 45.338 l +163.282 45.576 l +163.980 45.576 l +164.441 45.338 l +164.678 44.647 l +164.678 42.329 l +164.678 44.647 m +165.370 45.338 l +165.838 45.576 l +166.529 45.576 l +166.997 45.338 l +167.227 44.647 l +167.227 42.329 l +171.540 47.196 m +171.540 42.329 l +171.540 44.878 m +171.079 45.338 l +170.611 45.576 l +169.920 45.576 l +169.452 45.338 l +168.991 44.878 l +168.754 44.179 l +168.754 43.718 l +168.991 43.020 l +169.452 42.559 l +169.920 42.329 l +170.611 42.329 l +171.079 42.559 l +171.540 43.020 l +175.622 44.878 m +175.392 45.338 l +174.694 45.576 l +173.995 45.576 l +173.304 45.338 l +173.074 44.878 l +173.304 44.417 l +173.765 44.179 l +174.924 43.949 l +175.392 43.718 l +175.622 43.258 l +175.622 43.020 l +175.392 42.559 l +174.694 42.329 l +173.995 42.329 l +173.304 42.559 l +173.074 43.020 l +177.156 45.576 m +177.156 40.702 l +177.156 44.878 m +177.617 45.338 l +178.078 45.576 l +178.776 45.576 l +179.237 45.338 l +179.705 44.878 l +179.935 44.179 l +179.935 43.718 l +179.705 43.020 l +179.237 42.559 l +178.776 42.329 l +178.078 42.329 l +177.617 42.559 l +177.156 43.020 l +185.040 45.576 m +185.040 42.329 l +185.040 44.179 m +185.270 44.878 l +185.731 45.338 l +186.199 45.576 l +186.890 45.576 l +188.424 44.179 m +191.210 44.179 l +191.210 44.647 l +190.973 45.108 l +190.742 45.338 l +190.282 45.576 l +189.583 45.576 l +189.122 45.338 l +188.654 44.878 l +188.424 44.179 l +188.424 43.718 l +188.654 43.020 l +189.122 42.559 l +189.583 42.329 l +190.282 42.329 l +190.742 42.559 l +191.210 43.020 l +192.737 45.576 m +194.126 42.329 l +195.523 45.576 m +194.126 42.329 l +197.287 46.037 m +197.287 46.267 l +197.518 46.735 l +197.748 46.966 l +198.209 47.196 l +199.138 47.196 l +199.606 46.966 l +199.836 46.735 l +200.066 46.267 l +200.066 45.806 l +199.836 45.338 l +199.368 44.647 l +197.050 42.329 l +200.297 42.329 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +126.631 38.712 m +126.336 38.417 l +126.185 37.970 l +126.185 37.387 l +126.336 36.941 l +126.631 36.645 l +126.926 36.645 l +127.214 36.797 l +127.365 36.941 l +127.509 37.236 l +127.805 38.121 l +127.956 38.417 l +128.100 38.561 l +128.395 38.712 l +128.834 38.712 l +129.129 38.417 l +129.281 37.970 l +129.281 37.387 l +129.129 36.941 l +128.834 36.645 l +126.185 39.684 m +129.281 39.684 l +126.926 42.866 m +126.631 42.715 l +126.336 42.420 l +126.185 42.125 l +126.185 41.534 l +126.336 41.246 l +126.631 40.951 l +126.926 40.800 l +127.365 40.656 l +128.100 40.656 l +128.546 40.800 l +128.834 40.951 l +129.129 41.246 l +129.281 41.534 l +129.281 42.125 l +129.129 42.420 l +128.834 42.715 l +128.546 42.866 l +128.100 42.866 l +128.100 42.125 m +128.100 42.866 l +126.185 43.838 m +129.281 43.838 l +126.185 43.838 m +129.281 45.897 l +126.185 45.897 m +129.281 45.897 l +126.185 48.050 m +129.281 46.869 l +126.185 48.050 m +129.281 49.224 l +128.251 47.309 m +128.251 48.785 l +126.185 50.196 m +129.281 50.196 l +129.281 50.196 m +129.281 51.967 l +126.185 55.207 m +129.281 55.207 l +126.185 56.179 m +129.281 56.179 l +126.185 56.179 m +129.281 58.238 l +126.185 58.238 m +129.281 58.238 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +133.826 38.707 m +133.531 38.412 l +133.387 37.973 l +133.387 37.382 l +133.531 36.943 l +133.826 36.648 l +134.122 36.648 l +134.417 36.792 l +134.568 36.943 l +134.712 37.238 l +135.007 38.124 l +135.151 38.412 l +135.302 38.563 l +135.598 38.707 l +136.037 38.707 l +136.332 38.412 l +136.476 37.973 l +136.476 37.382 l +136.332 36.943 l +136.037 36.648 l +133.387 39.679 m +136.476 39.679 l +134.122 42.862 m +133.826 42.718 l +133.531 42.422 l +133.387 42.127 l +133.387 41.537 l +133.531 41.242 l +133.826 40.946 l +134.122 40.802 l +134.568 40.651 l +135.302 40.651 l +135.742 40.802 l +136.037 40.946 l +136.332 41.242 l +136.476 41.537 l +136.476 42.127 l +136.332 42.422 l +136.037 42.718 l +135.742 42.862 l +135.302 42.862 l +135.302 42.127 m +135.302 42.862 l +133.387 43.834 m +136.476 43.834 l +133.387 43.834 m +136.476 45.900 l +133.387 45.900 m +136.476 45.900 l +133.387 48.046 m +136.476 46.872 l +133.387 48.046 m +136.476 49.226 l +135.446 47.311 m +135.446 48.780 l +133.387 50.198 m +136.476 50.198 l +136.476 50.198 m +136.476 51.962 l +133.387 56.088 m +133.531 55.793 l +133.826 55.498 l +134.122 55.354 l +134.568 55.202 l +135.302 55.202 l +135.742 55.354 l +136.037 55.498 l +136.332 55.793 l +136.476 56.088 l +136.476 56.678 l +136.332 56.974 l +136.037 57.269 l +135.742 57.413 l +135.302 57.564 l +134.568 57.564 l +134.122 57.413 l +133.826 57.269 l +133.531 56.974 l +133.387 56.678 l +133.387 56.088 l +133.387 58.536 m +135.598 58.536 l +136.037 58.680 l +136.332 58.975 l +136.476 59.414 l +136.476 59.710 l +136.332 60.156 l +136.037 60.444 l +135.598 60.595 l +133.387 60.595 l +133.387 62.597 m +136.476 62.597 l +133.387 61.567 m +133.387 63.626 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +140.962 38.858 m +140.666 38.707 l +140.371 38.412 l +140.227 38.124 l +140.227 37.534 l +140.371 37.238 l +140.666 36.943 l +140.962 36.792 l +141.408 36.648 l +142.142 36.648 l +142.582 36.792 l +142.877 36.943 l +143.172 37.238 l +143.316 37.534 l +143.316 38.124 l +143.172 38.412 l +142.877 38.707 l +142.582 38.858 l +142.142 38.858 l +142.142 38.124 m +142.142 38.858 l +140.227 39.830 m +143.316 39.830 l +140.227 39.830 m +140.227 41.746 l +141.696 39.830 m +141.696 41.004 l +143.316 39.830 m +143.316 41.746 l +140.227 42.718 m +143.316 42.718 l +140.227 42.718 m +143.316 44.777 l +140.227 44.777 m +143.316 44.777 l +140.227 45.749 m +143.316 45.749 l +140.227 45.749 m +140.227 47.664 l +141.696 45.749 m +141.696 46.930 l +143.316 45.749 m +143.316 47.664 l +140.227 48.636 m +143.316 48.636 l +140.227 48.636 m +140.227 49.961 l +140.371 50.400 l +140.522 50.551 l +140.818 50.695 l +141.113 50.695 l +141.408 50.551 l +141.552 50.400 l +141.696 49.961 l +141.696 48.636 l +141.696 49.666 m +143.316 50.695 l +140.227 52.848 m +143.316 51.667 l +140.227 52.848 m +143.316 54.029 l +142.286 52.114 m +142.286 53.582 l +140.227 56.030 m +143.316 56.030 l +140.227 55.001 m +140.227 57.060 l +140.227 58.918 m +140.371 58.622 l +140.666 58.327 l +140.962 58.176 l +141.408 58.032 l +142.142 58.032 l +142.582 58.176 l +142.877 58.327 l +143.172 58.622 l +143.316 58.918 l +143.316 59.508 l +143.172 59.796 l +142.877 60.091 l +142.582 60.242 l +142.142 60.386 l +141.408 60.386 l +140.962 60.242 l +140.666 60.091 l +140.371 59.796 l +140.227 59.508 l +140.227 58.918 l +140.227 61.358 m +143.316 61.358 l +140.227 61.358 m +140.227 62.683 l +140.371 63.130 l +140.522 63.274 l +140.818 63.425 l +141.113 63.425 l +141.408 63.274 l +141.552 63.130 l +141.696 62.683 l +141.696 61.358 l +141.696 62.388 m +143.316 63.425 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +149.306 25.502 m +149.155 25.798 l +148.860 26.093 l +148.572 26.237 l +147.982 26.237 l +147.686 26.093 l +147.391 25.798 l +147.240 25.502 l +147.096 25.056 l +147.096 24.322 l +147.240 23.882 l +147.391 23.587 l +147.686 23.292 l +147.982 23.148 l +148.572 23.148 l +148.860 23.292 l +149.155 23.587 l +149.306 23.882 l +149.306 24.322 l +148.572 24.322 m +149.306 24.322 l +150.278 26.237 m +150.278 23.148 l +150.278 26.237 m +152.338 23.148 l +152.338 26.237 m +152.338 23.148 l +153.310 26.237 m +153.310 23.148 l +153.310 26.237 m +154.339 26.237 l +154.786 26.093 l +155.081 25.798 l +155.225 25.502 l +155.376 25.056 l +155.376 24.322 l +155.225 23.882 l +155.081 23.587 l +154.786 23.292 l +154.339 23.148 l +153.310 23.148 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +83.016 141.077 m +83.016 137.988 l +83.988 141.077 m +83.988 137.988 l +83.988 141.077 m +86.047 137.988 l +86.047 141.077 m +86.047 137.988 l +87.019 141.077 m +87.019 137.988 l +87.019 141.077 m +88.344 141.077 l +88.790 140.933 l +88.934 140.782 l +89.086 140.486 l +89.086 140.047 l +88.934 139.752 l +88.790 139.608 l +88.344 139.457 l +87.019 139.457 l +90.058 141.077 m +90.058 138.866 l +90.202 138.427 l +90.497 138.132 l +90.936 137.988 l +91.231 137.988 l +91.678 138.132 l +91.973 138.427 l +92.117 138.866 l +92.117 141.077 l +94.118 141.077 m +94.118 137.988 l +93.089 141.077 m +95.148 141.077 l +98.388 140.486 m +98.683 140.638 l +99.130 141.077 l +99.130 137.988 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +113.976 141.077 m +113.976 137.988 l +114.948 141.077 m +114.948 137.988 l +114.948 141.077 m +117.007 137.988 l +117.007 141.077 m +117.007 137.988 l +117.979 141.077 m +117.979 137.988 l +117.979 141.077 m +119.304 141.077 l +119.750 140.933 l +119.894 140.782 l +120.046 140.486 l +120.046 140.047 l +119.894 139.752 l +119.750 139.608 l +119.304 139.457 l +117.979 139.457 l +121.018 141.077 m +121.018 138.866 l +121.162 138.427 l +121.457 138.132 l +121.896 137.988 l +122.191 137.988 l +122.638 138.132 l +122.933 138.427 l +123.077 138.866 l +123.077 141.077 l +125.078 141.077 m +125.078 137.988 l +124.049 141.077 m +126.108 141.077 l +129.499 140.342 m +129.499 140.486 l +129.643 140.782 l +129.794 140.933 l +130.090 141.077 l +130.680 141.077 l +130.968 140.933 l +131.119 140.782 l +131.263 140.486 l +131.263 140.191 l +131.119 139.896 l +130.824 139.457 l +129.348 137.988 l +131.414 137.988 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +8.829 24.769 m +11.917 24.769 l +8.829 24.769 m +11.917 26.829 l +8.829 26.829 m +11.917 26.829 l +9.563 30.011 m +9.268 29.867 l +8.973 29.572 l +8.829 29.277 l +8.829 28.686 l +8.973 28.391 l +9.268 28.096 l +9.563 27.952 l +10.002 27.801 l +10.744 27.801 l +11.183 27.952 l +11.478 28.096 l +11.773 28.391 l +11.917 28.686 l +11.917 29.277 l +11.773 29.572 l +11.478 29.867 l +11.183 30.011 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +157.831 159.797 m +159.451 159.797 l +158.566 158.616 l +159.012 158.616 l +159.300 158.472 l +159.451 158.328 l +159.595 157.882 l +159.595 157.586 l +159.451 157.147 l +159.156 156.852 l +158.717 156.708 l +158.270 156.708 l +157.831 156.852 l +157.680 156.996 l +157.536 157.291 l +160.567 159.797 m +161.748 156.708 l +162.929 159.797 m +161.748 156.708 l +164.196 159.797 m +165.816 159.797 l +164.930 158.616 l +165.370 158.616 l +165.665 158.472 l +165.816 158.328 l +165.960 157.882 l +165.960 157.586 l +165.816 157.147 l +165.521 156.852 l +165.074 156.708 l +164.635 156.708 l +164.196 156.852 l +164.045 156.996 l +163.901 157.291 l +169.200 159.797 m +169.200 156.708 l +169.200 159.797 m +170.525 159.797 l +170.964 159.653 l +171.115 159.502 l +171.259 159.206 l +171.259 158.911 l +171.115 158.616 l +170.964 158.472 l +170.525 158.328 l +169.200 158.328 l +170.230 158.328 m +171.259 156.708 l +172.231 159.797 m +172.231 156.708 l +172.231 159.797 m +174.146 159.797 l +172.231 158.328 m +173.412 158.328 l +172.231 156.708 m +174.146 156.708 l +175.118 159.797 m +175.118 156.708 l +175.118 159.797 m +177.034 159.797 l +175.118 158.328 m +176.299 158.328 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +129.816 104.717 m +130.997 101.628 l +132.170 104.717 m +130.997 101.628 l +133.142 104.717 m +133.142 102.506 l +133.294 102.067 l +133.589 101.772 l +134.028 101.628 l +134.323 101.628 l +134.762 101.772 l +135.058 102.067 l +135.209 102.506 l +135.209 104.717 l +138.240 104.278 m +137.945 104.573 l +137.506 104.717 l +136.915 104.717 l +136.476 104.573 l +136.181 104.278 l +136.181 103.982 l +136.325 103.687 l +136.476 103.536 l +136.764 103.392 l +137.650 103.097 l +137.945 102.953 l +138.096 102.802 l +138.240 102.506 l +138.240 102.067 l +137.945 101.772 l +137.506 101.628 l +136.915 101.628 l +136.476 101.772 l +136.181 102.067 l +139.212 104.717 m +139.212 101.628 l +139.212 104.717 m +140.537 104.717 l +140.976 104.573 l +141.127 104.422 l +141.271 104.126 l +141.271 103.831 l +141.127 103.536 l +140.976 103.392 l +140.537 103.248 l +139.212 103.248 m +140.537 103.248 l +140.976 103.097 l +141.127 102.953 l +141.271 102.658 l +141.271 102.211 l +141.127 101.916 l +140.976 101.772 l +140.537 101.628 l +139.212 101.628 l +144.511 104.717 m +144.511 101.628 l +145.483 104.717 m +145.483 101.628 l +145.483 104.717 m +147.550 101.628 l +147.550 104.717 m +147.550 101.628 l +148.522 104.717 m +149.695 101.628 l +150.876 104.717 m +149.695 101.628 l +151.848 104.717 m +151.848 101.628 l +151.848 104.717 m +153.763 104.717 l +151.848 103.248 m +153.029 103.248 l +151.848 101.628 m +153.763 101.628 l +154.735 104.717 m +154.735 101.628 l +154.735 104.717 m +156.060 104.717 l +156.499 104.573 l +156.650 104.422 l +156.794 104.126 l +156.794 103.831 l +156.650 103.536 l +156.499 103.392 l +156.060 103.248 l +154.735 103.248 l +155.765 103.248 m +156.794 101.628 l +158.796 104.717 m +158.796 101.628 l +157.766 104.717 m +159.833 104.717 l +160.805 104.717 m +160.805 101.628 l +160.805 104.717 m +162.720 104.717 l +160.805 103.248 m +161.978 103.248 l +160.805 101.628 m +162.720 101.628 l +163.692 104.717 m +163.692 101.628 l +163.692 104.717 m +165.017 104.717 l +165.456 104.573 l +165.600 104.422 l +165.751 104.126 l +165.751 103.831 l +165.600 103.536 l +165.456 103.392 l +165.017 103.248 l +163.692 103.248 l +164.722 103.248 m +165.751 101.628 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +43.416 66.917 m +43.416 63.828 l +43.416 63.828 m +45.180 63.828 l +47.038 66.917 m +46.742 66.773 l +46.447 66.478 l +46.303 66.182 l +46.152 65.736 l +46.152 65.002 l +46.303 64.562 l +46.447 64.267 l +46.742 63.972 l +47.038 63.828 l +47.628 63.828 l +47.923 63.972 l +48.218 64.267 l +48.362 64.562 l +48.514 65.002 l +48.514 65.736 l +48.362 66.182 l +48.218 66.478 l +47.923 66.773 l +47.628 66.917 l +47.038 66.917 l +49.486 66.917 m +50.220 63.828 l +50.954 66.917 m +50.220 63.828 l +50.954 66.917 m +51.696 63.828 l +52.430 66.917 m +51.696 63.828 l +55.670 66.917 m +55.670 63.828 l +55.670 66.917 m +56.995 66.917 l +57.434 66.773 l +57.586 66.622 l +57.730 66.326 l +57.730 65.887 l +57.586 65.592 l +57.434 65.448 l +56.995 65.297 l +55.670 65.297 l +59.882 66.917 m +58.702 63.828 l +59.882 66.917 m +61.056 63.828 l +59.148 64.858 m +60.617 64.858 l +64.094 66.478 m +63.799 66.773 l +63.360 66.917 l +62.770 66.917 l +62.323 66.773 l +62.028 66.478 l +62.028 66.182 l +62.179 65.887 l +62.323 65.736 l +62.618 65.592 l +63.504 65.297 l +63.799 65.153 l +63.943 65.002 l +64.094 64.706 l +64.094 64.267 l +63.799 63.972 l +63.360 63.828 l +62.770 63.828 l +62.323 63.972 l +62.028 64.267 l +67.126 66.478 m +66.830 66.773 l +66.391 66.917 l +65.801 66.917 l +65.362 66.773 l +65.066 66.478 l +65.066 66.182 l +65.210 65.887 l +65.362 65.736 l +65.657 65.592 l +66.535 65.297 l +66.830 65.153 l +66.982 65.002 l +67.126 64.706 l +67.126 64.267 l +66.830 63.972 l +66.391 63.828 l +65.801 63.828 l +65.362 63.972 l +65.066 64.267 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +49.536 62.597 m +49.536 59.508 l +49.536 62.597 m +51.451 62.597 l +49.536 61.128 m +50.717 61.128 l +52.423 62.597 m +52.423 59.508 l +53.395 62.597 m +53.395 59.508 l +53.395 59.508 m +55.159 59.508 l +57.168 62.597 m +57.168 59.508 l +56.131 62.597 m +58.198 62.597 l +59.170 62.597 m +59.170 59.508 l +59.170 62.597 m +61.085 62.597 l +59.170 61.128 m +60.343 61.128 l +59.170 59.508 m +61.085 59.508 l +62.057 62.597 m +62.057 59.508 l +62.057 62.597 m +63.382 62.597 l +63.821 62.453 l +63.972 62.302 l +64.116 62.006 l +64.116 61.711 l +63.972 61.416 l +63.821 61.272 l +63.382 61.128 l +62.057 61.128 l +63.086 61.128 m +64.116 59.508 l +67.147 62.158 m +66.852 62.453 l +66.413 62.597 l +65.822 62.597 l +65.383 62.453 l +65.088 62.158 l +65.088 61.862 l +65.232 61.567 l +65.383 61.416 l +65.678 61.272 l +66.564 60.977 l +66.852 60.833 l +67.003 60.682 l +67.147 60.386 l +67.147 59.947 l +66.852 59.652 l +66.413 59.508 l +65.822 59.508 l +65.383 59.652 l +65.088 59.947 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +170.107 77.688 m +173.196 78.869 l +170.107 80.042 m +173.196 78.869 l +170.107 81.014 m +172.318 81.014 l +172.757 81.166 l +173.052 81.461 l +173.196 81.900 l +173.196 82.195 l +173.052 82.634 l +172.757 82.930 l +172.318 83.081 l +170.107 83.081 l +170.546 86.112 m +170.251 85.817 l +170.107 85.378 l +170.107 84.787 l +170.251 84.348 l +170.546 84.053 l +170.842 84.053 l +171.137 84.197 l +171.288 84.348 l +171.432 84.636 l +171.727 85.522 l +171.871 85.817 l +172.022 85.968 l +172.318 86.112 l +172.757 86.112 l +173.052 85.817 l +173.196 85.378 l +173.196 84.787 l +173.052 84.348 l +172.757 84.053 l +170.107 87.084 m +173.196 87.084 l +170.107 87.084 m +170.107 88.409 l +170.251 88.848 l +170.402 88.999 l +170.698 89.143 l +170.993 89.143 l +171.288 88.999 l +171.432 88.848 l +171.576 88.409 l +171.576 87.084 m +171.576 88.409 l +171.727 88.848 l +171.871 88.999 l +172.166 89.143 l +172.613 89.143 l +172.908 88.999 l +173.052 88.848 l +173.196 88.409 l +173.196 87.084 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +34.416 70.459 m +34.416 73.548 l +34.416 70.459 m +33.091 70.459 l +32.652 70.603 l +32.501 70.754 l +32.357 71.050 l +32.357 71.345 l +32.501 71.640 l +32.652 71.784 l +33.091 71.928 l +34.416 71.928 l +33.386 71.928 m +32.357 73.548 l +31.385 71.050 m +31.090 70.898 l +30.643 70.459 l +30.643 73.548 l +29.671 71.050 m +29.376 70.898 l +28.937 70.459 l +28.937 73.548 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +30.427 87.768 m +33.516 87.768 l +30.427 87.768 m +30.427 89.093 l +30.571 89.532 l +30.722 89.683 l +31.018 89.827 l +31.313 89.827 l +31.608 89.683 l +31.752 89.532 l +31.896 89.093 l +31.896 87.768 l +31.896 88.798 m +33.516 89.827 l +31.018 90.799 m +30.866 91.094 l +30.427 91.541 l +33.516 91.541 l +31.162 92.657 m +31.018 92.657 l +30.722 92.808 l +30.571 92.952 l +30.427 93.247 l +30.427 93.838 l +30.571 94.133 l +30.722 94.277 l +31.018 94.428 l +31.313 94.428 l +31.608 94.277 l +32.047 93.982 l +33.516 92.513 l +33.516 94.572 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +39.456 109.397 m +39.456 106.308 l +39.456 109.397 m +40.781 109.397 l +41.220 109.253 l +41.371 109.102 l +41.515 108.806 l +41.515 108.511 l +41.371 108.216 l +41.220 108.072 l +40.781 107.928 l +39.456 107.928 l +40.486 107.928 m +41.515 106.308 l +42.487 108.806 m +42.782 108.958 l +43.229 109.397 l +43.229 106.308 l +44.496 109.397 m +46.116 109.397 l +45.230 108.216 l +45.670 108.216 l +45.965 108.072 l +46.116 107.928 l +46.260 107.482 l +46.260 107.186 l +46.116 106.747 l +45.821 106.452 l +45.374 106.308 l +44.935 106.308 l +44.496 106.452 l +44.345 106.596 l +44.201 106.891 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +56.347 87.048 m +59.436 87.048 l +56.347 87.048 m +56.347 88.373 l +56.491 88.812 l +56.642 88.963 l +56.938 89.107 l +57.233 89.107 l +57.528 88.963 l +57.672 88.812 l +57.816 88.373 l +57.816 87.048 l +57.816 88.078 m +59.436 89.107 l +56.938 90.079 m +56.786 90.374 l +56.347 90.821 l +59.436 90.821 l +56.347 93.262 m +58.406 91.793 l +58.406 93.996 l +56.347 93.262 m +59.436 93.262 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +76.176 108.677 m +76.176 105.588 l +76.176 108.677 m +77.501 108.677 l +77.940 108.533 l +78.091 108.382 l +78.235 108.086 l +78.235 107.791 l +78.091 107.496 l +77.940 107.352 l +77.501 107.208 l +76.176 107.208 l +77.206 107.208 m +78.235 105.588 l +79.207 108.086 m +79.502 108.238 l +79.949 108.677 l +79.949 105.588 l +82.685 108.677 m +81.216 108.677 l +81.065 107.352 l +81.216 107.496 l +81.655 107.647 l +82.094 107.647 l +82.541 107.496 l +82.836 107.208 l +82.980 106.762 l +82.980 106.466 l +82.836 106.027 l +82.541 105.732 l +82.094 105.588 l +81.655 105.588 l +81.216 105.732 l +81.065 105.876 l +80.921 106.171 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +85.925 83.088 m +82.836 83.088 l +85.925 83.088 m +85.925 81.763 l +85.781 81.324 l +85.630 81.173 l +85.334 81.029 l +85.039 81.029 l +84.744 81.173 l +84.600 81.324 l +84.456 81.763 l +84.456 83.088 l +84.456 82.058 m +82.836 81.029 l +85.334 80.057 m +85.486 79.762 l +85.925 79.315 l +82.836 79.315 l +85.486 76.579 m +85.781 76.723 l +85.925 77.170 l +85.925 77.465 l +85.781 77.904 l +85.334 78.199 l +84.600 78.343 l +83.866 78.343 l +83.275 78.199 l +82.980 77.904 l +82.836 77.465 l +82.836 77.314 l +82.980 76.874 l +83.275 76.579 l +83.714 76.428 l +83.866 76.428 l +84.305 76.579 l +84.600 76.874 l +84.744 77.314 l +84.744 77.465 l +84.600 77.904 l +84.305 78.199 l +83.866 78.343 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +110.736 111.197 m +110.736 108.108 l +110.736 111.197 m +112.061 111.197 l +112.500 111.053 l +112.651 110.902 l +112.795 110.606 l +112.795 110.311 l +112.651 110.016 l +112.500 109.872 l +112.061 109.728 l +110.736 109.728 l +111.766 109.728 m +112.795 108.108 l +113.767 110.606 m +114.062 110.758 l +114.509 111.197 l +114.509 108.108 l +117.396 110.167 m +117.245 109.728 l +116.950 109.433 l +116.510 109.282 l +116.359 109.282 l +115.920 109.433 l +115.625 109.728 l +115.481 110.167 l +115.481 110.311 l +115.625 110.758 l +115.920 111.053 l +116.359 111.197 l +116.510 111.197 l +116.950 111.053 l +117.245 110.758 l +117.396 110.167 l +117.396 109.433 l +117.245 108.691 l +116.950 108.252 l +116.510 108.108 l +116.215 108.108 l +115.776 108.252 l +115.625 108.547 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +110.736 104.357 m +110.736 101.268 l +110.736 104.357 m +112.061 104.357 l +112.500 104.213 l +112.651 104.062 l +112.795 103.766 l +112.795 103.471 l +112.651 103.176 l +112.500 103.032 l +112.061 102.888 l +110.736 102.888 l +111.766 102.888 m +112.795 101.268 l +113.918 103.622 m +113.918 103.766 l +114.062 104.062 l +114.214 104.213 l +114.509 104.357 l +115.092 104.357 l +115.387 104.213 l +115.538 104.062 l +115.682 103.766 l +115.682 103.471 l +115.538 103.176 l +115.243 102.737 l +113.767 101.268 l +115.834 101.268 l +117.684 104.357 m +117.245 104.213 l +116.950 103.766 l +116.806 103.032 l +116.806 102.593 l +116.950 101.851 l +117.245 101.412 l +117.684 101.268 l +117.979 101.268 l +118.426 101.412 l +118.721 101.851 l +118.865 102.593 l +118.865 103.032 l +118.721 103.766 l +118.426 104.213 l +117.979 104.357 l +117.684 104.357 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +117.965 91.728 m +114.876 91.728 l +117.965 91.728 m +117.965 90.403 l +117.821 89.964 l +117.670 89.813 l +117.374 89.669 l +117.079 89.669 l +116.784 89.813 l +116.640 89.964 l +116.496 90.403 l +116.496 91.728 l +116.496 90.698 m +114.876 89.669 l +117.230 88.546 m +117.374 88.546 l +117.670 88.402 l +117.821 88.250 l +117.965 87.955 l +117.965 87.372 l +117.821 87.077 l +117.670 86.926 l +117.374 86.782 l +117.079 86.782 l +116.784 86.926 l +116.345 87.221 l +114.876 88.697 l +114.876 86.630 l +117.374 85.658 m +117.526 85.363 l +117.965 84.924 l +114.876 84.924 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +173.736 133.877 m +173.736 131.666 l +173.880 131.227 l +174.175 130.932 l +174.622 130.788 l +174.917 130.788 l +175.356 130.932 l +175.651 131.227 l +175.795 131.666 l +175.795 133.877 l +178.538 133.438 m +178.387 133.733 l +177.948 133.877 l +177.653 133.877 l +177.214 133.733 l +176.918 133.286 l +176.767 132.552 l +176.767 131.818 l +176.918 131.227 l +177.214 130.932 l +177.653 130.788 l +177.804 130.788 l +178.243 130.932 l +178.538 131.227 l +178.682 131.666 l +178.682 131.818 l +178.538 132.257 l +178.243 132.552 l +177.804 132.696 l +177.653 132.696 l +177.214 132.552 l +176.918 132.257 l +176.767 131.818 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +51.667 85.608 m +53.878 85.608 l +54.317 85.752 l +54.612 86.047 l +54.756 86.494 l +54.756 86.789 l +54.612 87.228 l +54.317 87.523 l +53.878 87.667 l +51.667 87.667 l +52.402 88.790 m +52.258 88.790 l +51.962 88.934 l +51.811 89.086 l +51.667 89.381 l +51.667 89.964 l +51.811 90.259 l +51.962 90.410 l +52.258 90.554 l +52.553 90.554 l +52.848 90.410 l +53.287 90.115 l +54.756 88.639 l +54.756 90.706 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +61.027 85.608 m +63.238 85.608 l +63.677 85.752 l +63.972 86.047 l +64.116 86.494 l +64.116 86.789 l +63.972 87.228 l +63.677 87.523 l +63.238 87.667 l +61.027 87.667 l +61.027 88.934 m +61.027 90.554 l +62.208 89.676 l +62.208 90.115 l +62.352 90.410 l +62.496 90.554 l +62.942 90.706 l +63.238 90.706 l +63.677 90.554 l +63.972 90.259 l +64.116 89.820 l +64.116 89.381 l +63.972 88.934 l +63.828 88.790 l +63.533 88.639 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +89.827 85.608 m +92.038 85.608 l +92.477 85.752 l +92.772 86.047 l +92.916 86.494 l +92.916 86.789 l +92.772 87.228 l +92.477 87.523 l +92.038 87.667 l +89.827 87.667 l +89.827 90.115 m +91.886 88.639 l +91.886 90.850 l +89.827 90.115 m +92.916 90.115 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +120.067 26.208 m +123.156 26.208 l +120.067 28.267 m +123.156 28.267 l +121.536 26.208 m +121.536 28.267 l +120.067 30.715 m +122.126 29.239 l +122.126 31.450 l +120.067 30.715 m +123.156 30.715 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +169.416 123.019 m +169.416 126.108 l +169.416 123.019 m +168.091 123.019 l +167.652 123.163 l +167.501 123.314 l +167.357 123.610 l +167.357 123.905 l +167.501 124.200 l +167.652 124.344 l +168.091 124.488 l +169.416 124.488 l +168.386 124.488 m +167.357 126.108 l +166.090 123.019 m +164.470 123.019 l +165.348 124.200 l +164.909 124.200 l +164.614 124.344 l +164.470 124.488 l +164.318 124.934 l +164.318 125.230 l +164.470 125.669 l +164.765 125.964 l +165.204 126.108 l +165.643 126.108 l +166.090 125.964 l +166.234 125.820 l +166.385 125.525 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +77.256 172.757 m +77.256 169.668 l +77.256 172.757 m +78.581 172.757 l +79.020 172.613 l +79.171 172.462 l +79.315 172.166 l +79.315 171.871 l +79.171 171.576 l +79.020 171.432 l +78.581 171.288 l +77.256 171.288 l +78.286 171.288 m +79.315 169.668 l +80.287 172.166 m +80.582 172.318 l +81.029 172.757 l +81.029 169.668 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +108.576 172.757 m +108.576 169.668 l +108.576 172.757 m +109.901 172.757 l +110.340 172.613 l +110.491 172.462 l +110.635 172.166 l +110.635 171.871 l +110.491 171.576 l +110.340 171.432 l +109.901 171.288 l +108.576 171.288 l +109.606 171.288 m +110.635 169.668 l +111.758 172.022 m +111.758 172.166 l +111.902 172.462 l +112.054 172.613 l +112.349 172.757 l +112.932 172.757 l +113.227 172.613 l +113.378 172.462 l +113.522 172.166 l +113.522 171.871 l +113.378 171.576 l +113.083 171.137 l +111.607 169.668 l +113.674 169.668 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +165.470 86.998 m +165.766 87.149 l +166.061 87.444 l +166.205 87.732 l +166.205 88.322 l +166.061 88.618 l +165.766 88.913 l +165.470 89.064 l +165.024 89.208 l +164.290 89.208 l +163.850 89.064 l +163.555 88.913 l +163.260 88.618 l +163.116 88.322 l +163.116 87.732 l +163.260 87.444 l +163.555 87.149 l +163.850 86.998 l +165.614 86.026 m +165.766 85.730 l +166.205 85.291 l +163.116 85.291 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +132.322 78.818 m +132.026 78.667 l +131.731 78.372 l +131.587 78.084 l +131.587 77.494 l +131.731 77.198 l +132.026 76.903 l +132.322 76.752 l +132.768 76.608 l +133.502 76.608 l +133.942 76.752 l +134.237 76.903 l +134.532 77.198 l +134.676 77.494 l +134.676 78.084 l +134.532 78.372 l +134.237 78.667 l +133.942 78.818 l +132.322 79.934 m +132.178 79.934 l +131.882 80.086 l +131.731 80.230 l +131.587 80.525 l +131.587 81.115 l +131.731 81.410 l +131.882 81.554 l +132.178 81.706 l +132.473 81.706 l +132.768 81.554 l +133.207 81.259 l +134.676 79.790 l +134.676 81.850 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +144.266 98.222 m +144.115 98.518 l +143.820 98.813 l +143.532 98.957 l +142.942 98.957 l +142.646 98.813 l +142.351 98.518 l +142.200 98.222 l +142.056 97.776 l +142.056 97.042 l +142.200 96.602 l +142.351 96.307 l +142.646 96.012 l +142.942 95.868 l +143.532 95.868 l +143.820 96.012 l +144.115 96.307 l +144.266 96.602 l +145.534 98.957 m +147.154 98.957 l +146.268 97.776 l +146.707 97.776 l +147.002 97.632 l +147.154 97.488 l +147.298 97.042 l +147.298 96.746 l +147.154 96.307 l +146.858 96.012 l +146.412 95.868 l +145.973 95.868 l +145.534 96.012 l +145.382 96.156 l +145.238 96.451 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +150.336 74.779 m +150.336 76.990 l +150.192 77.429 l +149.897 77.724 l +149.450 77.868 l +149.155 77.868 l +148.716 77.724 l +148.421 77.429 l +148.277 76.990 l +148.277 74.779 l +147.305 75.370 m +147.010 75.218 l +146.563 74.779 l +146.563 77.868 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +158.587 134.928 m +161.676 134.928 l +158.587 134.928 m +158.587 136.253 l +158.731 136.692 l +158.882 136.843 l +159.178 136.987 l +159.473 136.987 l +159.768 136.843 l +159.912 136.692 l +160.056 136.253 l +160.056 134.928 l +160.056 135.958 m +161.676 136.987 l +158.587 139.435 m +160.646 137.959 l +160.646 140.170 l +158.587 139.435 m +161.676 139.435 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +38.016 158.357 m +38.016 155.268 l +38.016 158.357 m +39.341 158.357 l +39.780 158.213 l +39.931 158.062 l +40.075 157.766 l +40.075 157.471 l +39.931 157.176 l +39.780 157.032 l +39.341 156.888 l +38.016 156.888 l +39.046 156.888 m +40.075 155.268 l +42.818 157.918 m +42.667 158.213 l +42.228 158.357 l +41.933 158.357 l +41.494 158.213 l +41.198 157.766 l +41.047 157.032 l +41.047 156.298 l +41.198 155.707 l +41.494 155.412 l +41.933 155.268 l +42.084 155.268 l +42.523 155.412 l +42.818 155.707 l +42.962 156.146 l +42.962 156.298 l +42.818 156.737 l +42.523 157.032 l +42.084 157.176 l +41.933 157.176 l +41.494 157.032 l +41.198 156.737 l +41.047 156.298 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +38.016 168.797 m +38.016 165.708 l +38.016 168.797 m +39.341 168.797 l +39.780 168.653 l +39.931 168.502 l +40.075 168.206 l +40.075 167.911 l +39.931 167.616 l +39.780 167.472 l +39.341 167.328 l +38.016 167.328 l +39.046 167.328 m +40.075 165.708 l +43.114 168.797 m +41.638 165.708 l +41.047 168.797 m +43.114 168.797 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +38.016 172.757 m +38.016 169.668 l +38.016 172.757 m +39.341 172.757 l +39.780 172.613 l +39.931 172.461 l +40.075 172.166 l +40.075 171.871 l +39.931 171.576 l +39.780 171.432 l +39.341 171.288 l +38.016 171.288 l +39.046 171.288 m +40.075 169.668 l +41.789 172.757 m +41.343 172.613 l +41.199 172.317 l +41.199 172.022 l +41.343 171.727 l +41.638 171.576 l +42.228 171.432 l +42.667 171.288 l +42.963 170.993 l +43.114 170.697 l +43.114 170.251 l +42.963 169.956 l +42.819 169.812 l +42.372 169.668 l +41.789 169.668 l +41.343 169.812 l +41.199 169.956 l +41.047 170.251 l +41.047 170.697 l +41.199 170.993 l +41.494 171.288 l +41.933 171.432 l +42.523 171.576 l +42.819 171.727 l +42.963 172.022 l +42.963 172.317 l +42.819 172.613 l +42.372 172.757 l +41.789 172.757 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +29.347 53.208 m +32.436 53.208 l +29.347 53.208 m +29.347 54.533 l +29.491 54.972 l +29.642 55.123 l +29.938 55.267 l +30.233 55.267 l +30.528 55.123 l +30.672 54.972 l +30.816 54.533 l +30.816 53.208 l +30.816 54.238 m +32.436 55.267 l +29.938 56.239 m +29.786 56.534 l +29.347 56.981 l +32.436 56.981 l +29.347 58.831 m +29.491 58.392 l +29.938 58.097 l +30.672 57.953 l +31.111 57.953 l +31.853 58.097 l +32.292 58.392 l +32.436 58.831 l +32.436 59.126 l +32.292 59.573 l +31.853 59.868 l +31.111 60.012 l +30.672 60.012 l +29.938 59.868 l +29.491 59.573 l +29.347 59.126 l +29.347 58.831 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +79.416 74.477 m +79.416 71.388 l +79.416 74.477 m +80.741 74.477 l +81.180 74.333 l +81.331 74.182 l +81.475 73.886 l +81.475 73.591 l +81.331 73.296 l +81.180 73.152 l +80.741 73.008 l +79.416 73.008 l +80.446 73.008 m +81.475 71.388 l +82.447 73.886 m +82.742 74.038 l +83.189 74.477 l +83.189 71.388 l +86.220 74.477 m +84.744 71.388 l +84.161 74.477 m +86.220 74.477 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +70.747 57.528 m +73.836 57.528 l +70.747 57.528 m +70.747 58.853 l +70.891 59.292 l +71.042 59.443 l +71.338 59.587 l +71.633 59.587 l +71.928 59.443 l +72.072 59.292 l +72.216 58.853 l +72.216 57.528 l +72.216 58.558 m +73.836 59.587 l +71.338 60.559 m +71.186 60.854 l +70.747 61.301 l +73.836 61.301 l +70.747 63.007 m +70.891 62.568 l +71.186 62.417 l +71.482 62.417 l +71.777 62.568 l +71.928 62.856 l +72.072 63.446 l +72.216 63.893 l +72.511 64.188 l +72.806 64.332 l +73.253 64.332 l +73.548 64.188 l +73.692 64.037 l +73.836 63.598 l +73.836 63.007 l +73.692 62.568 l +73.548 62.417 l +73.253 62.273 l +72.806 62.273 l +72.511 62.417 l +72.216 62.712 l +72.072 63.151 l +71.928 63.742 l +71.777 64.037 l +71.482 64.188 l +71.186 64.188 l +70.891 64.037 l +70.747 63.598 l +70.747 63.007 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +108.216 74.837 m +108.216 71.748 l +108.216 74.837 m +109.541 74.837 l +109.980 74.693 l +110.131 74.542 l +110.275 74.246 l +110.275 73.951 l +110.131 73.656 l +109.980 73.512 l +109.541 73.368 l +108.216 73.368 l +109.246 73.368 m +110.275 71.748 l +111.398 74.102 m +111.398 74.246 l +111.542 74.542 l +111.694 74.693 l +111.989 74.837 l +112.572 74.837 l +112.867 74.693 l +113.018 74.542 l +113.162 74.246 l +113.162 73.951 l +113.018 73.656 l +112.723 73.217 l +111.247 71.748 l +113.314 71.748 l +114.430 74.102 m +114.430 74.246 l +114.581 74.542 l +114.725 74.693 l +115.020 74.837 l +115.610 74.837 l +115.906 74.693 l +116.050 74.542 l +116.201 74.246 l +116.201 73.951 l +116.050 73.656 l +115.754 73.217 l +114.286 71.748 l +116.345 71.748 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +99.547 57.168 m +102.636 57.168 l +99.547 57.168 m +99.547 58.493 l +99.691 58.932 l +99.842 59.083 l +100.138 59.227 l +100.433 59.227 l +100.728 59.083 l +100.872 58.932 l +101.016 58.493 l +101.016 57.168 l +101.016 58.198 m +102.636 59.227 l +100.282 60.350 m +100.138 60.350 l +99.842 60.494 l +99.691 60.646 l +99.547 60.941 l +99.547 61.524 l +99.691 61.819 l +99.842 61.970 l +100.138 62.114 l +100.433 62.114 l +100.728 61.970 l +101.167 61.675 l +102.636 60.199 l +102.636 62.266 l +99.547 63.533 m +99.547 65.153 l +100.728 64.267 l +100.728 64.706 l +100.872 65.002 l +101.016 65.153 l +101.462 65.297 l +101.758 65.297 l +102.197 65.153 l +102.492 64.858 l +102.636 64.411 l +102.636 63.972 l +102.492 63.533 l +102.348 63.382 l +102.053 63.238 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +175.226 153.302 m +175.075 153.598 l +174.780 153.893 l +174.492 154.037 l +173.902 154.037 l +173.606 153.893 l +173.311 153.598 l +173.160 153.302 l +173.016 152.856 l +173.016 152.122 l +173.160 151.682 l +173.311 151.387 l +173.606 151.092 l +173.902 150.948 l +174.492 150.948 l +174.780 151.092 l +175.075 151.387 l +175.226 151.682 l +177.667 154.037 m +176.198 151.978 l +178.409 151.978 l +177.667 154.037 m +177.667 150.948 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +90.230 59.638 m +90.526 59.789 l +90.821 60.084 l +90.965 60.372 l +90.965 60.962 l +90.821 61.258 l +90.526 61.553 l +90.230 61.704 l +89.784 61.848 l +89.050 61.848 l +88.610 61.704 l +88.315 61.553 l +88.020 61.258 l +87.876 60.962 l +87.876 60.372 l +88.020 60.084 l +88.315 59.789 l +88.610 59.638 l +90.965 56.902 m +90.965 58.370 l +89.640 58.522 l +89.784 58.370 l +89.935 57.931 l +89.935 57.492 l +89.784 57.046 l +89.496 56.750 l +89.050 56.606 l +88.754 56.606 l +88.315 56.750 l +88.020 57.046 l +87.876 57.492 l +87.876 57.931 l +88.020 58.370 l +88.164 58.522 l +88.459 58.666 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +117.590 59.638 m +117.886 59.789 l +118.181 60.084 l +118.325 60.372 l +118.325 60.962 l +118.181 61.258 l +117.886 61.553 l +117.590 61.704 l +117.144 61.848 l +116.410 61.848 l +115.970 61.704 l +115.675 61.553 l +115.380 61.258 l +115.236 60.962 l +115.236 60.372 l +115.380 60.084 l +115.675 59.789 l +115.970 59.638 l +117.886 56.902 m +118.181 57.046 l +118.325 57.492 l +118.325 57.780 l +118.181 58.226 l +117.734 58.522 l +117.000 58.666 l +116.266 58.666 l +115.675 58.522 l +115.380 58.226 l +115.236 57.780 l +115.236 57.636 l +115.380 57.197 l +115.675 56.902 l +116.114 56.750 l +116.266 56.750 l +116.705 56.902 l +117.000 57.197 l +117.144 57.636 l +117.144 57.780 l +117.000 58.226 l +116.705 58.522 l +116.266 58.666 l +S +1 J +1 j +0.23 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +50.073 158.839 m +48.222 158.839 l +49.144 159.768 m +49.144 157.910 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +44.028 7.589 m +45.209 10.678 l +44.028 7.589 m +42.854 10.678 l +44.770 9.648 m +43.294 9.648 l +41.882 7.589 m +41.882 9.799 l +41.731 10.238 l +41.436 10.534 l +40.997 10.678 l +40.702 10.678 l +40.262 10.534 l +39.967 10.238 l +39.816 9.799 l +39.816 7.589 l +38.844 7.589 m +38.844 10.678 l +38.844 7.589 m +37.814 7.589 l +37.375 7.733 l +37.080 8.028 l +36.929 8.323 l +36.785 8.770 l +36.785 9.504 l +36.929 9.943 l +37.080 10.238 l +37.375 10.534 l +37.814 10.678 l +38.844 10.678 l +35.813 7.589 m +35.813 10.678 l +33.955 7.589 m +34.250 7.733 l +34.546 8.028 l +34.697 8.323 l +34.841 8.770 l +34.841 9.504 l +34.697 9.943 l +34.546 10.238 l +34.250 10.534 l +33.955 10.678 l +33.365 10.678 l +33.077 10.534 l +32.782 10.238 l +32.630 9.943 l +32.486 9.504 l +32.486 8.770 l +32.630 8.323 l +32.782 8.028 l +33.077 7.733 l +33.365 7.589 l +33.955 7.589 l +31.514 8.179 m +31.219 8.028 l +30.773 7.589 l +30.773 10.678 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +70.668 7.229 m +71.849 10.318 l +70.668 7.229 m +69.494 10.318 l +71.410 9.288 m +69.934 9.288 l +68.522 7.229 m +68.522 9.439 l +68.371 9.878 l +68.076 10.174 l +67.637 10.318 l +67.342 10.318 l +66.902 10.174 l +66.607 9.878 l +66.456 9.439 l +66.456 7.229 l +65.484 7.229 m +65.484 10.318 l +65.484 7.229 m +64.454 7.229 l +64.015 7.373 l +63.720 7.668 l +63.569 7.963 l +63.425 8.410 l +63.425 9.144 l +63.569 9.583 l +63.720 9.878 l +64.015 10.174 l +64.454 10.318 l +65.484 10.318 l +62.453 7.229 m +62.453 10.318 l +60.595 7.229 m +60.890 7.373 l +61.186 7.668 l +61.337 7.963 l +61.481 8.410 l +61.481 9.144 l +61.337 9.583 l +61.186 9.878 l +60.890 10.174 l +60.595 10.318 l +60.005 10.318 l +59.717 10.174 l +59.422 9.878 l +59.270 9.583 l +59.126 9.144 l +59.126 8.410 l +59.270 7.963 l +59.422 7.668 l +59.717 7.373 l +60.005 7.229 l +60.595 7.229 l +58.003 7.963 m +58.003 7.819 l +57.859 7.524 l +57.708 7.373 l +57.413 7.229 l +56.830 7.229 l +56.534 7.373 l +56.383 7.524 l +56.239 7.819 l +56.239 8.114 l +56.383 8.410 l +56.678 8.849 l +58.154 10.318 l +56.088 10.318 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +98.388 7.229 m +99.569 10.318 l +98.388 7.229 m +97.214 10.318 l +99.130 9.288 m +97.654 9.288 l +96.242 7.229 m +96.242 9.439 l +96.091 9.878 l +95.796 10.174 l +95.357 10.318 l +95.062 10.318 l +94.622 10.174 l +94.327 9.878 l +94.176 9.439 l +94.176 7.229 l +93.204 7.229 m +93.204 10.318 l +93.204 7.229 m +92.174 7.229 l +91.735 7.373 l +91.440 7.668 l +91.289 7.963 l +91.145 8.410 l +91.145 9.144 l +91.289 9.583 l +91.440 9.878 l +91.735 10.174 l +92.174 10.318 l +93.204 10.318 l +90.173 7.229 m +90.173 10.318 l +88.315 7.229 m +88.610 7.373 l +88.906 7.668 l +89.057 7.963 l +89.201 8.410 l +89.201 9.144 l +89.057 9.583 l +88.906 9.878 l +88.610 10.174 l +88.315 10.318 l +87.725 10.318 l +87.437 10.174 l +87.142 9.878 l +86.990 9.583 l +86.846 9.144 l +86.846 8.410 l +86.990 7.963 l +87.142 7.668 l +87.437 7.373 l +87.725 7.229 l +88.315 7.229 l +85.579 7.229 m +83.959 7.229 l +84.845 8.410 l +84.398 8.410 l +84.103 8.554 l +83.959 8.698 l +83.808 9.144 l +83.808 9.439 l +83.959 9.878 l +84.254 10.174 l +84.694 10.318 l +85.133 10.318 l +85.579 10.174 l +85.723 10.030 l +85.874 9.734 l +S +1 J +1 j +0.43 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +183.427 75.528 m +185.638 75.528 l +186.077 75.672 l +186.372 75.967 l +186.516 76.414 l +186.516 76.709 l +186.372 77.148 l +186.077 77.443 l +185.638 77.587 l +183.427 77.587 l +183.866 80.626 m +183.571 80.330 l +183.427 79.884 l +183.427 79.301 l +183.571 78.854 l +183.866 78.559 l +184.162 78.559 l +184.457 78.710 l +184.608 78.854 l +184.752 79.150 l +185.047 80.035 l +185.191 80.330 l +185.342 80.474 l +185.638 80.626 l +186.077 80.626 l +186.372 80.330 l +186.516 79.884 l +186.516 79.301 l +186.372 78.854 l +186.077 78.559 l +183.427 81.598 m +186.516 81.598 l +183.427 81.598 m +183.427 82.922 l +183.571 83.362 l +183.722 83.513 l +184.018 83.657 l +184.313 83.657 l +184.608 83.513 l +184.752 83.362 l +184.896 82.922 l +184.896 81.598 m +184.896 82.922 l +185.047 83.362 l +185.191 83.513 l +185.486 83.657 l +185.933 83.657 l +186.228 83.513 l +186.372 83.362 l +186.516 82.922 l +186.516 81.598 l +184.018 84.629 m +183.866 84.924 l +183.427 85.363 l +186.516 85.363 l +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +90.938 154.224 m +93.06 154.24 94.76 155.98 94.74 158.10 c +94.72 160.22 92.98 161.92 90.87 161.90 c +88.75 161.88 87.05 160.14 87.07 158.02 c +87.08 155.93 88.77 154.24 90.87 154.22 c +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +122.258 154.224 m +124.38 154.24 126.08 155.98 126.06 158.10 c +126.04 160.22 124.30 161.92 122.19 161.90 c +120.07 161.88 118.37 160.14 118.39 158.02 c +118.40 155.93 120.09 154.24 122.19 154.22 c +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +161.206 89.232 m +161.69 89.23 162.08 88.84 162.08 88.35 c +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +158.060 88.354 m +158.06 88.84 158.45 89.23 158.94 89.23 c +158.94 89.23 158.94 89.23 158.94 89.23 c +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +162.068 82.186 m +162.07 81.70 161.67 81.31 161.19 81.31 c +161.19 81.31 161.19 81.31 161.19 81.31 c +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +158.922 81.308 m +158.44 81.31 158.04 81.70 158.04 82.19 c +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +136.586 76.944 m +136.10 76.94 135.71 77.34 135.71 77.82 c +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +139.732 77.822 m +139.73 77.34 139.34 76.94 138.85 76.94 c +138.85 76.94 138.85 76.94 138.85 76.94 c +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +135.724 83.990 m +135.72 84.47 136.12 84.87 136.60 84.87 c +136.60 84.87 136.60 84.87 136.60 84.87 c +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +138.870 84.868 m +139.36 84.87 139.75 84.47 139.75 83.99 c +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +142.392 93.958 m +142.39 94.44 142.79 94.84 143.27 94.84 c +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +143.270 90.812 m +142.79 90.81 142.39 91.21 142.39 91.69 c +142.39 91.69 142.39 91.69 142.39 91.69 c +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +149.438 94.820 m +149.92 94.82 150.32 94.43 150.32 93.94 c +150.32 93.94 150.32 93.94 150.32 93.94 c +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +150.316 91.674 m +150.32 91.19 149.92 90.80 149.44 90.80 c +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +180.960 146.738 m +180.96 146.25 180.57 145.86 180.08 145.86 c +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +180.082 149.884 m +180.57 149.88 180.96 149.49 180.96 149.01 c +180.96 149.01 180.96 149.01 180.96 149.01 c +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +173.914 145.876 m +173.43 145.88 173.04 146.27 173.04 146.75 c +173.04 146.75 173.04 146.75 173.04 146.75 c +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +173.036 149.022 m +173.04 149.51 173.43 149.90 173.91 149.90 c +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +85.966 61.872 m +86.45 61.87 86.84 61.48 86.84 60.99 c +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +82.820 60.994 m +82.82 61.48 83.21 61.87 83.70 61.87 c +83.70 61.87 83.70 61.87 83.70 61.87 c +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +86.828 54.826 m +86.83 54.34 86.43 53.95 85.95 53.95 c +85.95 53.95 85.95 53.95 85.95 53.95 c +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +83.682 53.948 m +83.20 53.95 82.80 54.34 82.80 54.83 c +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +113.326 61.872 m +113.81 61.87 114.20 61.48 114.20 60.99 c +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +110.180 60.994 m +110.18 61.48 110.57 61.87 111.06 61.87 c +111.06 61.87 111.06 61.87 111.06 61.87 c +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +114.188 54.826 m +114.19 54.34 113.79 53.95 113.31 53.95 c +113.31 53.95 113.31 53.95 113.31 53.95 c +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +111.042 53.948 m +110.56 53.95 110.16 54.34 110.16 54.83 c +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +201.648 72.806 m +201.80 72.81 201.93 72.93 201.93 73.09 c +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +200.656 73.056 m +200.64 73.20 200.52 73.30 200.38 73.30 c +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +197.963 73.586 m +197.96 73.43 198.09 73.30 198.25 73.30 c +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +198.247 75.145 m +198.09 75.14 197.96 75.02 197.96 74.86 c +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +200.375 75.145 m +200.52 75.15 200.64 75.25 200.66 75.39 c +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +200.659 73.084 m +200.66 72.93 200.79 72.80 200.94 72.80 c +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +201.929 75.360 m +201.93 75.52 201.80 75.64 201.65 75.64 c +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +200.942 75.638 m +200.79 75.64 200.66 75.51 200.66 75.35 c +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +201.504 84.542 m +201.66 84.54 201.79 84.67 201.79 84.83 c +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +200.512 84.792 m +200.49 84.93 200.37 85.04 200.23 85.04 c +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +197.819 85.322 m +197.82 85.17 197.95 85.04 198.10 85.04 c +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +198.103 86.881 m +197.95 86.88 197.82 86.75 197.82 86.60 c +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +200.231 86.881 m +200.37 86.88 200.50 86.99 200.51 87.13 c +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +200.515 84.820 m +200.51 84.66 200.64 84.54 200.80 84.54 c +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +201.785 87.096 m +201.78 87.25 201.66 87.38 201.50 87.38 c +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +200.798 87.374 m +200.64 87.37 200.51 87.25 200.51 87.09 c +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +156.80 155.45 26.14 -34.20 re +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +129.82 100.37 37.80 -27.36 re +S +1 J +1 j +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +68.26 66.89 51.48 -14.04 re +S +1.70 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +13.44 169.85 m 13.44 170.79 12.68 171.55 11.74 171.55 c +10.80 171.55 10.04 170.79 10.04 169.85 c +10.04 168.91 10.80 168.15 11.74 168.15 c +12.68 168.15 13.44 168.91 13.44 169.85 c +S +0.85 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +38.44 85.95 m 38.44 86.18 38.25 86.37 38.02 86.37 c +37.78 86.37 37.59 86.18 37.59 85.95 c +37.59 85.71 37.78 85.52 38.02 85.52 c +38.25 85.52 38.44 85.71 38.44 85.95 c +S +0.85 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +36.33 80.27 m 36.33 80.50 36.13 80.69 35.90 80.69 c +35.66 80.69 35.47 80.50 35.47 80.27 c +35.47 80.03 35.66 79.84 35.90 79.84 c +36.13 79.84 36.33 80.03 36.33 80.27 c +S +0.85 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +78.04 89.95 m 78.04 90.18 77.85 90.37 77.62 90.37 c +77.38 90.37 77.19 90.18 77.19 89.95 c +77.19 89.71 77.38 89.52 77.62 89.52 c +77.85 89.52 78.04 89.71 78.04 89.95 c +S +0.85 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +80.16 95.63 m 80.16 95.86 79.97 96.05 79.73 96.05 c +79.50 96.05 79.31 95.86 79.31 95.63 c +79.31 95.39 79.50 95.20 79.73 95.20 c +79.97 95.20 80.16 95.39 80.16 95.63 c +S +0.85 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +106.84 90.31 m 106.84 90.54 106.65 90.73 106.42 90.73 c +106.18 90.73 105.99 90.54 105.99 90.31 c +105.99 90.07 106.18 89.88 106.42 89.88 c +106.65 89.88 106.84 90.07 106.84 90.31 c +S +0.85 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +108.96 95.99 m 108.96 96.22 108.77 96.41 108.53 96.41 c +108.30 96.41 108.11 96.22 108.11 95.99 c +108.11 95.75 108.30 95.56 108.53 95.56 c +108.77 95.56 108.96 95.75 108.96 95.99 c +S +0.72 w +1.00 0.80 0.00 RG /a0 gs +[] 0 d +144.94 88.13 m 144.94 88.33 144.77 88.49 144.58 88.49 c +144.38 88.49 144.22 88.33 144.22 88.13 c +144.22 87.93 144.38 87.77 144.58 87.77 c +144.77 87.77 144.94 87.93 144.94 88.13 c +S +1 J +1 j +0.72 w +1.00 0.00 1.00 RG /a0 gs +7.416 174.168 m +205.841 174.168 l +205.841 18.263 l +7.416 18.263 l +7.416 174.168 l +S +0.57 w +1.00 G /a0 gs +[] 0 d +181.22 136.92 m 181.22 137.07 181.09 137.20 180.94 137.20 c +180.78 137.20 180.65 137.07 180.65 136.92 c +180.65 136.76 180.78 136.63 180.94 136.63 c +181.09 136.63 181.22 136.76 181.22 136.92 c +S +0.85 w +1.00 G /a0 gs +[] 0 d +38.44 78.49 m 38.44 78.73 38.25 78.92 38.02 78.92 c +37.78 78.92 37.59 78.73 37.59 78.49 c +37.59 78.26 37.78 78.06 38.02 78.06 c +38.25 78.06 38.44 78.26 38.44 78.49 c +S +0.85 w +1.00 G /a0 gs +[] 0 d +78.04 97.41 m 78.04 97.64 77.85 97.83 77.62 97.83 c +77.38 97.83 77.19 97.64 77.19 97.41 c +77.19 97.17 77.38 96.98 77.62 96.98 c +77.85 96.98 78.04 97.17 78.04 97.41 c +S +0.85 w +1.00 G /a0 gs +[] 0 d +106.84 97.77 m 106.84 98.00 106.65 98.19 106.42 98.19 c +106.18 98.19 105.99 98.00 105.99 97.77 c +105.99 97.53 106.18 97.34 106.42 97.34 c +106.65 97.34 106.84 97.53 106.84 97.77 c +S +0.57 w +1.00 G /a0 gs +[] 0 d +144.85 86.14 m 144.85 86.30 144.72 86.42 144.57 86.42 c +144.41 86.42 144.28 86.30 144.28 86.14 c +144.28 85.98 144.41 85.86 144.57 85.86 c +144.72 85.86 144.85 85.98 144.85 86.14 c +S +0.71 w +1.00 G /a0 gs +[] 0 d +48.69 160.29 m 48.69 160.49 48.53 160.65 48.33 160.65 c +48.14 160.65 47.98 160.49 47.98 160.29 c +47.98 160.10 48.14 159.94 48.33 159.94 c +48.53 159.94 48.69 160.10 48.69 160.29 c +S +1.00 g /a0 gs +[] 0 d +45.442 160.530 m +45.374 160.530 l +45.374 160.666 l +45.442 160.666 l +h +f +1.00 g /a0 gs +[] 0 d +45.510 160.530 m +45.442 160.530 l +45.442 160.666 l +45.510 160.666 l +h +f +1.00 g /a0 gs +[] 0 d +45.578 160.530 m +45.510 160.530 l +45.510 160.666 l +45.578 160.666 l +h +f +1.00 g /a0 gs +[] 0 d +45.646 160.530 m +45.578 160.530 l +45.578 160.666 l +45.646 160.666 l +h +f +1.00 g /a0 gs +[] 0 d +45.714 160.530 m +45.646 160.530 l +45.646 160.666 l +45.714 160.666 l +h +f +1.00 g /a0 gs +[] 0 d +45.782 160.258 m +45.714 160.258 l +45.714 160.939 l +45.782 160.939 l +h +f +1.00 g /a0 gs +[] 0 d +45.851 160.258 m +45.782 160.258 l +45.782 160.939 l +45.851 160.939 l +h +f +1.00 g /a0 gs +[] 0 d +45.919 160.258 m +45.851 160.258 l +45.851 160.939 l +45.919 160.939 l +h +f +1.00 g /a0 gs +[] 0 d +45.987 160.530 m +45.919 160.530 l +45.919 160.666 l +45.987 160.666 l +h +f +1.00 g /a0 gs +[] 0 d +46.055 160.530 m +45.987 160.530 l +45.987 160.666 l +46.055 160.666 l +h +f +1.00 g /a0 gs +[] 0 d +46.123 160.530 m +46.055 160.530 l +46.055 160.666 l +46.123 160.666 l +h +f +1.00 g /a0 gs +[] 0 d +46.191 160.530 m +46.123 160.530 l +46.123 160.666 l +46.191 160.666 l +h +f +1.00 g /a0 gs +[] 0 d +46.395 160.871 m +46.327 160.871 l +46.327 161.007 l +46.395 161.007 l +h +f +1.00 g /a0 gs +[] 0 d +46.463 159.986 m +46.395 159.986 l +46.395 160.394 l +46.463 160.394 l +h +f +1.00 g /a0 gs +[] 0 d +46.463 160.871 m +46.395 160.871 l +46.395 161.007 l +46.463 161.007 l +h +f +1.00 g /a0 gs +[] 0 d +46.531 159.986 m +46.463 159.986 l +46.463 160.530 l +46.531 160.530 l +h +f +1.00 g /a0 gs +[] 0 d +46.531 160.871 m +46.463 160.871 l +46.463 161.007 l +46.531 161.007 l +h +f +1.00 g /a0 gs +[] 0 d +46.599 159.918 m +46.531 159.918 l +46.531 160.530 l +46.599 160.530 l +h +f +1.00 g /a0 gs +[] 0 d +46.599 160.871 m +46.531 160.871 l +46.531 161.007 l +46.599 161.007 l +h +f +1.00 g /a0 gs +[] 0 d +46.667 159.918 m +46.599 159.918 l +46.599 160.122 l +46.667 160.122 l +h +f +1.00 g /a0 gs +[] 0 d +46.667 160.326 m +46.599 160.326 l +46.599 160.598 l +46.667 160.598 l +h +f +1.00 g /a0 gs +[] 0 d +46.667 160.871 m +46.599 160.871 l +46.599 161.007 l +46.667 161.007 l +h +f +1.00 g /a0 gs +[] 0 d +46.735 159.918 m +46.667 159.918 l +46.667 160.054 l +46.735 160.054 l +h +f +1.00 g /a0 gs +[] 0 d +46.735 160.462 m +46.667 160.462 l +46.667 160.666 l +46.735 160.666 l +h +f +1.00 g /a0 gs +[] 0 d +46.735 160.871 m +46.667 160.871 l +46.667 161.007 l +46.735 161.007 l +h +f +1.00 g /a0 gs +[] 0 d +46.803 159.918 m +46.735 159.918 l +46.735 160.054 l +46.803 160.054 l +h +f +1.00 g /a0 gs +[] 0 d +46.803 160.462 m +46.735 160.462 l +46.735 160.666 l +46.803 160.666 l +h +f +1.00 g /a0 gs +[] 0 d +46.803 160.871 m +46.735 160.871 l +46.735 161.007 l +46.803 161.007 l +h +f +1.00 g /a0 gs +[] 0 d +46.871 159.918 m +46.803 159.918 l +46.803 160.122 l +46.871 160.122 l +h +f +1.00 g /a0 gs +[] 0 d +46.871 160.530 m +46.803 160.530 l +46.803 160.735 l +46.871 160.735 l +h +f +1.00 g /a0 gs +[] 0 d +46.871 160.871 m +46.803 160.871 l +46.803 161.007 l +46.871 161.007 l +h +f +1.00 g /a0 gs +[] 0 d +46.939 159.918 m +46.871 159.918 l +46.871 160.122 l +46.939 160.122 l +h +f +1.00 g /a0 gs +[] 0 d +46.939 160.598 m +46.871 160.598 l +46.871 161.007 l +46.939 161.007 l +h +f +1.00 g /a0 gs +[] 0 d +47.007 159.986 m +46.939 159.986 l +46.939 160.190 l +47.007 160.190 l +h +f +1.00 g /a0 gs +[] 0 d +47.007 160.666 m +46.939 160.666 l +46.939 161.007 l +47.007 161.007 l +h +f +1.00 g /a0 gs +[] 0 d +47.075 160.054 m +47.007 160.054 l +47.007 160.190 l +47.075 160.190 l +h +f +1.00 g /a0 gs +[] 0 d +47.075 160.735 m +47.007 160.735 l +47.007 161.007 l +47.075 161.007 l +h +f +1.00 g /a0 gs +[] 0 d +47.143 160.939 m +47.075 160.939 l +47.075 161.007 l +47.143 161.007 l +h +f +1.00 g /a0 gs +[] 0 d +45.851 163.082 m +45.782 163.082 l +45.782 163.218 l +45.851 163.218 l +h +f +1.00 g /a0 gs +[] 0 d +45.919 163.082 m +45.851 163.082 l +45.851 163.218 l +45.919 163.218 l +h +f +1.00 g /a0 gs +[] 0 d +45.987 163.082 m +45.919 163.082 l +45.919 163.218 l +45.987 163.218 l +h +f +1.00 g /a0 gs +[] 0 d +46.055 163.082 m +45.987 163.082 l +45.987 163.218 l +46.055 163.218 l +h +f +1.00 g /a0 gs +[] 0 d +46.123 163.082 m +46.055 163.082 l +46.055 163.218 l +46.123 163.218 l +h +f +1.00 g /a0 gs +[] 0 d +46.191 163.082 m +46.123 163.082 l +46.123 163.218 l +46.191 163.218 l +h +f +1.00 g /a0 gs +[] 0 d +46.259 163.082 m +46.191 163.082 l +46.191 163.218 l +46.259 163.218 l +h +f +1.00 g /a0 gs +[] 0 d +46.327 163.218 m +46.259 163.218 l +46.259 163.354 l +46.327 163.354 l +h +f +1.00 g /a0 gs +[] 0 d +46.395 163.218 m +46.327 163.218 l +46.327 163.354 l +46.395 163.354 l +h +f +1.00 g /a0 gs +[] 0 d +46.463 163.218 m +46.395 163.218 l +46.395 163.354 l +46.463 163.354 l +h +f +1.00 g /a0 gs +[] 0 d +46.531 162.469 m +46.463 162.469 l +46.463 163.558 l +46.531 163.558 l +h +f +1.00 g /a0 gs +[] 0 d +46.599 162.469 m +46.531 162.469 l +46.531 163.558 l +46.599 163.558 l +h +f +1.00 g /a0 gs +[] 0 d +46.667 162.469 m +46.599 162.469 l +46.599 163.558 l +46.667 163.558 l +h +f +1.00 g /a0 gs +[] 0 d +46.735 162.469 m +46.667 162.469 l +46.667 162.878 l +46.735 162.878 l +h +f +1.00 g /a0 gs +[] 0 d +46.735 163.218 m +46.667 163.218 l +46.667 163.354 l +46.735 163.354 l +h +f +1.00 g /a0 gs +[] 0 d +46.803 162.605 m +46.735 162.605 l +46.735 163.014 l +46.803 163.014 l +h +f +1.00 g /a0 gs +[] 0 d +46.803 163.218 m +46.735 163.218 l +46.735 163.354 l +46.803 163.354 l +h +f +1.00 g /a0 gs +[] 0 d +46.871 162.741 m +46.803 162.741 l +46.803 163.082 l +46.871 163.082 l +h +f +1.00 g /a0 gs +[] 0 d +46.871 163.218 m +46.803 163.218 l +46.803 163.354 l +46.871 163.354 l +h +f +1.00 g /a0 gs +[] 0 d +46.939 162.878 m +46.871 162.878 l +46.871 163.354 l +46.939 163.354 l +h +f +1.00 g /a0 gs +[] 0 d +47.007 162.946 m +46.939 162.946 l +46.939 163.354 l +47.007 163.354 l +h +f +1.00 g /a0 gs +[] 0 d +47.075 163.014 m +47.007 163.014 l +47.007 163.354 l +47.075 163.354 l +h +f +1.00 g /a0 gs +[] 0 d +47.143 163.150 m +47.075 163.150 l +47.075 163.354 l +47.143 163.354 l +h +f +1.00 g /a0 gs +[] 0 d +47.211 163.218 m +47.143 163.218 l +47.143 163.354 l +47.211 163.354 l +h +f +1.00 g /a0 gs +[] 0 d +43.424 162.537 m +43.356 162.537 l +43.356 162.673 l +43.424 162.673 l +h +f +1.00 g /a0 gs +[] 0 d +43.424 163.354 m +43.356 163.354 l +43.356 163.490 l +43.424 163.490 l +h +f +1.00 g /a0 gs +[] 0 d +43.492 162.469 m +43.424 162.469 l +43.424 162.673 l +43.492 162.673 l +h +f +1.00 g /a0 gs +[] 0 d +43.492 162.946 m +43.424 162.946 l +43.424 163.082 l +43.492 163.082 l +h +f +1.00 g /a0 gs +[] 0 d +43.492 163.354 m +43.424 163.354 l +43.424 163.490 l +43.492 163.490 l +h +f +1.00 g /a0 gs +[] 0 d +43.560 162.469 m +43.492 162.469 l +43.492 162.673 l +43.560 162.673 l +h +f +1.00 g /a0 gs +[] 0 d +43.560 162.946 m +43.492 162.946 l +43.492 163.082 l +43.560 163.082 l +h +f +1.00 g /a0 gs +[] 0 d +43.560 163.354 m +43.492 163.354 l +43.492 163.558 l +43.560 163.558 l +h +f +1.00 g /a0 gs +[] 0 d +43.628 162.469 m +43.560 162.469 l +43.560 162.605 l +43.628 162.605 l +h +f +1.00 g /a0 gs +[] 0 d +43.628 162.946 m +43.560 162.946 l +43.560 163.082 l +43.628 163.082 l +h +f +1.00 g /a0 gs +[] 0 d +43.628 163.422 m +43.560 163.422 l +43.560 163.558 l +43.628 163.558 l +h +f +1.00 g /a0 gs +[] 0 d +43.696 162.469 m +43.628 162.469 l +43.628 162.605 l +43.696 162.605 l +h +f +1.00 g /a0 gs +[] 0 d +43.696 162.946 m +43.628 162.946 l +43.628 163.082 l +43.696 163.082 l +h +f +1.00 g /a0 gs +[] 0 d +43.696 163.422 m +43.628 163.422 l +43.628 163.558 l +43.696 163.558 l +h +f +1.00 g /a0 gs +[] 0 d +43.764 162.469 m +43.696 162.469 l +43.696 162.605 l +43.764 162.605 l +h +f +1.00 g /a0 gs +[] 0 d +43.764 162.946 m +43.696 162.946 l +43.696 163.150 l +43.764 163.150 l +h +f +1.00 g /a0 gs +[] 0 d +43.764 163.422 m +43.696 163.422 l +43.696 163.558 l +43.764 163.558 l +h +f +1.00 g /a0 gs +[] 0 d +43.832 162.469 m +43.764 162.469 l +43.764 162.673 l +43.832 162.673 l +h +f +1.00 g /a0 gs +[] 0 d +43.832 162.878 m +43.764 162.878 l +43.764 163.558 l +43.832 163.558 l +h +f +1.00 g /a0 gs +[] 0 d +43.900 162.469 m +43.832 162.469 l +43.832 163.558 l +43.900 163.558 l +h +f +1.00 g /a0 gs +[] 0 d +43.968 162.537 m +43.900 162.537 l +43.900 163.014 l +43.968 163.014 l +h +f +1.00 g /a0 gs +[] 0 d +43.968 163.082 m +43.900 163.082 l +43.900 163.490 l +43.968 163.490 l +h +f +1.00 g /a0 gs +[] 0 d +44.036 162.605 m +43.968 162.605 l +43.968 162.946 l +44.036 162.946 l +h +f +1.00 g /a0 gs +[] 0 d +44.036 163.150 m +43.968 163.150 l +43.968 163.422 l +44.036 163.422 l +h +f +1.00 g /a0 gs +[] 0 d +44.240 162.809 m +44.172 162.809 l +44.172 162.946 l +44.240 162.946 l +h +f +1.00 g /a0 gs +[] 0 d +44.309 162.809 m +44.240 162.809 l +44.240 162.946 l +44.309 162.946 l +h +f +1.00 g /a0 gs +[] 0 d +44.376 162.809 m +44.309 162.809 l +44.309 162.946 l +44.376 162.946 l +h +f +1.00 g /a0 gs +[] 0 d +44.445 162.809 m +44.376 162.809 l +44.376 162.946 l +44.445 162.946 l +h +f +1.00 g /a0 gs +[] 0 d +44.513 162.809 m +44.445 162.809 l +44.445 162.946 l +44.513 162.946 l +h +f +1.00 g /a0 gs +[] 0 d +44.581 162.809 m +44.513 162.809 l +44.513 162.946 l +44.581 162.946 l +h +f +1.00 g /a0 gs +[] 0 d +44.649 162.809 m +44.581 162.809 l +44.581 162.946 l +44.649 162.946 l +h +f +1.00 g /a0 gs +[] 0 d +43.424 160.666 m +43.356 160.666 l +43.356 160.803 l +43.424 160.803 l +h +f +1.00 g /a0 gs +[] 0 d +43.492 160.666 m +43.424 160.666 l +43.424 160.803 l +43.492 160.803 l +h +f +1.00 g /a0 gs +[] 0 d +43.560 160.666 m +43.492 160.666 l +43.492 160.871 l +43.560 160.871 l +h +f +1.00 g /a0 gs +[] 0 d +43.628 160.735 m +43.560 160.735 l +43.560 160.939 l +43.628 160.939 l +h +f +1.00 g /a0 gs +[] 0 d +43.696 159.918 m +43.628 159.918 l +43.628 160.939 l +43.696 160.939 l +h +f +1.00 g /a0 gs +[] 0 d +43.764 159.918 m +43.696 159.918 l +43.696 161.007 l +43.764 161.007 l +h +f +1.00 g /a0 gs +[] 0 d +43.832 159.918 m +43.764 159.918 l +43.764 161.007 l +43.832 161.007 l +h +f +1.00 g /a0 gs +[] 0 d +43.900 159.918 m +43.832 159.918 l +43.832 161.007 l +43.900 161.007 l +h +f +1.00 g /a0 gs +[] 0 d +44.240 160.258 m +44.172 160.258 l +44.172 160.394 l +44.240 160.394 l +h +f +1.00 g /a0 gs +[] 0 d +44.309 160.258 m +44.240 160.258 l +44.240 160.394 l +44.309 160.394 l +h +f +1.00 g /a0 gs +[] 0 d +44.376 160.258 m +44.309 160.258 l +44.309 160.394 l +44.376 160.394 l +h +f +1.00 g /a0 gs +[] 0 d +44.445 160.258 m +44.376 160.258 l +44.376 160.394 l +44.445 160.394 l +h +f +1.00 g /a0 gs +[] 0 d +44.513 160.258 m +44.445 160.258 l +44.445 160.394 l +44.513 160.394 l +h +f +1.00 g /a0 gs +[] 0 d +44.581 160.258 m +44.513 160.258 l +44.513 160.394 l +44.581 160.394 l +h +f +1.00 g /a0 gs +[] 0 d +44.649 160.258 m +44.581 160.258 l +44.581 160.394 l +44.649 160.394 l +h +f +endstream +endobj +1 0 obj +<> +endobj +2 0 obj +<< +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +/Font << +>> +/XObject << +>> +/ExtGState << + /a0 << /CA 1.00 /ca 1.00 >> +>> +>> +endobj +5 0 obj +<< +/Producer (jsPDF 0.0.0) +/CreationDate (D:20211030171045-04'00') +>> +endobj +6 0 obj +<< +/Type /Catalog +/Pages 1 0 R +/OpenAction [3 0 R /FitH null] +/PageLayout /OneColumn +>> +endobj +xref +0 7 +0000000000 65535 f +0000138815 00000 n +0000138872 00000 n +0000000015 00000 n +0000000124 00000 n +0000139012 00000 n +0000139097 00000 n +trailer +<< +/Size 7 +/Root 6 0 R +/Info 5 0 R +/ID [ <12E1C01CE3FAB397214A7E2F1234DDCC> <12E1C01CE3FAB397214A7E2F1234DDCC> ] +>> +startxref +139200 +%%EOF \ No newline at end of file diff --git a/doc/addon_rev2_schematic.pdf b/doc/addon_rev2_schematic.pdf new file mode 100644 index 0000000..9d222e3 --- /dev/null +++ b/doc/addon_rev2_schematic.pdf @@ -0,0 +1,8711 @@ +%PDF-1.4 +%ºß¬à +3 0 obj +<> +endobj +4 0 obj +<< +/Length 98926 +>> +stream +0.20 w +0 G +2 J +0 j +100 M +1.00 g +[] 0 d +0.00 827.30 1169.00 -827.30 re +f +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +216.000 807.000 m +216.000 817.000 l +216.000 21.000 m +216.000 11.000 l +412.000 807.000 m +412.000 817.000 l +412.000 21.000 m +412.000 11.000 l +608.000 807.000 m +608.000 817.000 l +608.000 21.000 m +608.000 11.000 l +804.000 807.000 m +804.000 817.000 l +804.000 21.000 m +804.000 11.000 l +1000.000 807.000 m +1000.000 817.000 l +1000.000 21.000 m +1000.000 11.000 l +20.000 611.000 m +10.000 611.000 l +1149.000 611.000 m +1159.000 611.000 l +20.000 415.000 m +10.000 415.000 l +1149.000 415.000 m +1159.000 415.000 l +20.000 219.000 m +10.000 219.000 l +1149.000 219.000 m +1159.000 219.000 l +20.000 23.000 m +10.000 23.000 l +1149.000 23.000 m +1159.000 23.000 l +S +10.00 w +BT +/F1 9 Tf +9.00 TL +0.533 0.000 0.000 rg +11.50 709.00 Td +(A) Tj +ET +10.00 w +BT +/F1 9 Tf +9.00 TL +0.533 0.000 0.000 rg +1150.50 709.00 Td +(A) Tj +ET +10.00 w +BT +/F1 9 Tf +9.00 TL +0.533 0.000 0.000 rg +11.50 513.00 Td +(B) Tj +ET +10.00 w +BT +/F1 9 Tf +9.00 TL +0.533 0.000 0.000 rg +1150.50 513.00 Td +(B) Tj +ET +10.00 w +BT +/F1 9 Tf +9.00 TL +0.533 0.000 0.000 rg +11.50 317.00 Td +(C) Tj +ET +10.00 w +BT +/F1 9 Tf +9.00 TL +0.533 0.000 0.000 rg +1150.50 317.00 Td +(C) Tj +ET +10.00 w +BT +/F1 9 Tf +9.00 TL +0.533 0.000 0.000 rg +11.50 121.00 Td +(D) Tj +ET +10.00 w +BT +/F1 9 Tf +9.00 TL +0.533 0.000 0.000 rg +1150.50 121.00 Td +(D) Tj +ET +10.00 w +BT +/F1 9 Tf +9.00 TL +0.533 0.000 0.000 rg +118.00 808.50 Td +(1) Tj +ET +10.00 w +BT +/F1 9 Tf +9.00 TL +0.533 0.000 0.000 rg +118.00 12.50 Td +(1) Tj +ET +10.00 w +BT +/F1 9 Tf +9.00 TL +0.533 0.000 0.000 rg +314.00 808.50 Td +(2) Tj +ET +10.00 w +BT +/F1 9 Tf +9.00 TL +0.533 0.000 0.000 rg +314.00 12.50 Td +(2) Tj +ET +10.00 w +BT +/F1 9 Tf +9.00 TL +0.533 0.000 0.000 rg +510.00 808.50 Td +(3) Tj +ET +10.00 w +BT +/F1 9 Tf +9.00 TL +0.533 0.000 0.000 rg +510.00 12.50 Td +(3) Tj +ET +10.00 w +BT +/F1 9 Tf +9.00 TL +0.533 0.000 0.000 rg +706.00 808.50 Td +(4) Tj +ET +10.00 w +BT +/F1 9 Tf +9.00 TL +0.533 0.000 0.000 rg +706.00 12.50 Td +(4) Tj +ET +10.00 w +BT +/F1 9 Tf +9.00 TL +0.533 0.000 0.000 rg +902.00 808.50 Td +(5) Tj +ET +10.00 w +BT +/F1 9 Tf +9.00 TL +0.533 0.000 0.000 rg +902.00 12.50 Td +(5) Tj +ET +2 J +0 j +100 M +1.00 w +0.53 0.00 0.00 RG +[] 0 d +20.00 807.00 1129.00 -786.00 re +S +2 J +0 j +100 M +1.00 w +0.53 0.00 0.00 RG +[] 0 d +10.00 817.00 1149.00 -806.00 re +S +2 J +0 j +100 M +1.00 w +0.53 0.00 0.00 RG +[] 0 d +705.00 101.00 444.00 -80.00 re +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +0.00 g +[] 0 d +705.100 61.750 m +1148.630 61.750 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +0.00 g +[] 0 d +809.630 41.750 m +1148.630 41.750 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +0.00 g +[] 0 d +1069.610 100.930 m +1069.630 61.750 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +0.00 g +[] 0 d +1069.630 61.750 m +1069.630 41.750 l +S +10.00 w +BT +/F1 11 Tf +11.00 TL +0.533 0.000 0.000 rg +710.00 88.00 Td +(TITLE:) Tj +ET +10.00 w +BT +/F1 13 Tf +13.00 TL +0.000 0.000 1.000 rg +767.62 75.41 Td +(stmdsp add-on board) Tj +ET +10.00 w +BT +/F1 11 Tf +11.00 TL +0.533 0.000 0.000 rg +1074.62 74.75 Td +(REV:) Tj +ET +10.00 w +BT +/F1 12 Tf +12.00 TL +0.000 0.000 1.000 rg +1112.62 74.75 Td +(2.0) Tj +ET +10.00 w +BT +/F1 11 Tf +11.00 TL +0.533 0.000 0.000 rg +814.62 26.00 Td +(Date:) Tj +ET +10.00 w +BT +/F1 12 Tf +12.00 TL +0.000 0.000 1.000 rg +861.62 25.52 Td +(2021-09-28) Tj +ET +10.00 w +BT +/F1 11 Tf +11.00 TL +0.533 0.000 0.000 rg +1073.62 46.00 Td +(Sheet:) Tj +ET +10.00 w +BT +/F1 12 Tf +12.00 TL +0.000 0.000 1.000 rg +1118.62 45.52 Td +(1/1) Tj +ET +10.00 w +BT +/F1 11 Tf +11.00 TL +0.533 0.000 0.000 rg +953.62 25.75 Td +(Drawn By:) Tj +ET +10.00 w +BT +/F1 12 Tf +12.00 TL +0.000 0.000 1.000 rg +1018.63 25.75 Td +(Clyne Sullivan) Tj +ET +10.00 w +BT +/F1 11 Tf +11.00 TL +0.533 0.000 0.000 rg +814.62 47.75 Td +(Company:) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +0.00 g +[] 0 d +809.630 61.750 m +809.630 21.750 l +S +0.33 0.53 1.00 rg +[] 0 d +760.394 39.565 m +760.535 39.671 760.707 39.723 760.904 39.723 c +761.168 39.723 761.451 39.630 761.752 39.448 c +762.053 39.266 762.342 38.980 762.618 38.587 c +763.687 40.221 l +763.355 40.678 762.944 41.035 762.446 41.287 c +761.948 41.539 761.420 41.662 760.867 41.662 c +760.081 41.662 759.393 41.433 758.815 40.977 c +758.238 40.520 757.949 39.922 757.949 39.196 c +757.949 38.675 758.133 38.177 758.502 37.709 c +758.766 37.375 759.245 36.971 759.933 36.502 c +760.529 36.098 760.898 35.817 761.033 35.659 c +761.168 35.501 761.236 35.348 761.236 35.196 c +761.236 35.009 761.150 34.851 760.972 34.710 c +760.793 34.575 760.560 34.505 760.265 34.505 c +759.522 34.505 758.834 34.898 758.207 35.688 c +756.825 34.154 l +757.439 33.533 757.998 33.100 758.496 32.865 c +758.993 32.631 759.552 32.514 760.161 32.514 c +761.217 32.514 762.022 32.801 762.581 33.375 c +763.140 33.949 763.417 34.564 763.417 35.208 c +763.417 35.700 763.281 36.151 763.011 36.572 c +762.741 36.988 762.176 37.492 761.316 38.078 c +760.775 38.447 760.456 38.693 760.351 38.821 c +760.241 38.950 760.185 39.079 760.185 39.208 c +760.179 39.343 760.253 39.460 760.394 39.565 c +h +f +0.33 0.53 1.00 rg +[] 0 d +745.024 39.975 m +740.699 39.975 l +741.055 42.417 l +741.055 42.417 745.644 42.423 745.669 42.423 c +746.271 42.423 746.762 42.892 746.762 43.466 c +746.762 44.040 746.271 44.508 745.669 44.508 c +745.650 44.508 739.009 44.508 739.009 44.508 c +737.314 32.736 l +744.268 32.736 l +744.268 32.736 l +744.852 32.748 745.325 33.205 745.325 33.761 c +745.325 34.329 744.839 34.792 744.243 34.792 c +744.219 34.792 739.931 34.786 739.931 34.786 c +740.385 37.908 l +740.385 37.908 744.790 37.902 744.827 37.902 c +745.429 37.902 745.921 38.370 745.921 38.944 c +745.933 39.466 745.540 39.893 745.024 39.975 c +h +f +0.33 0.53 1.00 rg +[] 0 d +782.922 44.502 m +782.903 44.502 776.262 44.502 776.262 44.502 c +774.579 32.742 l +781.539 32.742 l +781.539 32.742 l +782.123 32.754 782.596 33.211 782.596 33.767 c +782.596 34.335 782.111 34.798 781.515 34.798 c +781.490 34.798 777.202 34.792 777.202 34.792 c +777.657 37.914 l +777.657 37.914 782.062 37.908 782.105 37.908 c +782.707 37.908 783.198 38.376 783.198 38.950 c +783.198 39.466 782.805 39.893 782.289 39.975 c +777.964 39.975 l +778.320 42.417 l +778.320 42.417 782.909 42.423 782.934 42.423 c +783.536 42.423 784.027 42.892 784.027 43.466 c +784.015 44.034 783.530 44.502 782.922 44.502 c +h +f +0.33 0.53 1.00 rg +[] 0 d +795.350 38.868 m +795.350 40.022 795.067 41.047 794.508 41.931 c +793.949 42.816 793.224 43.466 792.327 43.876 c +791.430 44.291 790.072 44.496 788.236 44.496 c +786.282 44.496 l +784.599 32.736 l +788.432 32.736 l +790.042 32.736 791.301 32.965 792.204 33.422 c +793.107 33.878 793.863 34.605 794.459 35.594 c +795.055 36.590 795.350 37.679 795.350 38.868 c +h +792.315 36.438 m +791.866 35.794 791.277 35.337 790.539 35.073 c +790.011 34.886 789.163 34.792 787.990 34.792 c +787.228 34.792 l +788.315 42.429 l +788.899 42.429 l +789.851 42.429 790.613 42.288 791.184 42.001 c +791.756 41.714 792.198 41.310 792.517 40.783 c +792.831 40.256 792.990 39.606 792.990 38.827 c +792.984 37.884 792.763 37.082 792.315 36.438 c +h +f +0.33 0.53 1.00 rg +[] 0 d +804.472 39.003 m +803.102 38.283 l +802.992 37.334 802.144 36.602 801.124 36.602 c +800.025 36.602 799.134 37.451 799.134 38.499 c +799.134 39.548 800.025 40.397 801.124 40.397 c +801.548 40.397 801.941 40.268 802.261 40.057 c +803.962 40.953 l +803.041 44.479 l +801.094 44.479 l +794.459 32.766 l +796.941 32.766 l +798.341 35.261 l +803.219 35.261 l +803.870 32.766 l +806.106 32.766 l +804.472 39.003 l +h +f +0.33 0.53 1.00 rg +[] 0 d +800.393 38.546 m +800.393 38.142 800.737 37.814 801.161 37.814 c +801.585 37.814 801.929 38.142 801.929 38.546 c +801.929 38.950 801.585 39.278 801.161 39.278 c +800.737 39.278 800.393 38.950 800.393 38.546 c +h +f +0.33 0.53 1.00 rg +[] 0 d +755.056 40.069 m +755.056 40.069 755.056 40.075 755.056 40.069 c +754.288 40.069 l +754.208 40.209 l +753.895 40.684 753.501 41.041 753.028 41.287 c +752.549 41.533 751.793 41.656 751.228 41.656 c +750.387 41.656 749.582 41.439 748.814 41.006 c +748.046 40.572 747.432 39.969 746.977 39.190 c +746.523 38.417 746.289 37.597 746.289 36.742 c +746.289 35.618 746.645 34.634 747.358 33.785 c +748.071 32.936 749.035 32.514 750.245 32.514 c +750.774 32.514 751.247 32.596 751.671 32.772 c +752.095 32.941 752.549 33.240 753.034 33.673 c +753.034 33.673 753.606 33.199 753.612 33.205 c +753.968 32.936 754.411 32.766 754.890 32.736 c +755.111 32.736 l +755.142 32.988 l +755.922 39.249 l +755.916 39.249 755.916 39.249 755.910 39.249 c +755.910 39.700 755.529 40.063 755.056 40.069 c +h +753.262 35.870 m +752.985 35.372 752.641 35.003 752.230 34.769 c +751.818 34.534 751.339 34.417 750.786 34.417 c +750.123 34.417 749.582 34.622 749.158 35.044 c +748.734 35.460 748.525 36.010 748.525 36.690 c +748.525 37.574 748.802 38.294 749.361 38.857 c +749.920 39.419 750.596 39.694 751.394 39.694 c +752.082 39.694 752.635 39.483 753.053 39.067 c +753.471 38.646 753.679 38.095 753.679 37.404 c +753.679 36.883 753.538 36.367 753.262 35.870 c +h +f +0.33 0.53 1.00 rg +[] 0 d +729.837 43.360 m +729.377 44.526 728.627 45.574 727.638 46.423 c +726.121 47.723 724.155 48.444 722.109 48.444 c +720.340 48.444 718.650 47.917 717.225 46.921 c +716.537 46.441 715.941 45.873 715.450 45.228 c +715.143 45.269 714.829 45.293 714.510 45.293 c +712.747 45.293 711.082 44.637 709.835 43.448 c +708.588 42.259 707.900 40.678 707.900 38.991 c +707.900 37.428 708.508 35.928 709.607 34.769 c +710.480 33.849 711.610 33.199 712.857 32.895 c +713.398 31.360 714.921 30.253 716.709 30.253 c +718.951 30.253 720.776 31.993 720.776 34.130 c +720.776 34.253 720.770 34.382 720.758 34.505 c +726.465 37.363 l +725.218 39.425 l +719.762 36.695 l +719.019 37.504 717.925 38.013 716.709 38.013 c +714.946 38.013 713.441 36.936 712.876 35.436 c +711.438 36.040 710.431 37.404 710.431 38.997 c +710.431 41.141 712.255 42.886 714.510 42.886 c +715.302 42.886 716.046 42.669 716.672 42.294 c +717.428 44.467 719.578 46.037 722.109 46.037 c +725.058 46.037 727.478 43.917 727.804 41.193 c +727.908 41.205 728.013 41.211 728.117 41.211 c +729.880 41.211 731.312 39.846 731.312 38.165 c +731.312 36.572 730.028 35.266 728.394 35.132 c +726.569 35.132 l +726.489 35.149 726.403 35.155 726.317 35.155 c +725.611 35.155 725.039 34.611 725.039 33.937 c +725.039 33.299 725.555 32.777 726.213 32.725 c +726.213 32.713 l +728.394 32.713 l +728.504 32.713 l +728.615 32.725 l +730.040 32.842 731.361 33.457 732.332 34.464 c +733.308 35.477 733.849 36.789 733.849 38.165 c +733.849 40.590 732.159 42.663 729.837 43.360 c +h +716.709 35.630 m +717.575 35.630 718.282 34.956 718.282 34.130 c +718.282 33.305 717.575 32.631 716.709 32.631 c +715.843 32.631 715.136 33.305 715.136 34.130 c +715.136 34.956 715.843 35.630 716.709 35.630 c +h +f +0.33 0.53 1.00 rg +[] 0 d +768.810 36.280 m +767.035 41.439 l +764.836 41.439 l +767.404 33.925 l +764.811 29.556 l +767.176 29.556 l +774.346 41.439 l +771.931 41.439 l +f +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +182.33 518.17 Td +(U-F-M5SS-W-1) Tj +ET +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +182.33 527.50 Td +(USB1) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +0.00 1.00 -1.00 0.00 168.00 547.88 Tm +(EP) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +0.00 1.00 -1.00 0.00 164.00 566.00 Tm +(9) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +165.000 581.000 m +165.000 561.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +0.00 1.00 -1.00 0.00 178.00 547.88 Tm +(EP) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +0.00 1.00 -1.00 0.00 174.00 566.00 Tm +(8) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +175.000 581.000 m +175.000 561.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +0.00 1.00 -1.00 0.00 178.00 503.00 Tm +(EP) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +0.00 1.00 -1.00 0.00 174.00 490.29 Tm +(7) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +175.000 481.000 m +175.000 501.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +0.00 1.00 -1.00 0.00 168.00 503.00 Tm +(EP) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +0.00 1.00 -1.00 0.00 164.00 490.29 Tm +(6) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +165.000 481.000 m +165.000 501.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +132.00 508.00 Td +(GND) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +119.28 512.00 Td +(5) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +110.000 511.000 m +130.000 511.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +132.00 518.00 Td +(ID) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +119.28 522.00 Td +(4) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +110.000 521.000 m +130.000 521.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +132.00 528.00 Td +(D+) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +119.28 532.00 Td +(3) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +110.000 531.000 m +130.000 531.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +132.00 538.00 Td +(D-) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +119.28 542.00 Td +(2) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +110.000 541.000 m +130.000 541.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +132.00 548.00 Td +(VBUS) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +119.28 552.00 Td +(1) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +110.000 551.000 m +130.000 551.000 l +S +2 J +0 j +100 M +1.00 w +0.53 0.00 0.00 RG +[] 0 d +132.000 561.000 m +178.000 561.000 l +179.105 561.000 180.000 560.105 180.000 559.000 c +180.000 503.000 l +180.000 501.895 178.895 501.000 178.000 501.000 c +132.000 501.000 l +130.895 501.000 130.000 502.105 130.000 503.000 c +130.000 559.000 l +130.000 560.105 131.105 561.000 132.000 561.000 c +S +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +189.03 764.33 Td +(2171-210SG0CUNT3) Tj +ET +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +189.03 773.67 Td +(H1) Tj +ET +2 J +0 j +100 M +1.00 w +0.53 0.00 0.00 RG +[] 0 d +177.000 761.000 m +213.000 761.000 l +214.105 761.000 215.000 760.105 215.000 759.000 c +215.000 653.000 l +215.000 651.895 213.895 651.000 213.000 651.000 c +177.000 651.000 l +175.895 651.000 175.000 652.105 175.000 653.000 c +175.000 759.000 l +175.000 760.105 176.105 761.000 177.000 761.000 c +S +1.00 w +0.53 0.00 0.00 RG +0.53 0.00 0.00 rg +[] 0 d +181.50 756.00 m 181.50 756.83 180.83 757.50 180.00 757.50 c +179.17 757.50 178.50 756.83 178.50 756.00 c +178.50 755.17 179.17 754.50 180.00 754.50 c +180.83 754.50 181.50 755.17 181.50 756.00 c +B +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +178.70 747.00 Td +(1) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +168.78 752.00 Td +(1) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +165.000 751.000 m +175.000 751.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +199.87 657.00 Td +(20) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +215.50 662.00 Td +(20) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +225.000 661.000 m +215.000 661.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +178.70 737.00 Td +(3) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +168.78 742.00 Td +(3) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +165.000 741.000 m +175.000 741.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +199.87 667.00 Td +(18) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +215.50 672.00 Td +(18) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +225.000 671.000 m +215.000 671.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +178.70 727.00 Td +(5) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +168.78 732.00 Td +(5) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +165.000 731.000 m +175.000 731.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +199.87 677.00 Td +(16) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +215.50 682.00 Td +(16) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +225.000 681.000 m +215.000 681.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +178.70 717.00 Td +(7) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +168.78 722.00 Td +(7) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +165.000 721.000 m +175.000 721.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +199.87 687.00 Td +(14) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +215.50 692.00 Td +(14) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +225.000 691.000 m +215.000 691.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +178.70 707.00 Td +(9) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +168.78 712.00 Td +(9) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +165.000 711.000 m +175.000 711.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +199.87 697.00 Td +(12) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +215.50 702.00 Td +(12) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +225.000 701.000 m +215.000 701.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +178.70 697.00 Td +(11) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +163.07 702.00 Td +(11) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +165.000 701.000 m +175.000 701.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +199.87 707.00 Td +(10) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +215.50 712.00 Td +(10) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +225.000 711.000 m +215.000 711.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +178.70 687.00 Td +(13) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +163.07 692.00 Td +(13) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +165.000 691.000 m +175.000 691.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +205.59 717.00 Td +(8) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +215.50 722.00 Td +(8) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +225.000 721.000 m +215.000 721.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +178.70 677.00 Td +(15) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +163.07 682.00 Td +(15) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +165.000 681.000 m +175.000 681.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +205.59 727.00 Td +(6) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +215.50 732.00 Td +(6) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +225.000 731.000 m +215.000 731.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +178.70 667.00 Td +(17) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +163.07 672.00 Td +(17) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +165.000 671.000 m +175.000 671.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +205.59 737.00 Td +(4) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +215.50 742.00 Td +(4) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +225.000 741.000 m +215.000 741.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +178.70 657.00 Td +(19) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +163.07 662.00 Td +(19) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +165.000 661.000 m +175.000 661.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +205.59 747.00 Td +(2) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +215.50 752.00 Td +(2) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +225.000 751.000 m +215.000 751.000 l +S +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +374.03 764.33 Td +(2171-210SG0CUNT3) Tj +ET +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +374.03 773.67 Td +(H2) Tj +ET +2 J +0 j +100 M +1.00 w +0.53 0.00 0.00 RG +[] 0 d +362.000 761.000 m +398.000 761.000 l +399.105 761.000 400.000 760.105 400.000 759.000 c +400.000 653.000 l +400.000 651.895 398.895 651.000 398.000 651.000 c +362.000 651.000 l +360.895 651.000 360.000 652.105 360.000 653.000 c +360.000 759.000 l +360.000 760.105 361.105 761.000 362.000 761.000 c +S +1.00 w +0.53 0.00 0.00 RG +0.53 0.00 0.00 rg +[] 0 d +366.50 756.00 m 366.50 756.83 365.83 757.50 365.00 757.50 c +364.17 757.50 363.50 756.83 363.50 756.00 c +363.50 755.17 364.17 754.50 365.00 754.50 c +365.83 754.50 366.50 755.17 366.50 756.00 c +B +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +363.70 747.00 Td +(1) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +353.79 752.00 Td +(1) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +350.000 751.000 m +360.000 751.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +384.87 657.00 Td +(20) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +400.50 662.00 Td +(20) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +410.000 661.000 m +400.000 661.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +363.70 737.00 Td +(3) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +353.79 742.00 Td +(3) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +350.000 741.000 m +360.000 741.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +384.87 667.00 Td +(18) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +400.50 672.00 Td +(18) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +410.000 671.000 m +400.000 671.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +363.70 727.00 Td +(5) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +353.79 732.00 Td +(5) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +350.000 731.000 m +360.000 731.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +384.87 677.00 Td +(16) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +400.50 682.00 Td +(16) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +410.000 681.000 m +400.000 681.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +363.70 717.00 Td +(7) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +353.79 722.00 Td +(7) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +350.000 721.000 m +360.000 721.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +384.87 687.00 Td +(14) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +400.50 692.00 Td +(14) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +410.000 691.000 m +400.000 691.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +363.70 707.00 Td +(9) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +353.79 712.00 Td +(9) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +350.000 711.000 m +360.000 711.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +384.87 697.00 Td +(12) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +400.50 702.00 Td +(12) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +410.000 701.000 m +400.000 701.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +363.70 697.00 Td +(11) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +348.07 702.00 Td +(11) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +350.000 701.000 m +360.000 701.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +384.87 707.00 Td +(10) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +400.50 712.00 Td +(10) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +410.000 711.000 m +400.000 711.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +363.70 687.00 Td +(13) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +348.07 692.00 Td +(13) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +350.000 691.000 m +360.000 691.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +390.59 717.00 Td +(8) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +400.50 722.00 Td +(8) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +410.000 721.000 m +400.000 721.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +363.70 677.00 Td +(15) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +348.07 682.00 Td +(15) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +350.000 681.000 m +360.000 681.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +390.59 727.00 Td +(6) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +400.50 732.00 Td +(6) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +410.000 731.000 m +400.000 731.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +363.70 667.00 Td +(17) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +348.07 672.00 Td +(17) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +350.000 671.000 m +360.000 671.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +390.59 737.00 Td +(4) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +400.50 742.00 Td +(4) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +410.000 741.000 m +400.000 741.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +363.70 657.00 Td +(19) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +348.07 662.00 Td +(19) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +350.000 661.000 m +360.000 661.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +390.59 747.00 Td +(2) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +400.50 752.00 Td +(2) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +410.000 751.000 m +400.000 751.000 l +S +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +374.03 629.33 Td +(2171-210SG0CUNT3) Tj +ET +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +374.03 638.67 Td +(H3) Tj +ET +2 J +0 j +100 M +1.00 w +0.53 0.00 0.00 RG +[] 0 d +362.000 626.000 m +398.000 626.000 l +399.105 626.000 400.000 625.105 400.000 624.000 c +400.000 518.000 l +400.000 516.895 398.895 516.000 398.000 516.000 c +362.000 516.000 l +360.895 516.000 360.000 517.105 360.000 518.000 c +360.000 624.000 l +360.000 625.105 361.105 626.000 362.000 626.000 c +S +1.00 w +0.53 0.00 0.00 RG +0.53 0.00 0.00 rg +[] 0 d +366.50 621.00 m 366.50 621.83 365.83 622.50 365.00 622.50 c +364.17 622.50 363.50 621.83 363.50 621.00 c +363.50 620.17 364.17 619.50 365.00 619.50 c +365.83 619.50 366.50 620.17 366.50 621.00 c +B +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +363.70 612.00 Td +(1) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +353.79 617.00 Td +(1) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +350.000 616.000 m +360.000 616.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +384.87 522.00 Td +(20) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +400.50 527.00 Td +(20) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +410.000 526.000 m +400.000 526.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +363.70 602.00 Td +(3) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +353.79 607.00 Td +(3) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +350.000 606.000 m +360.000 606.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +384.87 532.00 Td +(18) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +400.50 537.00 Td +(18) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +410.000 536.000 m +400.000 536.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +363.70 592.00 Td +(5) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +353.79 597.00 Td +(5) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +350.000 596.000 m +360.000 596.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +384.87 542.00 Td +(16) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +400.50 547.00 Td +(16) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +410.000 546.000 m +400.000 546.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +363.70 582.00 Td +(7) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +353.79 587.00 Td +(7) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +350.000 586.000 m +360.000 586.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +384.87 552.00 Td +(14) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +400.50 557.00 Td +(14) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +410.000 556.000 m +400.000 556.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +363.70 572.00 Td +(9) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +353.79 577.00 Td +(9) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +350.000 576.000 m +360.000 576.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +384.87 562.00 Td +(12) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +400.50 567.00 Td +(12) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +410.000 566.000 m +400.000 566.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +363.70 562.00 Td +(11) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +348.07 567.00 Td +(11) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +350.000 566.000 m +360.000 566.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +384.87 572.00 Td +(10) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +400.50 577.00 Td +(10) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +410.000 576.000 m +400.000 576.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +363.70 552.00 Td +(13) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +348.07 557.00 Td +(13) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +350.000 556.000 m +360.000 556.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +390.59 582.00 Td +(8) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +400.50 587.00 Td +(8) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +410.000 586.000 m +400.000 586.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +363.70 542.00 Td +(15) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +348.07 547.00 Td +(15) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +350.000 546.000 m +360.000 546.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +390.59 592.00 Td +(6) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +400.50 597.00 Td +(6) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +410.000 596.000 m +400.000 596.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +363.70 532.00 Td +(17) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +348.07 537.00 Td +(17) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +350.000 536.000 m +360.000 536.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +390.59 602.00 Td +(4) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +400.50 607.00 Td +(4) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +410.000 606.000 m +400.000 606.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +363.70 522.00 Td +(19) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +348.07 527.00 Td +(19) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +350.000 526.000 m +360.000 526.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +390.59 612.00 Td +(2) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +400.50 617.00 Td +(2) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +410.000 616.000 m +400.000 616.000 l +S +10.00 w +BT +/F1 12 Tf +12.00 TL +0.400 g +230.00 636.00 Td +(Placed on bottom) Tj +ET +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +95.67 692.50 Td +(PA12_USB_DP) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +155.000 702.000 m +155.000 700.000 l +154.000 701.000 m +156.000 701.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +92.61 682.50 Td +(PA11_USB_DM) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +155.000 692.000 m +155.000 690.000 l +154.000 691.000 m +156.000 691.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +155.000 701.000 m +165.000 701.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +155.000 691.000 m +165.000 691.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +237.00 723.50 Td +(VDDA) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +235.000 722.000 m +235.000 720.000 l +234.000 721.000 m +236.000 721.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +237.00 713.50 Td +(GND) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +235.000 712.000 m +235.000 710.000 l +234.000 711.000 m +236.000 711.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +237.00 703.50 Td +(PA5_DAC_SIGOUT) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +235.000 702.000 m +235.000 700.000 l +234.000 701.000 m +236.000 701.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +273.29 527.50 Td +(PC0_ADC_POT1) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +340.000 537.000 m +340.000 535.000 l +339.000 536.000 m +341.000 536.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +273.29 537.50 Td +(PC1_ADC_POT2) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +340.000 547.000 m +340.000 545.000 l +339.000 546.000 m +341.000 546.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +260.24 557.50 Td +(PA4_DAC_DSPOUT) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +340.000 567.000 m +340.000 565.000 l +339.000 566.000 m +341.000 566.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +269.24 577.50 Td +(PA0_ADC_DSPIN) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +340.000 587.000 m +340.000 585.000 l +339.000 586.000 m +341.000 586.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +422.00 753.50 Td +(PC10_LED_R) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +420.000 752.000 m +420.000 750.000 l +419.000 751.000 m +421.000 751.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +422.00 743.50 Td +(PC12_LED_B) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +420.000 742.000 m +420.000 740.000 l +419.000 741.000 m +421.000 741.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +420.000 741.000 m +410.000 741.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +420.000 751.000 m +410.000 751.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +235.000 721.000 m +225.000 721.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +235.000 711.000 m +225.000 711.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +235.000 701.000 m +225.000 701.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +260.17 742.50 Td +(PC11_LED_G) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +315.000 752.000 m +315.000 750.000 l +314.000 751.000 m +316.000 751.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +315.000 751.000 m +350.000 751.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +335.000 691.000 m +335.000 681.000 l +340.000 681.000 l +350.000 681.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +340.000 586.000 m +350.000 586.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +340.000 566.000 m +350.000 566.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +340.000 546.000 m +350.000 546.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +340.000 536.000 m +350.000 536.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +37.61 532.50 Td +(PA11_USB_DM) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +100.000 542.000 m +100.000 540.000 l +99.000 541.000 m +101.000 541.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +40.67 522.50 Td +(PA12_USB_DP) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +100.000 532.000 m +100.000 530.000 l +99.000 531.000 m +101.000 531.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +78.56 502.50 Td +(GND) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +100.000 512.000 m +100.000 510.000 l +99.000 511.000 m +101.000 511.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +143.56 452.50 Td +(GND) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +165.000 462.000 m +165.000 460.000 l +164.000 461.000 m +166.000 461.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +100.000 541.000 m +105.000 541.000 l +110.000 541.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +100.000 531.000 m +110.000 531.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +100.000 511.000 m +110.000 511.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +165.000 461.000 m +165.000 481.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +175.000 481.000 m +175.000 471.000 l +165.000 471.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +175.000 581.000 m +175.000 591.000 l +190.000 591.000 l +190.000 471.000 l +175.000 471.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +165.000 581.000 m +165.000 591.000 l +175.000 591.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +868.62 747.50 Td +(VIN_-5V) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +905.000 757.000 m +905.000 755.000 l +904.000 756.000 m +906.000 756.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +965.000 726.000 m +905.000 726.000 l +905.000 756.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +957.00 642.50 Td +(GND) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +955.000 652.000 m +955.000 650.000 l +954.000 651.000 m +956.000 651.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +106.000 525.000 m +114.000 517.000 l +114.000 525.000 m +106.000 517.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +393.56 107.50 Td +(GND) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +415.000 117.000 m +415.000 115.000 l +414.000 116.000 m +416.000 116.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +303.29 157.50 Td +(PC0_ADC_POT1) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +370.000 167.000 m +370.000 165.000 l +369.000 166.000 m +371.000 166.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +468.29 157.50 Td +(PC1_ADC_POT2) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +535.000 167.000 m +535.000 165.000 l +534.000 166.000 m +536.000 166.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +370.000 166.000 m +370.000 146.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +535.000 166.000 m +535.000 146.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +152.00 313.20 Td +(GND) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +150.000 312.000 m +150.000 310.000 l +149.000 311.000 m +151.000 311.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +152.00 293.20 Td +(EXT_SIGOUT) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +150.000 292.000 m +150.000 290.000 l +149.000 291.000 m +151.000 291.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +147.00 223.20 Td +(GND) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +145.000 222.000 m +145.000 220.000 l +144.000 221.000 m +146.000 221.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +147.00 203.20 Td +(EXT_DSPOUT) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +145.000 202.000 m +145.000 200.000 l +144.000 201.000 m +146.000 201.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +152.00 138.20 Td +(EXT_DSPIN_GND) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +150.000 137.000 m +150.000 135.000 l +149.000 136.000 m +151.000 136.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +152.00 118.20 Td +(EXT_DSPIN) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +150.000 117.000 m +150.000 115.000 l +149.000 116.000 m +151.000 116.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +150.000 311.000 m +140.000 311.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +145.000 221.000 m +135.000 221.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +150.000 136.000 m +140.000 136.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +808.62 187.37 Td +(VIN_-5V) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +845.000 197.000 m +845.000 195.000 l +844.000 196.000 m +846.000 196.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +966.99 393.63 Td +(GND) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +965.000 392.000 m +965.000 390.000 l +964.000 391.000 m +966.000 391.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +966.99 223.63 Td +(GND) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +965.000 222.000 m +965.000 220.000 l +964.000 221.000 m +966.000 221.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +818.52 392.37 Td +(0V825) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +845.000 402.000 m +845.000 400.000 l +844.000 401.000 m +846.000 401.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +818.52 222.37 Td +(0V825) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +845.000 232.000 m +845.000 230.000 l +844.000 231.000 m +846.000 231.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +685.21 537.37 Td +(EXT_DSPIN) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +735.000 547.000 m +735.000 545.000 l +734.000 546.000 m +736.000 546.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +655.24 402.37 Td +(PA4_DAC_DSPOUT) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +735.000 412.000 m +735.000 410.000 l +734.000 411.000 m +736.000 411.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +657.22 232.37 Td +(PA5_DAC_SIGOUT) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +735.000 242.000 m +735.000 240.000 l +734.000 241.000 m +736.000 241.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +1027.00 548.20 Td +(PA0_ADC_DSPIN) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +1025.000 547.000 m +1025.000 545.000 l +1024.000 546.000 m +1026.000 546.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +1077.00 413.20 Td +(EXT_DSPOUT) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +1075.000 412.000 m +1075.000 410.000 l +1074.000 411.000 m +1076.000 411.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +1077.00 243.20 Td +(EXT_SIGOUT) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +1075.000 242.000 m +1075.000 240.000 l +1074.000 241.000 m +1076.000 241.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +735.000 241.000 m +745.000 241.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +543.56 692.49 Td +(GND) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +565.000 702.000 m +565.000 700.000 l +564.000 701.000 m +566.000 701.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +617.00 728.20 Td +(0V825) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +615.000 727.000 m +615.000 725.000 l +614.000 726.000 m +616.000 726.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +565.000 701.000 m +565.000 711.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +161.000 755.000 m +169.000 747.000 l +169.000 755.000 m +161.000 747.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +161.000 745.000 m +169.000 737.000 l +169.000 745.000 m +161.000 737.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +161.000 735.000 m +169.000 727.000 l +169.000 735.000 m +161.000 727.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +161.000 725.000 m +169.000 717.000 l +169.000 725.000 m +161.000 717.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +161.000 715.000 m +169.000 707.000 l +169.000 715.000 m +161.000 707.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +221.000 755.000 m +229.000 747.000 l +229.000 755.000 m +221.000 747.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +221.000 745.000 m +229.000 737.000 l +229.000 745.000 m +221.000 737.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +221.000 735.000 m +229.000 727.000 l +229.000 735.000 m +221.000 727.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +221.000 695.000 m +229.000 687.000 l +229.000 695.000 m +221.000 687.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +221.000 685.000 m +229.000 677.000 l +229.000 685.000 m +221.000 677.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +221.000 675.000 m +229.000 667.000 l +229.000 675.000 m +221.000 667.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +221.000 665.000 m +229.000 657.000 l +229.000 665.000 m +221.000 657.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +161.000 665.000 m +169.000 657.000 l +169.000 665.000 m +161.000 657.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +161.000 675.000 m +169.000 667.000 l +169.000 675.000 m +161.000 667.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +161.000 685.000 m +169.000 677.000 l +169.000 685.000 m +161.000 677.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +406.000 735.000 m +414.000 727.000 l +414.000 735.000 m +406.000 727.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +406.000 725.000 m +414.000 717.000 l +414.000 725.000 m +406.000 717.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +406.000 715.000 m +414.000 707.000 l +414.000 715.000 m +406.000 707.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +406.000 705.000 m +414.000 697.000 l +414.000 705.000 m +406.000 697.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +406.000 695.000 m +414.000 687.000 l +414.000 695.000 m +406.000 687.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +406.000 685.000 m +414.000 677.000 l +414.000 685.000 m +406.000 677.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +406.000 675.000 m +414.000 667.000 l +414.000 675.000 m +406.000 667.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +406.000 665.000 m +414.000 657.000 l +414.000 665.000 m +406.000 657.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +346.000 675.000 m +354.000 667.000 l +354.000 675.000 m +346.000 667.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +346.000 695.000 m +354.000 687.000 l +354.000 695.000 m +346.000 687.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +346.000 705.000 m +354.000 697.000 l +354.000 705.000 m +346.000 697.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +346.000 715.000 m +354.000 707.000 l +354.000 715.000 m +346.000 707.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +346.000 745.000 m +354.000 737.000 l +354.000 745.000 m +346.000 737.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +406.000 530.000 m +414.000 522.000 l +414.000 530.000 m +406.000 522.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +406.000 540.000 m +414.000 532.000 l +414.000 540.000 m +406.000 532.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +406.000 550.000 m +414.000 542.000 l +414.000 550.000 m +406.000 542.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +406.000 560.000 m +414.000 552.000 l +414.000 560.000 m +406.000 552.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +406.000 570.000 m +414.000 562.000 l +414.000 570.000 m +406.000 562.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +406.000 580.000 m +414.000 572.000 l +414.000 580.000 m +406.000 572.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +406.000 590.000 m +414.000 582.000 l +414.000 590.000 m +406.000 582.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +406.000 600.000 m +414.000 592.000 l +414.000 600.000 m +406.000 592.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +406.000 610.000 m +414.000 602.000 l +414.000 610.000 m +406.000 602.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +406.000 620.000 m +414.000 612.000 l +414.000 620.000 m +406.000 612.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +346.000 620.000 m +354.000 612.000 l +354.000 620.000 m +346.000 612.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +346.000 600.000 m +354.000 592.000 l +354.000 600.000 m +346.000 592.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +346.000 580.000 m +354.000 572.000 l +354.000 580.000 m +346.000 572.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +346.000 530.000 m +354.000 522.000 l +354.000 530.000 m +346.000 522.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +346.000 560.000 m +354.000 552.000 l +354.000 560.000 m +346.000 552.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +83.56 367.19 Td +(GND) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +105.000 377.000 m +105.000 375.000 l +104.000 376.000 m +106.000 376.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +207.02 398.19 Td +(EXT_DSPIN) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +205.000 397.000 m +205.000 395.000 l +204.000 396.000 m +206.000 396.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +207.01 388.19 Td +(EXT_DSPOUT) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +205.000 387.000 m +205.000 385.000 l +204.000 386.000 m +206.000 386.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +207.01 378.19 Td +(EXT_SIGOUT) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +205.000 377.000 m +205.000 375.000 l +204.000 376.000 m +206.000 376.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +290.71 272.50 Td +(PC10_LED_R) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +345.000 282.000 m +345.000 280.000 l +344.000 281.000 m +346.000 281.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +290.16 242.50 Td +(PC11_LED_G) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +345.000 252.000 m +345.000 250.000 l +344.000 251.000 m +346.000 251.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +290.70 212.50 Td +(PC12_LED_B) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +345.000 222.000 m +345.000 220.000 l +344.000 221.000 m +346.000 221.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +140.000 301.000 m +150.000 301.000 l +150.000 291.000 l +150.000 281.000 l +140.000 281.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +135.000 211.000 m +145.000 211.000 l +145.000 191.000 l +135.000 191.000 l +135.000 191.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +140.000 126.000 m +150.000 126.000 l +150.000 106.000 l +140.000 106.000 l +140.000 106.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +31.27 387.48 Td +(EXT_DSPIN_GND) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +105.000 397.000 m +105.000 395.000 l +104.000 396.000 m +106.000 396.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +105.000 396.000 m +115.000 396.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +115.000 386.000 m +105.000 386.000 l +105.000 376.000 l +115.000 376.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +205.000 376.000 m +195.000 376.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +205.000 386.000 m +195.000 386.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +205.000 396.000 m +195.000 396.000 l +S +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +759.04 553.00 Td +(20K) Tj +ET +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +759.04 562.14 Td +(R10) Tj +ET +1 J +1 j +1.00 w +0.00 G +[] 0 d +785.000 546.000 m +775.000 546.000 l +S +1 J +1 j +1.00 w +0.00 G +[] 0 d +745.000 546.000 m +755.000 546.000 l +S +2 J +0 j +100 M +1.00 w +0.53 0.00 0.00 RG +[] 0 d +755.00 550.00 20.00 -8.00 re +S +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +979.04 408.00 Td +(20K) Tj +ET +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +979.04 417.14 Td +(R17) Tj +ET +1 J +1 j +1.00 w +0.00 G +[] 0 d +1005.000 401.000 m +995.000 401.000 l +S +1 J +1 j +1.00 w +0.00 G +[] 0 d +965.000 401.000 m +975.000 401.000 l +S +2 J +0 j +100 M +1.00 w +0.53 0.00 0.00 RG +[] 0 d +975.00 405.00 20.00 -8.00 re +S +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +979.04 238.00 Td +(20K) Tj +ET +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +979.04 247.14 Td +(R22) Tj +ET +1 J +1 j +1.00 w +0.00 G +[] 0 d +1005.000 231.000 m +995.000 231.000 l +S +1 J +1 j +1.00 w +0.00 G +[] 0 d +965.000 231.000 m +975.000 231.000 l +S +2 J +0 j +100 M +1.00 w +0.53 0.00 0.00 RG +[] 0 d +975.00 235.00 20.00 -8.00 re +S +BT +/F3 12 Tf +12.00 TL +0.000 g +1.00 -0.00 0.00 1.00 955.00 583.00 Tm +(+5V) Tj +ET +1 J +1 j +1.00 w +0.00 G +0.00 g +[] 0 d +965.000 581.000 m +965.000 571.000 l +S +1 J +1 j +1.00 w +0.00 G +0.00 g +[] 0 d +960.000 581.000 m +970.000 581.000 l +S +BT +/F3 12 Tf +12.00 TL +0.000 g +1.00 -0.00 0.00 1.00 955.00 448.00 Tm +(+5V) Tj +ET +1 J +1 j +1.00 w +0.00 G +0.00 g +[] 0 d +965.000 446.000 m +965.000 436.000 l +S +1 J +1 j +1.00 w +0.00 G +0.00 g +[] 0 d +960.000 446.000 m +970.000 446.000 l +S +BT +/F3 12 Tf +12.00 TL +0.000 g +1.00 -0.00 0.00 1.00 955.00 278.00 Tm +(+5V) Tj +ET +1 J +1 j +1.00 w +0.00 G +0.00 g +[] 0 d +965.000 276.000 m +965.000 266.000 l +S +1 J +1 j +1.00 w +0.00 G +0.00 g +[] 0 d +960.000 276.000 m +970.000 276.000 l +S +BT +/F3 12 Tf +12.00 TL +0.000 g +1.00 -0.00 0.00 1.00 865.00 718.00 Tm +(+5V) Tj +ET +1 J +1 j +1.00 w +0.00 G +0.00 g +[] 0 d +875.000 716.000 m +875.000 706.000 l +S +1 J +1 j +1.00 w +0.00 G +0.00 g +[] 0 d +870.000 716.000 m +880.000 716.000 l +S +BT +/F3 12 Tf +12.00 TL +0.000 g +1.00 -0.00 0.00 1.00 1120.00 728.00 Tm +(+5V) Tj +ET +1 J +1 j +1.00 w +0.00 G +0.00 g +[] 0 d +1130.000 726.000 m +1130.000 716.000 l +S +1 J +1 j +1.00 w +0.00 G +0.00 g +[] 0 d +1125.000 726.000 m +1135.000 726.000 l +S +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +423.33 309.00 Td +(19-237/R6GHBHC-M07/2T) Tj +ET +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +423.33 318.14 Td +(LED4) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +0.00 g +[] 0 d +430.000 291.000 m +423.000 298.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +0.00 g +[] 0 d +434.000 295.000 m +427.000 302.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +423.000 298.000 m +427.000 296.000 l +425.000 294.000 l + h +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +427.000 302.000 m +431.000 300.000 l +429.000 298.000 l + h +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +412.29 282.00 Td +(1) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +405.000 281.000 m +430.000 281.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +440.000 275.000 m +430.000 281.000 l +440.000 288.000 l +h +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +0.00 g +[] 0 d +430.000 274.000 m +430.000 288.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +0.00 g +[] 0 d +430.000 261.000 m +423.000 268.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +0.00 g +[] 0 d +434.000 265.000 m +427.000 272.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +423.000 268.000 m +427.000 266.000 l +425.000 264.000 l + h +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +427.000 272.000 m +431.000 270.000 l +429.000 268.000 l + h +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +465.000 251.000 m +440.000 251.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +412.29 252.00 Td +(3) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +405.000 251.000 m +430.000 251.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +440.000 245.000 m +430.000 251.000 l +440.000 258.000 l +h +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +0.00 g +[] 0 d +430.000 244.000 m +430.000 258.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +0.00 g +[] 0 d +430.000 231.000 m +423.000 238.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +0.00 g +[] 0 d +434.000 235.000 m +427.000 242.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +423.000 238.000 m +427.000 236.000 l +425.000 234.000 l + h +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +427.000 242.000 m +431.000 240.000 l +429.000 238.000 l + h +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +412.29 222.00 Td +(4) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +405.000 221.000 m +430.000 221.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +440.000 215.000 m +430.000 221.000 l +440.000 228.000 l +h +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +0.00 g +[] 0 d +430.000 214.000 m +430.000 228.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +0.00 g +[] 0 d +440.000 281.000 m +445.000 281.000 l +445.000 221.000 l +440.000 221.000 l +S +2 J +0 j +100 M +1.00 w +0.53 0.00 0.00 RG +[] 0 d +415.00 306.00 40.00 -100.00 re +S +BT +/F3 12 Tf +12.00 TL +0.000 g +1.00 -0.00 0.00 1.00 458.00 268.00 Tm +(VCC) Tj +ET +1 J +1 j +1.00 w +0.00 G +0.00 g +[] 0 d +470.000 266.000 m +470.000 256.000 l +S +1 J +1 j +1.00 w +0.00 G +0.00 g +[] 0 d +465.000 266.000 m +475.000 266.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +465.000 251.000 m +470.000 251.000 l +470.000 256.000 l +S +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +369.03 258.00 Td +(240) Tj +ET +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +369.03 267.22 Td +(R7) Tj +ET +1 J +1 j +1.00 w +0.00 G +[] 0 d +395.000 251.000 m +385.000 251.000 l +S +1 J +1 j +1.00 w +0.00 G +[] 0 d +355.000 251.000 m +365.000 251.000 l +S +2 J +0 j +100 M +1.00 w +0.53 0.00 0.00 RG +[] 0 d +365.00 255.00 20.00 -8.00 re +S +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +369.03 288.00 Td +(511) Tj +ET +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +369.03 297.22 Td +(R6) Tj +ET +1 J +1 j +1.00 w +0.00 G +[] 0 d +395.000 281.000 m +385.000 281.000 l +S +1 J +1 j +1.00 w +0.00 G +[] 0 d +355.000 281.000 m +365.000 281.000 l +S +2 J +0 j +100 M +1.00 w +0.53 0.00 0.00 RG +[] 0 d +365.00 285.00 20.00 -8.00 re +S +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +369.03 228.00 Td +(240) Tj +ET +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +369.03 237.22 Td +(R8) Tj +ET +1 J +1 j +1.00 w +0.00 G +[] 0 d +395.000 221.000 m +385.000 221.000 l +S +1 J +1 j +1.00 w +0.00 G +[] 0 d +355.000 221.000 m +365.000 221.000 l +S +2 J +0 j +100 M +1.00 w +0.53 0.00 0.00 RG +[] 0 d +365.00 225.00 20.00 -8.00 re +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +345.000 281.000 m +355.000 281.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +345.000 251.000 m +355.000 251.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +345.000 221.000 m +355.000 221.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +395.000 221.000 m +405.000 221.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +405.000 251.000 m +400.000 251.000 l +395.000 251.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +395.000 281.000 m +405.000 281.000 l +S +BT +/F3 12 Tf +12.00 TL +0.000 g +1.00 -0.00 0.00 1.00 95.00 583.00 Tm +(+5V) Tj +ET +1 J +1 j +1.00 w +0.00 G +0.00 g +[] 0 d +105.000 581.000 m +105.000 571.000 l +S +1 J +1 j +1.00 w +0.00 G +0.00 g +[] 0 d +100.000 581.000 m +110.000 581.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +110.000 551.000 m +105.000 551.000 l +105.000 571.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +346.000 610.000 m +354.000 602.000 l +354.000 610.000 m +346.000 602.000 l +S +BT +/F3 12 Tf +12.00 TL +0.000 g +1.00 -0.00 0.00 1.00 325.00 778.00 Tm +(+5V) Tj +ET +1 J +1 j +1.00 w +0.00 G +0.00 g +[] 0 d +335.000 776.000 m +335.000 766.000 l +S +1 J +1 j +1.00 w +0.00 G +0.00 g +[] 0 d +330.000 776.000 m +340.000 776.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +335.000 766.000 m +335.000 731.000 l +350.000 731.000 l +S +BT +/F3 12 Tf +12.00 TL +0.000 g +1.00 -0.00 0.00 1.00 323.00 703.00 Tm +(VCC) Tj +ET +1 J +1 j +1.00 w +0.00 G +0.00 g +[] 0 d +335.000 701.000 m +335.000 691.000 l +S +1 J +1 j +1.00 w +0.00 G +0.00 g +[] 0 d +330.000 701.000 m +340.000 701.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +318.56 712.50 Td +(GND) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +340.000 722.000 m +340.000 720.000 l +339.000 721.000 m +341.000 721.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +340.000 721.000 m +350.000 721.000 l +S +1 J +1 j +1.00 w +0.20 0.80 0.20 RG +[] 0 d +346.000 665.000 m +354.000 657.000 l +354.000 665.000 m +346.000 657.000 l +S +BT +/F3 12 Tf +12.00 TL +0.000 g +1.00 -0.00 0.00 1.00 665.00 773.00 Tm +(+5V) Tj +ET +1 J +1 j +1.00 w +0.00 G +0.00 g +[] 0 d +675.000 771.000 m +675.000 761.000 l +S +1 J +1 j +1.00 w +0.00 G +0.00 g +[] 0 d +670.000 771.000 m +680.000 771.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +763.56 702.50 Td +(GND) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +785.000 712.000 m +785.000 710.000 l +784.000 711.000 m +786.000 711.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +802.00 748.50 Td +(VDDA) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +800.000 747.000 m +800.000 745.000 l +799.000 746.000 m +801.000 746.000 l +S +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +579.03 748.00 Td +(30K) Tj +ET +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +579.03 757.22 Td +(R4) Tj +ET +2 J +0 j +100 M +1.00 w +0.63 0.00 0.00 RG +[] 0 d +575.00 745.00 20.00 -8.00 re +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +595.000 741.000 m +605.000 741.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +575.000 741.000 m +565.000 741.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +605.000 741.000 m +605.000 711.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +615.000 726.000 m +605.000 726.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +537.08 753.50 Td +(VDDA) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +565.000 752.000 m +565.000 750.000 l +564.000 751.000 m +566.000 751.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +565.000 751.000 m +565.000 741.000 l +S +BT +/F3 12 Tf +12.00 TL +0.000 g +1.00 -0.00 0.00 1.00 488.00 143.00 Tm +(VCC) Tj +ET +1 J +1 j +1.00 w +0.00 G +0.00 g +[] 0 d +500.000 141.000 m +500.000 131.000 l +S +1 J +1 j +1.00 w +0.00 G +0.00 g +[] 0 d +495.000 141.000 m +505.000 141.000 l +S +BT +/F3 12 Tf +12.00 TL +0.000 g +1.00 -0.00 0.00 1.00 323.00 143.00 Tm +(VCC) Tj +ET +1 J +1 j +1.00 w +0.00 G +0.00 g +[] 0 d +335.000 141.000 m +335.000 131.000 l +S +1 J +1 j +1.00 w +0.00 G +0.00 g +[] 0 d +330.000 141.000 m +340.000 141.000 l +S +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +810.00 703.50 Td +(100nF) Tj +ET +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +810.00 712.50 Td +(C4) Tj +ET +1 J +1 j +1.00 w +0.63 0.00 0.00 RG +0.00 g +[] 0 d +792.000 718.000 m +808.000 718.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +800.000 726.000 m +800.000 736.000 l +S +1 J +1 j +1.00 w +0.63 0.00 0.00 RG +0.00 g +[] 0 d +800.000 706.000 m +800.000 714.000 l +S +1 J +1 j +1.00 w +0.63 0.00 0.00 RG +0.00 g +[] 0 d +808.000 714.000 m +792.000 714.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +800.000 706.000 m +800.000 696.000 l +S +1 J +1 j +1.00 w +0.63 0.00 0.00 RG +0.00 g +[] 0 d +800.000 718.000 m +800.000 726.000 l +S +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +1075.00 378.50 Td +(100nF) Tj +ET +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +1075.00 387.50 Td +(C5) Tj +ET +1 J +1 j +1.00 w +0.63 0.00 0.00 RG +0.00 g +[] 0 d +1057.000 393.000 m +1073.000 393.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +1065.000 401.000 m +1065.000 411.000 l +S +1 J +1 j +1.00 w +0.63 0.00 0.00 RG +0.00 g +[] 0 d +1065.000 381.000 m +1065.000 389.000 l +S +1 J +1 j +1.00 w +0.63 0.00 0.00 RG +0.00 g +[] 0 d +1073.000 389.000 m +1057.000 389.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +1065.000 381.000 m +1065.000 371.000 l +S +1 J +1 j +1.00 w +0.63 0.00 0.00 RG +0.00 g +[] 0 d +1065.000 393.000 m +1065.000 401.000 l +S +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +1075.00 208.50 Td +(100nF) Tj +ET +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +1075.00 217.50 Td +(C6) Tj +ET +1 J +1 j +1.00 w +0.63 0.00 0.00 RG +0.00 g +[] 0 d +1057.000 223.000 m +1073.000 223.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +1065.000 231.000 m +1065.000 241.000 l +S +1 J +1 j +1.00 w +0.63 0.00 0.00 RG +0.00 g +[] 0 d +1065.000 211.000 m +1065.000 219.000 l +S +1 J +1 j +1.00 w +0.63 0.00 0.00 RG +0.00 g +[] 0 d +1073.000 219.000 m +1057.000 219.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +1065.000 211.000 m +1065.000 201.000 l +S +1 J +1 j +1.00 w +0.63 0.00 0.00 RG +0.00 g +[] 0 d +1065.000 223.000 m +1065.000 231.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +778.56 682.49 Td +(GND) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +800.000 692.000 m +800.000 690.000 l +799.000 691.000 m +801.000 691.000 l +S +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +1039.04 418.00 Td +(33) Tj +ET +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +1039.04 427.00 Td +(R18) Tj +ET +2 J +0 j +100 M +1.00 w +0.63 0.00 0.00 RG +[] 0 d +1035.00 415.00 20.00 -8.00 re +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +1055.000 411.000 m +1065.000 411.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +1035.000 411.000 m +1025.000 411.000 l +S +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +1039.04 248.00 Td +(33) Tj +ET +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +1039.04 257.00 Td +(R23) Tj +ET +2 J +0 j +100 M +1.00 w +0.63 0.00 0.00 RG +[] 0 d +1035.00 245.00 20.00 -8.00 re +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +1055.000 241.000 m +1065.000 241.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +1035.000 241.000 m +1025.000 241.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +1075.000 411.000 m +1065.000 411.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +1075.000 241.000 m +1065.000 241.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +1043.56 357.37 Td +(GND) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +1065.000 367.000 m +1065.000 365.000 l +1064.000 366.000 m +1066.000 366.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +1043.56 187.37 Td +(GND) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +1065.000 197.000 m +1065.000 195.000 l +1064.000 196.000 m +1066.000 196.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +1065.000 366.000 m +1065.000 371.000 l +S +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +99.47 149.33 Td +(PJ-313D) Tj +ET +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +99.47 158.67 Td +(AUDIO1) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +0.00 g +[] 0 d +90.000 136.000 m +120.000 136.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +0.00 g +[] 0 d +90.000 136.000 m +90.000 126.000 l +S +2 J +0 j +100 M +1.00 w +0.53 0.00 0.00 RG +[] 0 d +86.00 126.00 8.00 -20.00 re +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +125.00 137.00 Td +(1) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +140.000 136.000 m +120.000 136.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +125.00 107.00 Td +(2) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +140.000 106.000 m +120.000 106.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +125.00 127.00 Td +(3) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +140.000 126.000 m +120.000 126.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +0.00 g +[] 0 d +120.000 126.000 m +105.000 126.000 l +102.000 122.000 l +99.000 126.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +0.00 g +[] 0 d +120.000 106.000 m +112.000 106.000 l +109.000 110.000 l +106.000 106.000 l +S +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +94.47 234.33 Td +(PJ-313D) Tj +ET +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +94.47 243.67 Td +(AUDIO2) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +0.00 g +[] 0 d +85.000 221.000 m +115.000 221.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +0.00 g +[] 0 d +85.000 221.000 m +85.000 211.000 l +S +2 J +0 j +100 M +1.00 w +0.53 0.00 0.00 RG +[] 0 d +81.00 211.00 8.00 -20.00 re +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +120.00 222.00 Td +(1) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +135.000 221.000 m +115.000 221.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +120.00 192.00 Td +(2) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +135.000 191.000 m +115.000 191.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +120.00 212.00 Td +(3) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +135.000 211.000 m +115.000 211.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +0.00 g +[] 0 d +115.000 211.000 m +100.000 211.000 l +97.000 207.000 l +94.000 211.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +0.00 g +[] 0 d +115.000 191.000 m +107.000 191.000 l +104.000 195.000 l +101.000 191.000 l +S +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +99.47 324.33 Td +(PJ-313D) Tj +ET +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +99.47 333.67 Td +(AUDIO3) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +0.00 g +[] 0 d +90.000 311.000 m +120.000 311.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +0.00 g +[] 0 d +90.000 311.000 m +90.000 301.000 l +S +2 J +0 j +100 M +1.00 w +0.53 0.00 0.00 RG +[] 0 d +86.00 301.00 8.00 -20.00 re +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +125.00 312.00 Td +(1) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +140.000 311.000 m +120.000 311.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +125.00 282.00 Td +(2) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +140.000 281.000 m +120.000 281.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +125.00 302.00 Td +(3) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +140.000 301.000 m +120.000 301.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +0.00 g +[] 0 d +120.000 301.000 m +105.000 301.000 l +102.000 297.000 l +99.000 301.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +0.00 g +[] 0 d +120.000 281.000 m +112.000 281.000 l +109.000 285.000 l +106.000 281.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +350.000 131.000 m +335.000 131.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +515.000 131.000 m +500.000 131.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +415.000 116.000 m +415.000 131.000 l +390.000 131.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +558.56 107.50 Td +(GND) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +580.000 117.000 m +580.000 115.000 l +579.000 116.000 m +581.000 116.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +580.000 116.000 m +580.000 131.000 l +555.000 131.000 l +S +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +1008.75 741.00 Td +(LM2776DBVR) Tj +ET +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +1008.75 750.00 Td +(U1) Tj +ET +1.00 w +0.53 0.00 0.00 RG +0.53 0.00 0.00 rg +[] 0 d +981.50 733.00 m 981.50 733.83 980.83 734.50 980.00 734.50 c +979.17 734.50 978.50 733.83 978.50 733.00 c +978.50 732.17 979.17 731.50 980.00 731.50 c +980.83 731.50 981.50 732.17 981.50 733.00 c +B +2 J +0 j +100 M +1.00 w +0.53 0.00 0.00 RG +[] 0 d +977.000 738.000 m +1053.000 738.000 l +1054.105 738.000 1055.000 737.105 1055.000 736.000 c +1055.000 696.000 l +1055.000 694.895 1053.895 694.000 1053.000 694.000 c +977.000 694.000 l +975.895 694.000 975.000 695.105 975.000 696.000 c +975.000 736.000 l +975.000 737.105 976.105 738.000 977.000 738.000 c +S +1.00 w +0.53 0.00 0.00 RG +0.53 0.00 0.00 rg +[] 0 d +981.50 733.00 m 981.50 733.83 980.83 734.50 980.00 734.50 c +979.17 734.50 978.50 733.83 978.50 733.00 c +978.50 732.17 979.17 731.50 980.00 731.50 c +980.83 731.50 981.50 732.17 981.50 733.00 c +B +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +978.70 722.00 Td +(VOUT) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +968.78 727.00 Td +(1) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +965.000 726.000 m +975.000 726.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 g +978.70 712.00 Td +(GND) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 g +968.78 717.00 Td +(2) Tj +ET +1 J +1 j +1.00 w +0.00 G +[] 0 d +965.000 716.000 m +975.000 716.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +978.70 702.00 Td +(VIN) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +968.78 707.00 Td +(3) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +965.000 706.000 m +975.000 706.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +1038.88 702.00 Td +(EN) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +1055.50 707.00 Td +(4) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +1065.000 706.000 m +1055.000 706.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +1031.94 712.00 Td +(C1+) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +1055.50 717.00 Td +(5) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +1065.000 716.000 m +1055.000 716.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +1035.22 722.00 Td +(C1-) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +1055.50 727.00 Td +(6) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +1065.000 726.000 m +1055.000 726.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +1130.000 716.000 m +1130.000 706.000 l +1065.000 706.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +875.000 701.000 m +875.000 706.000 l +965.000 706.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +955.000 651.000 m +955.000 716.000 l +965.000 716.000 l +S +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +1083.75 737.00 Td +(1uF) Tj +ET +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +1083.75 746.00 Td +(C1) Tj +ET +1 J +1 j +1.00 w +0.63 0.00 0.00 RG +0.00 g +[] 0 d +1088.000 718.000 m +1088.000 734.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +1080.000 726.000 m +1070.000 726.000 l +S +1 J +1 j +1.00 w +0.63 0.00 0.00 RG +0.00 g +[] 0 d +1100.000 726.000 m +1092.000 726.000 l +S +1 J +1 j +1.00 w +0.63 0.00 0.00 RG +0.00 g +[] 0 d +1092.000 734.000 m +1092.000 718.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +1100.000 726.000 m +1110.000 726.000 l +S +1 J +1 j +1.00 w +0.63 0.00 0.00 RG +0.00 g +[] 0 d +1088.000 726.000 m +1080.000 726.000 l +S +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +885.00 668.75 Td +(2.2uF) Tj +ET +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +885.00 677.75 Td +(C2) Tj +ET +1 J +1 j +1.00 w +0.63 0.00 0.00 RG +0.00 g +[] 0 d +867.000 683.000 m +883.000 683.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +875.000 691.000 m +875.000 701.000 l +S +1 J +1 j +1.00 w +0.63 0.00 0.00 RG +0.00 g +[] 0 d +875.000 671.000 m +875.000 679.000 l +S +1 J +1 j +1.00 w +0.63 0.00 0.00 RG +0.00 g +[] 0 d +883.000 679.000 m +867.000 679.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +875.000 671.000 m +875.000 661.000 l +S +1 J +1 j +1.00 w +0.63 0.00 0.00 RG +0.00 g +[] 0 d +875.000 683.000 m +875.000 691.000 l +S +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +925.00 668.75 Td +(2.2uF) Tj +ET +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +925.00 677.75 Td +(C3) Tj +ET +1 J +1 j +1.00 w +0.63 0.00 0.00 RG +0.00 g +[] 0 d +907.000 683.000 m +923.000 683.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +915.000 691.000 m +915.000 701.000 l +S +1 J +1 j +1.00 w +0.63 0.00 0.00 RG +0.00 g +[] 0 d +915.000 671.000 m +915.000 679.000 l +S +1 J +1 j +1.00 w +0.63 0.00 0.00 RG +0.00 g +[] 0 d +923.000 679.000 m +907.000 679.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +915.000 671.000 m +915.000 661.000 l +S +1 J +1 j +1.00 w +0.63 0.00 0.00 RG +0.00 g +[] 0 d +915.000 683.000 m +915.000 691.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +915.000 701.000 m +915.000 726.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +875.000 661.000 m +875.000 656.000 l +955.000 656.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +915.000 661.000 m +915.000 656.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +1065.000 726.000 m +1070.000 726.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +1065.000 716.000 m +1115.000 716.000 l +1115.000 726.000 l +1110.000 726.000 l +S +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +363.75 107.50 Td +(10K) Tj +ET +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +363.75 116.50 Td +(R1) Tj +ET +1 J +1 j +1.00 w +0.00 G +[] 0 d +350.000 131.000 m +360.000 131.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +0.00 g +[] 0 d +380.000 135.000 m +360.000 135.000 l +360.000 125.000 l +380.000 125.000 l +380.000 135.000 l +S +1 J +1 j +1.00 w +0.00 G +[] 0 d +370.000 146.000 m +370.000 136.000 l +S +1 J +1 j +1.00 w +0.00 G +[] 0 d +390.000 131.000 m +380.000 131.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +0.00 g +[] 0 d +370.000 137.000 m +370.000 142.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +0.94 g +[] 0 d +370.000 135.000 m +372.000 140.000 l +368.000 140.000 l + h +B +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +528.75 107.50 Td +(10K) Tj +ET +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +528.75 116.50 Td +(R2) Tj +ET +1 J +1 j +1.00 w +0.00 G +[] 0 d +515.000 131.000 m +525.000 131.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +0.00 g +[] 0 d +545.000 135.000 m +525.000 135.000 l +525.000 125.000 l +545.000 125.000 l +545.000 135.000 l +S +1 J +1 j +1.00 w +0.00 G +[] 0 d +535.000 146.000 m +535.000 136.000 l +S +1 J +1 j +1.00 w +0.00 G +[] 0 d +555.000 131.000 m +545.000 131.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +0.00 g +[] 0 d +535.000 137.000 m +535.000 142.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +0.94 g +[] 0 d +535.000 135.000 m +537.000 140.000 l +533.000 140.000 l + h +B +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +675.000 761.000 m +675.000 746.000 l +680.000 746.000 l +S +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +579.29 719.00 Td +(10K) Tj +ET +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +579.29 728.14 Td +(R3) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +575.000 711.000 m +565.000 711.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +595.000 711.000 m +605.000 711.000 l +S +2 J +0 j +100 M +1.00 w +0.63 0.00 0.00 RG +[] 0 d +575.00 716.00 20.00 -10.00 re +S +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +149.00 411.00 Td +(1-87215-2) Tj +ET +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +149.00 420.00 Td +(H4) Tj +ET +1.00 w +0.53 0.00 0.00 RG +0.53 0.00 0.00 rg +[] 0 d +141.50 403.00 m 141.50 403.83 140.83 404.50 140.00 404.50 c +139.17 404.50 138.50 403.83 138.50 403.00 c +138.50 402.17 139.17 401.50 140.00 401.50 c +140.83 401.50 141.50 402.17 141.50 403.00 c +B +2 J +0 j +100 M +1.00 w +0.53 0.00 0.00 RG +[] 0 d +137.000 408.000 m +173.000 408.000 l +174.105 408.000 175.000 407.105 175.000 406.000 c +175.000 368.000 l +175.000 366.895 173.895 366.000 173.000 366.000 c +137.000 366.000 l +135.895 366.000 135.000 367.105 135.000 368.000 c +135.000 406.000 l +135.000 407.105 136.105 408.000 137.000 408.000 c +S +1.00 w +0.53 0.00 0.00 RG +0.53 0.00 0.00 rg +[] 0 d +141.50 403.00 m 141.50 403.83 140.83 404.50 140.00 404.50 c +139.17 404.50 138.50 403.83 138.50 403.00 c +138.50 402.17 139.17 401.50 140.00 401.50 c +140.83 401.50 141.50 402.17 141.50 403.00 c +B +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +137.00 393.00 Td +(1) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +124.28 397.00 Td +(1) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +115.000 396.000 m +135.000 396.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +167.28 393.00 Td +(2) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +180.00 397.00 Td +(2) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +195.000 396.000 m +175.000 396.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +137.00 383.00 Td +(3) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +124.28 387.00 Td +(3) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +115.000 386.000 m +135.000 386.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +167.28 383.00 Td +(4) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +180.00 387.00 Td +(4) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +195.000 386.000 m +175.000 386.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +137.00 373.00 Td +(5) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +124.28 377.00 Td +(5) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +115.000 376.000 m +135.000 376.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +167.28 373.00 Td +(6) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +180.00 377.00 Td +(6) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +195.000 376.000 m +175.000 376.000 l +S +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +819.04 563.00 Td +(10K) Tj +ET +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +819.04 572.14 Td +(R11) Tj +ET +2 J +0 j +100 M +1.00 w +0.63 0.00 0.00 RG +[] 0 d +815.00 560.00 20.00 -8.00 re +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +835.000 556.000 m +845.000 556.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +815.000 556.000 m +805.000 556.000 l +S +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +899.04 493.00 Td +(10K) Tj +ET +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +899.04 502.14 Td +(R12) Tj +ET +2 J +0 j +100 M +1.00 w +0.63 0.00 0.00 RG +[] 0 d +895.00 490.00 20.00 -8.00 re +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +915.000 486.000 m +925.000 486.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +895.000 486.000 m +885.000 486.000 l +S +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +979.04 543.00 Td +(10K) Tj +ET +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +979.04 552.14 Td +(R13) Tj +ET +2 J +0 j +100 M +1.00 w +0.63 0.00 0.00 RG +[] 0 d +975.00 540.00 20.00 -8.00 re +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +995.000 536.000 m +1005.000 536.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +975.000 536.000 m +965.000 536.000 l +S +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +759.04 418.00 Td +(10K) Tj +ET +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +759.04 427.14 Td +(R14) Tj +ET +2 J +0 j +100 M +1.00 w +0.63 0.00 0.00 RG +[] 0 d +755.00 415.00 20.00 -8.00 re +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +775.000 411.000 m +785.000 411.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +755.000 411.000 m +745.000 411.000 l +S +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +819.04 428.00 Td +(10K) Tj +ET +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +819.04 437.14 Td +(R15) Tj +ET +2 J +0 j +100 M +1.00 w +0.63 0.00 0.00 RG +[] 0 d +815.00 425.00 20.00 -8.00 re +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +835.000 421.000 m +845.000 421.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +815.000 421.000 m +805.000 421.000 l +S +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +899.04 358.00 Td +(10K) Tj +ET +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +899.04 367.14 Td +(R16) Tj +ET +2 J +0 j +100 M +1.00 w +0.63 0.00 0.00 RG +[] 0 d +895.00 355.00 20.00 -8.00 re +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +915.000 351.000 m +925.000 351.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +895.000 351.000 m +885.000 351.000 l +S +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +759.04 248.00 Td +(10K) Tj +ET +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +759.04 257.14 Td +(R19) Tj +ET +2 J +0 j +100 M +1.00 w +0.63 0.00 0.00 RG +[] 0 d +755.00 245.00 20.00 -8.00 re +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +775.000 241.000 m +785.000 241.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +755.000 241.000 m +745.000 241.000 l +S +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +819.04 258.00 Td +(10K) Tj +ET +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +819.04 267.14 Td +(R20) Tj +ET +2 J +0 j +100 M +1.00 w +0.63 0.00 0.00 RG +[] 0 d +815.00 255.00 20.00 -8.00 re +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +835.000 251.000 m +845.000 251.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +815.000 251.000 m +805.000 251.000 l +S +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +899.04 188.00 Td +(10K) Tj +ET +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +899.04 197.14 Td +(R21) Tj +ET +2 J +0 j +100 M +1.00 w +0.63 0.00 0.00 RG +[] 0 d +895.00 185.00 20.00 -8.00 re +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +915.000 181.000 m +925.000 181.000 l +S +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +895.000 181.000 m +885.000 181.000 l +S +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +724.04 759.00 Td +(REF3333AIDBZR) Tj +ET +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +724.04 768.00 Td +(U6) Tj +ET +2 J +0 j +100 M +1.00 w +0.53 0.00 0.00 RG +[] 0 d +702.000 756.000 m +758.000 756.000 l +759.105 756.000 760.000 755.105 760.000 754.000 c +760.000 718.000 l +760.000 716.895 758.895 716.000 758.000 716.000 c +702.000 716.000 l +700.895 716.000 700.000 717.105 700.000 718.000 c +700.000 754.000 l +700.000 755.105 701.105 756.000 702.000 756.000 c +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +703.00 743.00 Td +(IN) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +688.28 747.00 Td +(1) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +680.000 746.000 m +700.000 746.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +737.79 743.00 Td +(OUT) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +766.00 747.00 Td +(2) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +780.000 746.000 m +760.000 746.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 g +736.36 723.00 Td +(GND) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 g +766.00 727.00 Td +(3) Tj +ET +1 J +1 j +1.00 w +0.00 G +[] 0 d +780.000 726.000 m +760.000 726.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +785.000 711.000 m +785.000 726.000 l +780.000 726.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +800.000 696.000 m +800.000 691.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +780.000 746.000 m +800.000 746.000 l +800.000 736.000 l +S +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +899.04 571.00 Td +(LM833DR2G) Tj +ET +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +899.04 580.00 Td +(U2) Tj +ET +1.00 w +0.53 0.00 0.00 RG +0.53 0.00 0.00 rg +[] 0 d +881.50 563.00 m 881.50 563.83 880.83 564.50 880.00 564.50 c +879.17 564.50 878.50 563.83 878.50 563.00 c +878.50 562.17 879.17 561.50 880.00 561.50 c +880.83 561.50 881.50 562.17 881.50 563.00 c +B +2 J +0 j +100 M +1.00 w +0.53 0.00 0.00 RG +[] 0 d +877.000 568.000 m +933.000 568.000 l +934.105 568.000 935.000 567.105 935.000 566.000 c +935.000 516.000 l +935.000 514.895 933.895 514.000 933.000 514.000 c +877.000 514.000 l +875.895 514.000 875.000 515.105 875.000 516.000 c +875.000 566.000 l +875.000 567.105 876.105 568.000 877.000 568.000 c +S +1.00 w +0.53 0.00 0.00 RG +0.53 0.00 0.00 rg +[] 0 d +881.50 563.00 m 881.50 563.83 880.83 564.50 880.00 564.50 c +879.17 564.50 878.50 563.83 878.50 563.00 c +878.50 562.17 879.17 561.50 880.00 561.50 c +880.83 561.50 881.50 562.17 881.50 563.00 c +B +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +878.70 552.00 Td +(OUT1) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +868.78 557.00 Td +(1) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +865.000 556.000 m +875.000 556.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +878.70 542.00 Td +(-IN1) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +868.78 547.00 Td +(2) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +865.000 546.000 m +875.000 546.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +878.70 532.00 Td +(+IN1) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +868.78 537.00 Td +(3) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +865.000 536.000 m +875.000 536.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 g +878.70 522.00 Td +(VEE) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 g +868.78 527.00 Td +(4) Tj +ET +1 J +1 j +1.00 w +0.00 G +[] 0 d +865.000 526.000 m +875.000 526.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +907.71 522.00 Td +(+IN2) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +935.50 527.00 Td +(5) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +945.000 526.000 m +935.000 526.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +910.99 532.00 Td +(-IN2) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +935.50 537.00 Td +(6) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +945.000 536.000 m +935.000 536.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +906.38 542.00 Td +(OUT2) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +935.50 547.00 Td +(7) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +945.000 546.000 m +935.000 546.000 l +S +BT +/F1 9 Tf +9.00 TL +1.000 0.000 0.000 rg +912.59 552.00 Td +(VCC) Tj +ET +BT +/F1 9 Tf +9.00 TL +1.000 0.000 0.000 rg +935.50 557.00 Td +(8) Tj +ET +1 J +1 j +1.00 w +1.00 0.00 0.00 RG +[] 0 d +945.000 556.000 m +935.000 556.000 l +S +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +899.04 436.00 Td +(LM833DR2G) Tj +ET +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +899.04 445.00 Td +(U3) Tj +ET +1.00 w +0.53 0.00 0.00 RG +0.53 0.00 0.00 rg +[] 0 d +881.50 428.00 m 881.50 428.83 880.83 429.50 880.00 429.50 c +879.17 429.50 878.50 428.83 878.50 428.00 c +878.50 427.17 879.17 426.50 880.00 426.50 c +880.83 426.50 881.50 427.17 881.50 428.00 c +B +2 J +0 j +100 M +1.00 w +0.53 0.00 0.00 RG +[] 0 d +877.000 433.000 m +933.000 433.000 l +934.105 433.000 935.000 432.105 935.000 431.000 c +935.000 381.000 l +935.000 379.895 933.895 379.000 933.000 379.000 c +877.000 379.000 l +875.895 379.000 875.000 380.105 875.000 381.000 c +875.000 431.000 l +875.000 432.105 876.105 433.000 877.000 433.000 c +S +1.00 w +0.53 0.00 0.00 RG +0.53 0.00 0.00 rg +[] 0 d +881.50 428.00 m 881.50 428.83 880.83 429.50 880.00 429.50 c +879.17 429.50 878.50 428.83 878.50 428.00 c +878.50 427.17 879.17 426.50 880.00 426.50 c +880.83 426.50 881.50 427.17 881.50 428.00 c +B +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +878.70 417.00 Td +(OUT1) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +868.78 422.00 Td +(1) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +865.000 421.000 m +875.000 421.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +878.70 407.00 Td +(-IN1) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +868.78 412.00 Td +(2) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +865.000 411.000 m +875.000 411.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +878.70 397.00 Td +(+IN1) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +868.78 402.00 Td +(3) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +865.000 401.000 m +875.000 401.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 g +878.70 387.00 Td +(VEE) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 g +868.78 392.00 Td +(4) Tj +ET +1 J +1 j +1.00 w +0.00 G +[] 0 d +865.000 391.000 m +875.000 391.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +907.71 387.00 Td +(+IN2) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +935.50 392.00 Td +(5) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +945.000 391.000 m +935.000 391.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +910.99 397.00 Td +(-IN2) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +935.50 402.00 Td +(6) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +945.000 401.000 m +935.000 401.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +906.38 407.00 Td +(OUT2) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +935.50 412.00 Td +(7) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +945.000 411.000 m +935.000 411.000 l +S +BT +/F1 9 Tf +9.00 TL +1.000 0.000 0.000 rg +912.59 417.00 Td +(VCC) Tj +ET +BT +/F1 9 Tf +9.00 TL +1.000 0.000 0.000 rg +935.50 422.00 Td +(8) Tj +ET +1 J +1 j +1.00 w +1.00 0.00 0.00 RG +[] 0 d +945.000 421.000 m +935.000 421.000 l +S +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +899.04 266.00 Td +(LM833DR2G) Tj +ET +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +899.04 275.00 Td +(U4) Tj +ET +1.00 w +0.53 0.00 0.00 RG +0.53 0.00 0.00 rg +[] 0 d +881.50 258.00 m 881.50 258.83 880.83 259.50 880.00 259.50 c +879.17 259.50 878.50 258.83 878.50 258.00 c +878.50 257.17 879.17 256.50 880.00 256.50 c +880.83 256.50 881.50 257.17 881.50 258.00 c +B +2 J +0 j +100 M +1.00 w +0.53 0.00 0.00 RG +[] 0 d +877.000 263.000 m +933.000 263.000 l +934.105 263.000 935.000 262.105 935.000 261.000 c +935.000 211.000 l +935.000 209.895 933.895 209.000 933.000 209.000 c +877.000 209.000 l +875.895 209.000 875.000 210.105 875.000 211.000 c +875.000 261.000 l +875.000 262.105 876.105 263.000 877.000 263.000 c +S +1.00 w +0.53 0.00 0.00 RG +0.53 0.00 0.00 rg +[] 0 d +881.50 258.00 m 881.50 258.83 880.83 259.50 880.00 259.50 c +879.17 259.50 878.50 258.83 878.50 258.00 c +878.50 257.17 879.17 256.50 880.00 256.50 c +880.83 256.50 881.50 257.17 881.50 258.00 c +B +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +878.70 247.00 Td +(OUT1) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +868.78 252.00 Td +(1) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +865.000 251.000 m +875.000 251.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +878.70 237.00 Td +(-IN1) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +868.78 242.00 Td +(2) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +865.000 241.000 m +875.000 241.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +878.70 227.00 Td +(+IN1) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +868.78 232.00 Td +(3) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +865.000 231.000 m +875.000 231.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 g +878.70 217.00 Td +(VEE) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 g +868.78 222.00 Td +(4) Tj +ET +1 J +1 j +1.00 w +0.00 G +[] 0 d +865.000 221.000 m +875.000 221.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +907.71 217.00 Td +(+IN2) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +935.50 222.00 Td +(5) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +945.000 221.000 m +935.000 221.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +910.99 227.00 Td +(-IN2) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +935.50 232.00 Td +(6) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +945.000 231.000 m +935.000 231.000 l +S +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +906.38 237.00 Td +(OUT2) Tj +ET +BT +/F1 9 Tf +9.00 TL +0.000 0.000 1.000 rg +935.50 242.00 Td +(7) Tj +ET +1 J +1 j +1.00 w +0.53 0.00 0.00 RG +[] 0 d +945.000 241.000 m +935.000 241.000 l +S +BT +/F1 9 Tf +9.00 TL +1.000 0.000 0.000 rg +912.59 247.00 Td +(VCC) Tj +ET +BT +/F1 9 Tf +9.00 TL +1.000 0.000 0.000 rg +935.50 252.00 Td +(8) Tj +ET +1 J +1 j +1.00 w +1.00 0.00 0.00 RG +[] 0 d +945.000 251.000 m +935.000 251.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +808.62 497.37 Td +(VIN_-5V) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +845.000 507.000 m +845.000 505.000 l +844.000 506.000 m +846.000 506.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +771.27 527.37 Td +(EXT_DSPIN_GND) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +845.000 537.000 m +845.000 535.000 l +844.000 536.000 m +846.000 536.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +967.00 528.63 Td +(0V825) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +965.000 527.000 m +965.000 525.000 l +964.000 526.000 m +966.000 526.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +845.000 536.000 m +865.000 536.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +965.000 526.000 m +945.000 526.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +965.000 571.000 m +965.000 556.000 l +945.000 556.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +845.000 506.000 m +845.000 526.000 l +865.000 526.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +865.000 556.000 m +855.000 556.000 l +855.000 486.000 l +885.000 486.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +925.000 486.000 m +955.000 486.000 l +955.000 536.000 l +945.000 536.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +945.000 546.000 m +1015.000 546.000 l +1015.000 536.000 l +1005.000 536.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +965.000 536.000 m +955.000 536.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +845.000 556.000 m +855.000 556.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +805.000 556.000 m +795.000 556.000 l +795.000 546.000 l +865.000 546.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +785.000 546.000 m +795.000 546.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +735.000 546.000 m +745.000 546.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +1025.000 546.000 m +1015.000 546.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +808.62 362.37 Td +(VIN_-5V) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +845.000 372.000 m +845.000 370.000 l +844.000 371.000 m +846.000 371.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +735.000 411.000 m +745.000 411.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +805.000 421.000 m +795.000 421.000 l +795.000 411.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +845.000 421.000 m +865.000 421.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +845.000 401.000 m +865.000 401.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +845.000 371.000 m +845.000 391.000 l +865.000 391.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +885.000 351.000 m +855.000 351.000 l +855.000 421.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +925.000 351.000 m +955.000 351.000 l +955.000 401.000 l +945.000 401.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +965.000 391.000 m +945.000 391.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +965.000 401.000 m +955.000 401.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +945.000 411.000 m +1015.000 411.000 l +1015.000 401.000 l +1005.000 401.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +945.000 421.000 m +965.000 421.000 l +965.000 436.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +1025.000 411.000 m +1015.000 411.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +845.000 411.000 m +805.000 411.000 l +785.000 411.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +845.000 411.000 m +865.000 411.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +1065.000 196.000 m +1065.000 201.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +865.000 251.000 m +845.000 251.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +785.000 241.000 m +865.000 241.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +805.000 251.000 m +795.000 251.000 l +795.000 241.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +845.000 231.000 m +865.000 231.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +845.000 196.000 m +845.000 221.000 l +865.000 221.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +885.000 181.000 m +855.000 181.000 l +855.000 251.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +925.000 181.000 m +955.000 181.000 l +955.000 231.000 l +945.000 231.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +965.000 221.000 m +945.000 221.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +965.000 231.000 m +955.000 231.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +965.000 266.000 m +965.000 251.000 l +945.000 251.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +1025.000 241.000 m +1020.000 241.000 l +945.000 241.000 l +S +1 J +1 j +1.00 w +0.00 0.53 0.00 RG +0.00 g +[] 0 d +1005.000 231.000 m +1015.000 231.000 l +1015.000 241.000 l +S +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +507.00 539.58 Td +(TESTPAD50) Tj +ET +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +507.00 548.58 Td +(P1) Tj +ET +1 J +1 j +1.00 w +0.65 0.29 0.29 RG +0.00 g +[] 0 d +500.000 541.160 m +505.000 546.160 l +S +1 J +1 j +1.00 w +0.65 0.29 0.29 RG +0.00 g +[] 0 d +505.000 546.160 m +500.000 551.160 l +S +1 J +1 j +1.00 w +0.65 0.29 0.29 RG +0.00 g +[] 0 d +500.000 551.160 m +495.000 546.160 l +S +1 J +1 j +1.00 w +0.65 0.29 0.29 RG +0.00 g +[] 0 d +495.000 546.160 m +500.000 541.160 l +S +1 J +1 j +1.00 w +0.65 0.29 0.29 RG +[] 0 d +502.500 546.157 m +502.49 547.54 501.37 548.65 499.99 548.64 c +498.61 548.64 497.49 547.51 497.50 546.13 c +497.51 544.75 498.63 543.64 500.01 543.64 c +501.38 543.65 502.49 544.76 502.50 546.13 c +S +1 J +1 j +1.00 w +0.65 0.29 0.29 RG +[] 0 d +500.000 561.000 m +500.000 551.158 l +S +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +507.00 499.58 Td +(TESTPAD50) Tj +ET +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +507.00 508.58 Td +(P2) Tj +ET +1 J +1 j +1.00 w +0.65 0.29 0.29 RG +0.00 g +[] 0 d +500.000 501.160 m +505.000 506.160 l +S +1 J +1 j +1.00 w +0.65 0.29 0.29 RG +0.00 g +[] 0 d +505.000 506.160 m +500.000 511.160 l +S +1 J +1 j +1.00 w +0.65 0.29 0.29 RG +0.00 g +[] 0 d +500.000 511.160 m +495.000 506.160 l +S +1 J +1 j +1.00 w +0.65 0.29 0.29 RG +0.00 g +[] 0 d +495.000 506.160 m +500.000 501.160 l +S +1 J +1 j +1.00 w +0.65 0.29 0.29 RG +[] 0 d +502.500 506.157 m +502.49 507.54 501.37 508.65 499.99 508.64 c +498.61 508.64 497.49 507.51 497.50 506.13 c +497.51 504.75 498.63 503.64 500.01 503.64 c +501.38 503.65 502.49 504.76 502.50 506.13 c +S +1 J +1 j +1.00 w +0.65 0.29 0.29 RG +[] 0 d +500.000 521.000 m +500.000 511.158 l +S +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +507.00 464.58 Td +(TESTPAD50) Tj +ET +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +507.00 473.58 Td +(P3) Tj +ET +1 J +1 j +1.00 w +0.65 0.29 0.29 RG +0.00 g +[] 0 d +500.000 466.160 m +505.000 471.160 l +S +1 J +1 j +1.00 w +0.65 0.29 0.29 RG +0.00 g +[] 0 d +505.000 471.160 m +500.000 476.160 l +S +1 J +1 j +1.00 w +0.65 0.29 0.29 RG +0.00 g +[] 0 d +500.000 476.160 m +495.000 471.160 l +S +1 J +1 j +1.00 w +0.65 0.29 0.29 RG +0.00 g +[] 0 d +495.000 471.160 m +500.000 466.160 l +S +1 J +1 j +1.00 w +0.65 0.29 0.29 RG +[] 0 d +502.500 471.157 m +502.49 472.54 501.37 473.65 499.99 473.64 c +498.61 473.64 497.49 472.51 497.50 471.13 c +497.51 469.75 498.63 468.64 500.01 468.64 c +501.38 468.65 502.49 469.76 502.50 471.13 c +S +1 J +1 j +1.00 w +0.65 0.29 0.29 RG +[] 0 d +500.000 486.000 m +500.000 476.158 l +S +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +507.00 429.58 Td +(TESTPAD50) Tj +ET +10.00 w +BT +/F2 9 Tf +9.00 TL +0.000 0.000 0.502 rg +507.00 438.58 Td +(P4) Tj +ET +1 J +1 j +1.00 w +0.65 0.29 0.29 RG +0.00 g +[] 0 d +500.000 431.160 m +505.000 436.160 l +S +1 J +1 j +1.00 w +0.65 0.29 0.29 RG +0.00 g +[] 0 d +505.000 436.160 m +500.000 441.160 l +S +1 J +1 j +1.00 w +0.65 0.29 0.29 RG +0.00 g +[] 0 d +500.000 441.160 m +495.000 436.160 l +S +1 J +1 j +1.00 w +0.65 0.29 0.29 RG +0.00 g +[] 0 d +495.000 436.160 m +500.000 431.160 l +S +1 J +1 j +1.00 w +0.65 0.29 0.29 RG +[] 0 d +502.500 436.157 m +502.49 437.54 501.37 438.65 499.99 438.64 c +498.61 438.64 497.49 437.51 497.50 436.13 c +497.51 434.75 498.63 433.64 500.01 433.64 c +501.38 433.65 502.49 434.76 502.50 436.13 c +S +1 J +1 j +1.00 w +0.65 0.29 0.29 RG +[] 0 d +500.000 451.000 m +500.000 441.158 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +502.00 488.50 Td +(VDDA) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +500.000 487.000 m +500.000 485.000 l +499.000 486.000 m +501.000 486.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +478.56 453.50 Td +(GND) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +500.000 452.000 m +500.000 450.000 l +499.000 451.000 m +501.000 451.000 l +S +BT +/F3 12 Tf +12.00 TL +0.000 g +1.00 -0.00 0.00 1.00 490.00 573.00 Tm +(+5V) Tj +ET +1 J +1 j +1.00 w +0.00 G +0.00 g +[] 0 d +500.000 571.000 m +500.000 561.000 l +S +1 J +1 j +1.00 w +0.00 G +0.00 g +[] 0 d +495.000 571.000 m +505.000 571.000 l +S +BT +/F3 9 Tf +9.00 TL +0.000 0.000 1.000 rg +502.00 523.50 Td +(VIN_-5V) Tj +ET +1 J +1 j +0.10 w +0.00 G +[] 0 d +500.000 522.000 m +500.000 520.000 l +499.000 521.000 m +501.000 521.000 l +S +0.80 0.00 0.00 rg +177.50 591.00 m 177.50 592.38 176.38 593.50 175.00 593.50 c +173.62 593.50 172.50 592.38 172.50 591.00 c +172.50 589.62 173.62 588.50 175.00 588.50 c +176.38 588.50 177.50 589.62 177.50 591.00 c +f +0.80 0.00 0.00 rg +167.50 471.00 m 167.50 472.38 166.38 473.50 165.00 473.50 c +163.62 473.50 162.50 472.38 162.50 471.00 c +162.50 469.62 163.62 468.50 165.00 468.50 c +166.38 468.50 167.50 469.62 167.50 471.00 c +f +0.80 0.00 0.00 rg +177.50 471.00 m 177.50 472.38 176.38 473.50 175.00 473.50 c +173.62 473.50 172.50 472.38 172.50 471.00 c +172.50 469.62 173.62 468.50 175.00 468.50 c +176.38 468.50 177.50 469.62 177.50 471.00 c +f +0.80 0.00 0.00 rg +607.50 726.00 m 607.50 727.38 606.38 728.50 605.00 728.50 c +603.62 728.50 602.50 727.38 602.50 726.00 c +602.50 724.62 603.62 723.50 605.00 723.50 c +606.38 723.50 607.50 724.62 607.50 726.00 c +f +0.80 0.00 0.00 rg +1067.50 411.00 m 1067.50 412.38 1066.38 413.50 1065.00 413.50 c +1063.62 413.50 1062.50 412.38 1062.50 411.00 c +1062.50 409.62 1063.62 408.50 1065.00 408.50 c +1066.38 408.50 1067.50 409.62 1067.50 411.00 c +f +0.80 0.00 0.00 rg +877.50 706.00 m 877.50 707.38 876.38 708.50 875.00 708.50 c +873.62 708.50 872.50 707.38 872.50 706.00 c +872.50 704.62 873.62 703.50 875.00 703.50 c +876.38 703.50 877.50 704.62 877.50 706.00 c +f +0.80 0.00 0.00 rg +917.50 726.00 m 917.50 727.38 916.38 728.50 915.00 728.50 c +913.62 728.50 912.50 727.38 912.50 726.00 c +912.50 724.62 913.62 723.50 915.00 723.50 c +916.38 723.50 917.50 724.62 917.50 726.00 c +f +0.80 0.00 0.00 rg +957.50 656.00 m 957.50 657.38 956.38 658.50 955.00 658.50 c +953.62 658.50 952.50 657.38 952.50 656.00 c +952.50 654.62 953.62 653.50 955.00 653.50 c +956.38 653.50 957.50 654.62 957.50 656.00 c +f +0.80 0.00 0.00 rg +917.50 656.00 m 917.50 657.38 916.38 658.50 915.00 658.50 c +913.62 658.50 912.50 657.38 912.50 656.00 c +912.50 654.62 913.62 653.50 915.00 653.50 c +916.38 653.50 917.50 654.62 917.50 656.00 c +f +0.80 0.00 0.00 rg +957.50 536.00 m 957.50 537.38 956.38 538.50 955.00 538.50 c +953.62 538.50 952.50 537.38 952.50 536.00 c +952.50 534.62 953.62 533.50 955.00 533.50 c +956.38 533.50 957.50 534.62 957.50 536.00 c +f +0.80 0.00 0.00 rg +857.50 556.00 m 857.50 557.38 856.38 558.50 855.00 558.50 c +853.62 558.50 852.50 557.38 852.50 556.00 c +852.50 554.62 853.62 553.50 855.00 553.50 c +856.38 553.50 857.50 554.62 857.50 556.00 c +f +0.80 0.00 0.00 rg +797.50 546.00 m 797.50 547.38 796.38 548.50 795.00 548.50 c +793.62 548.50 792.50 547.38 792.50 546.00 c +792.50 544.62 793.62 543.50 795.00 543.50 c +796.38 543.50 797.50 544.62 797.50 546.00 c +f +0.80 0.00 0.00 rg +1017.50 546.00 m 1017.50 547.38 1016.38 548.50 1015.00 548.50 c +1013.62 548.50 1012.50 547.38 1012.50 546.00 c +1012.50 544.62 1013.62 543.50 1015.00 543.50 c +1016.38 543.50 1017.50 544.62 1017.50 546.00 c +f +0.80 0.00 0.00 rg +797.50 411.00 m 797.50 412.38 796.38 413.50 795.00 413.50 c +793.62 413.50 792.50 412.38 792.50 411.00 c +792.50 409.62 793.62 408.50 795.00 408.50 c +796.38 408.50 797.50 409.62 797.50 411.00 c +f +0.80 0.00 0.00 rg +857.50 421.00 m 857.50 422.38 856.38 423.50 855.00 423.50 c +853.62 423.50 852.50 422.38 852.50 421.00 c +852.50 419.62 853.62 418.50 855.00 418.50 c +856.38 418.50 857.50 419.62 857.50 421.00 c +f +0.80 0.00 0.00 rg +957.50 401.00 m 957.50 402.38 956.38 403.50 955.00 403.50 c +953.62 403.50 952.50 402.38 952.50 401.00 c +952.50 399.62 953.62 398.50 955.00 398.50 c +956.38 398.50 957.50 399.62 957.50 401.00 c +f +0.80 0.00 0.00 rg +1017.50 411.00 m 1017.50 412.38 1016.38 413.50 1015.00 413.50 c +1013.62 413.50 1012.50 412.38 1012.50 411.00 c +1012.50 409.62 1013.62 408.50 1015.00 408.50 c +1016.38 408.50 1017.50 409.62 1017.50 411.00 c +f +0.80 0.00 0.00 rg +797.50 241.00 m 797.50 242.38 796.38 243.50 795.00 243.50 c +793.62 243.50 792.50 242.38 792.50 241.00 c +792.50 239.62 793.62 238.50 795.00 238.50 c +796.38 238.50 797.50 239.62 797.50 241.00 c +f +0.80 0.00 0.00 rg +857.50 251.00 m 857.50 252.38 856.38 253.50 855.00 253.50 c +853.62 253.50 852.50 252.38 852.50 251.00 c +852.50 249.62 853.62 248.50 855.00 248.50 c +856.38 248.50 857.50 249.62 857.50 251.00 c +f +0.80 0.00 0.00 rg +957.50 231.00 m 957.50 232.38 956.38 233.50 955.00 233.50 c +953.62 233.50 952.50 232.38 952.50 231.00 c +952.50 229.62 953.62 228.50 955.00 228.50 c +956.38 228.50 957.50 229.62 957.50 231.00 c +f +0.80 0.00 0.00 rg +1017.50 241.00 m 1017.50 242.38 1016.38 243.50 1015.00 243.50 c +1013.62 243.50 1012.50 242.38 1012.50 241.00 c +1012.50 239.62 1013.62 238.50 1015.00 238.50 c +1016.38 238.50 1017.50 239.62 1017.50 241.00 c +f +0.80 0.00 0.00 rg +1067.50 241.00 m 1067.50 242.38 1066.38 243.50 1065.00 243.50 c +1063.62 243.50 1062.50 242.38 1062.50 241.00 c +1062.50 239.62 1063.62 238.50 1065.00 238.50 c +1066.38 238.50 1067.50 239.62 1067.50 241.00 c +f +endstream +endobj +1 0 obj +<> +endobj +5 0 obj +<< +/Descent -209 +/CapHeight 727 +/StemV 0 +/Type /FontDescriptor +/Flags 32 +/FontBBox [-559 -303 1446 1050] +/FontName /Verdana +/ItalicAngle 0 +/Ascent 1005 +>> +endobj +6 0 obj +<> +endobj +7 0 obj +<< +/Descent -325 +/CapHeight 500 +/StemV 80 +/Type /FontDescriptor +/Flags 32 +/FontBBox [-665 -325 2000 1006] +/FontName /Arial +/ItalicAngle 0 +/Ascent 1006 +>> +endobj +8 0 obj +<> +endobj +9 0 obj +<< +/Type /Font +/BaseFont /Times-Roman +/Subtype /Type1 +/Encoding /WinAnsiEncoding +/FirstChar 32 +/LastChar 255 +>> +endobj +2 0 obj +<< +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +/Font << +/F1 6 0 R +/F2 8 0 R +/F3 9 0 R +>> +/XObject << +>> +>> +endobj +10 0 obj +<< +/Producer (jsPDF 0.0.0) +/CreationDate (D:20210928184609-04'00') +>> +endobj +11 0 obj +<< +/Type /Catalog +/Pages 1 0 R +/OpenAction [3 0 R /FitH null] +/PageLayout /OneColumn +>> +endobj +xref +0 12 +0000000000 65535 f +0000099104 00000 n +0000101725 00000 n +0000000015 00000 n +0000000125 00000 n +0000099161 00000 n +0000099331 00000 n +0000100385 00000 n +0000100554 00000 n +0000101598 00000 n +0000101849 00000 n +0000101935 00000 n +trailer +<< +/Size 12 +/Root 11 0 R +/Info 10 0 R +/ID [ <15C4C120BFEB88FA4193BB26708B8A50> <15C4C120BFEB88FA4193BB26708B8A50> ] +>> +startxref +102039 +%%EOF \ No newline at end of file From 3dd57491b1e81a9d93054eff19ca0e6c65c85b9b Mon Sep 17 00:00:00 2001 From: Clyne Sullivan Date: Sat, 20 Nov 2021 14:29:08 -0500 Subject: [PATCH 13/13] fixed signal generator input data streaming --- source/communication.cpp | 25 +++++++++++++------------ source/periph/dac.cpp | 13 ++++++++++++- source/periph/dac.hpp | 1 + 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/source/communication.cpp b/source/communication.cpp index ec02a42..b5ee28e 100644 --- a/source/communication.cpp +++ b/source/communication.cpp @@ -112,22 +112,23 @@ void updateGenerator(unsigned char *cmd) if (EM.assert(USBSerial::read(&cmd[1], 2) == 2, Error::BadParamSize)) { unsigned int count = cmd[1] | (cmd[2] << 8); if (EM.assert(count <= MAX_SAMPLE_BUFFER_SIZE, Error::BadParam)) { - if (run_status == RunStatus::Idle) { + if (!DAC::isSigGenRunning()) { Samples::Generator.setSize(count); USBSerial::read( reinterpret_cast(Samples::Generator.data()), Samples::Generator.bytesize()); - } else if (run_status == RunStatus::Running) { - int more; - do { - chThdSleepMicroseconds(10); - more = DAC::sigGenWantsMore(); - } while (more == -1); - - // Receive streamed samples in half-buffer chunks. - USBSerial::read(reinterpret_cast( - more == 0 ? Samples::Generator.data() : Samples::Generator.middata()), - Samples::Generator.bytesize() / 2); + } else { + const int more = DAC::sigGenWantsMore(); + if (more == -1) { + USBSerial::write(reinterpret_cast("\0"), 1); + } else { + USBSerial::write(reinterpret_cast("\1"), 1); + + // Receive streamed samples in half-buffer chunks. + USBSerial::read(reinterpret_cast( + more == 0 ? Samples::Generator.data() : Samples::Generator.middata()), + Samples::Generator.bytesize() / 2); + } } } } diff --git a/source/periph/dac.cpp b/source/periph/dac.cpp index 1ff8867..35c2908 100644 --- a/source/periph/dac.cpp +++ b/source/periph/dac.cpp @@ -61,7 +61,18 @@ void DAC::start(int channel, dacsample_t *buffer, size_t count) int DAC::sigGenWantsMore() { - return dacIsDone; + if (dacIsDone != -1) { + int tmp = dacIsDone; + dacIsDone = -1; + return tmp; + } else { + return -1; + } +} + +int DAC::isSigGenRunning() +{ + return m_driver[1]->state == DAC_ACTIVE; } void DAC::stop(int channel) diff --git a/source/periph/dac.hpp b/source/periph/dac.hpp index 4360c26..7250a52 100644 --- a/source/periph/dac.hpp +++ b/source/periph/dac.hpp @@ -24,6 +24,7 @@ public: static void stop(int channel); static int sigGenWantsMore(); + static int isSigGenRunning(); private: static DACDriver *m_driver[2];