<|start_filename|>include/simdtools.h<|end_filename|>
// libsimdtools -- Tools for vector math - SSE and AVX.
// Copyright (C) 2015 <NAME>
// Report bugs, etc at: https://github.com/andersx/simd-exp
//
// This is free and unencumbered software released into the public domain.
//
// Anyone is free to copy, modify, publish, use, compile, sell, or
// distribute this software, either in source code form or as a compiled
// binary, for any purpose, commercial or non-commercial, and by any
// means.
//
// In jurisdictions that recognize copyright laws, the author or authors
// of this software dedicate any and all copyright interest in the
// software to the public domain. We make this dedication for the benefit
// of the public at large and to the detriment of our heirs and
// successors. We intend this dedication to be an overt act of
// relinquishment in perpetuity of all present and future rights to this
// software under copyright law.
//
// 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 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.
//
// For more information, please refer to <http://unlicense.org>


#ifndef INCLUDE_SIMD_TOOLS_H
#define INCLUDE_SIMD_TOOLS_H

#include <stdio.h>
#include <immintrin.h>


namespace simdmath {


    // Prints a __m256 vector to std out.
    static void _mm256_print_si256(const __m256i &q) {

        int * temp;
        _mm256_storeu_si256((__m256i*)temp, q);

        printf("0: %16.10f  1: %16.10f  2: %16.10f  3: %16.10f\n",
                temp, temp + 1, temp +1 , temp + 3);

        // printf("4: %16.10f  5: %16.10f  6: %16.10f  7: %16.10f\n",
        //         temp[4], temp[5], temp[6], temp[7]);

    }


    // Prints a __m256 vector to std out.
    static void _mm256_print_ps(const __m256 &q) {

        float temp[8];
        _mm256_store_ps(temp, q);

        printf("0: %16.10f  1: %16.10f  2: %16.10f  3: %16.10f\n",
                temp[0], temp[1], temp[2], temp[3]);

        printf("4: %16.10f  5: %16.10f  6: %16.10f  7: %16.10f\n",
                temp[4], temp[5], temp[6], temp[7]);

    }


    // Return the lowest element from a __m256 vector as float.
    static float _mm256_minelement_ps(const __m256 &q) {

        float temp[8];
        _mm256_store_ps(temp, q);

        float min = temp[0];

        for (unsigned int i = 1; i < 8; i++) {

            if (temp[i] < min) min = temp[i];
        }

        return min;

    }


    // Return the largest element from a __m256 vector as float.
    static float _mm256_maxelement_ps(const __m256 &q) {

        float temp[8];
        _mm256_store_ps(temp, q);

        float max = temp[0];

        for (unsigned int i = 1; i < 8; i++) {

            if (temp[i] > max) max = temp[i];
        }

        return max;

    }


} // namespace simdmath


#endif // INCLUDE_SIMD_TOOLS_H


<|start_filename|>graphs/exp_graph.cpp<|end_filename|>
// Copyright (C) 2015 <NAME>
// Report bugs, etc at: https://github.com/andersx/simd-exp
//
// This is free and unencumbered software released into the public domain.
//
// Anyone is free to copy, modify, publish, use, compile, sell, or
// distribute this software, either in source code form or as a compiled
// binary, for any purpose, commercial or non-commercial, and by any
// means.
//
// In jurisdictions that recognize copyright laws, the author or authors
// of this software dedicate any and all copyright interest in the
// software to the public domain. We make this dedication for the benefit
// of the public at large and to the detriment of our heirs and
// successors. We intend this dedication to be an overt act of
// relinquishment in perpetuity of all present and future rights to this
// software under copyright law.
//
// 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 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.
//
// For more information, please refer to <http://unlicense.org>


#include <stdio.h>
#include <immintrin.h>
#include <iostream>
#include <math.h> 

#include "../include/simdexp.h"
#include "../include/simdrsqrt.h"
#include "../include/simdtools.h"

int main() {


    __m256 ONE = _mm256_set1_ps(1.0f);
    __m256 ONE_HUNDRED = _mm256_set1_ps(100.0f);

    for (float i = -63.0f; i < 63.0f; i += 0.001f) {


        __m256 t = _mm256_set1_ps(i);

        __m256 rcp = _mm256_mul_ps(ONE_HUNDRED, _mm256_sub_ps(_mm256_div_ps(_mm256_rcp_ps(t), _mm256_div_ps(ONE, t)), ONE));
        __m256 rcp1s = _mm256_mul_ps(ONE_HUNDRED, _mm256_sub_ps(_mm256_div_ps(simdmath::_mm256_rcp1s_ps(t), _mm256_div_ps(ONE, t)), ONE));
        __m256 rsqrt = _mm256_mul_ps(ONE_HUNDRED, _mm256_sub_ps(_mm256_div_ps(_mm256_rsqrt_ps(t), _mm256_div_ps(ONE, _mm256_sqrt_ps(t))), ONE));
        __m256 rsqrt1s = _mm256_mul_ps(ONE_HUNDRED, _mm256_sub_ps(_mm256_div_ps(simdmath::_mm256_rsqrt1s_ps(t), _mm256_div_ps(ONE, _mm256_sqrt_ps(t))), ONE));
        __m256 expfast = _mm256_mul_ps(ONE_HUNDRED, _mm256_sub_ps(_mm256_div_ps(simdmath::_mm256_expfast_ps(t), _mm256_exp_ps(t)), ONE));
        __m256 expfast1s = _mm256_mul_ps(ONE_HUNDRED, _mm256_sub_ps(_mm256_div_ps(simdmath::_mm256_expfast1s_ps(t), _mm256_exp_ps(t)), ONE));
        __m256 expfaster = _mm256_mul_ps(ONE_HUNDRED, _mm256_sub_ps(_mm256_div_ps(simdmath::_mm256_expfaster_ps(t), _mm256_exp_ps(t)), ONE));

        float tvec[8];

        float frcp[8];
        float frcp1s[8];
        float frsqrt[8];
        float frsqrt1s[8];
        float fexpfast[8];
        float fexpfast1s[8];
        float fexpfaster[8];

        _mm256_store_ps(tvec, t); 
        _mm256_store_ps(frcp, rcp);
        _mm256_store_ps(frcp1s, rcp1s);
        _mm256_store_ps(frsqrt, rsqrt);
        _mm256_store_ps(frsqrt1s, rsqrt1s);
        _mm256_store_ps(fexpfast, expfast);
        _mm256_store_ps(fexpfast1s, expfast1s);
        _mm256_store_ps(fexpfaster, expfaster);



        printf("%16.10f %16.10f  %16.10f  %16.10f  %16.10f  %16.10f  %16.10f  %16.10f \n", tvec[0], frcp[0], frcp1s[0],
                frsqrt[0], frsqrt1s[0], fexpfast[0], fexpfast1s[0], fexpfaster[0]);


    }

    return 0;

}




<|start_filename|>include/simdrcp.h<|end_filename|>
// libsimdrcp -- Approximate RCP(x) implementations for SSE and AVX.
// Copyright (C) 2015 <NAME>
// Report bugs, etc at: https://github.com/andersx/simd-exp
//
// This is free and unencumbered software released into the public domain.
// 
// Anyone is free to copy, modify, publish, use, compile, sell, or
// distribute this software, either in source code form or as a compiled
// binary, for any purpose, commercial or non-commercial, and by any
// means.
// 
// In jurisdictions that recognize copyright laws, the author or authors
// of this software dedicate any and all copyright interest in the
// software to the public domain. We make this dedication for the benefit
// of the public at large and to the detriment of our heirs and
// successors. We intend this dedication to be an overt act of
// relinquishment in perpetuity of all present and future rights to this
// software under copyright law.
// 
// 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 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.
// 
// For more information, please refer to <http://unlicense.org>


#ifndef LIB_SIMD_DIV
#define LIB_SIMD_DIV

#include <immintrin.h>


namespace simdmath {

    // Approximation for 1/x -- Newtons method to 1st order.
    // using an AVX2-intrinsic function as initial guess.
    // Speed inbetween _mm256_rcp_ps(x) and _mm256_div_ps(ONE, x).
    // Practically same accuracy as _mm256_div_ps(ONE, x).
    // Probably the only useful function in this header.
    // Error of _mm256_rcp1s_ps is 0.00001%.
    // In comparison Error of intrinsic _mm256_rcp_ps is 0.02%.
    static inline __m256 _mm256_rcp1s_ps(const __m256 &q) {

        const __m256 TWO = _mm256_set1_ps(2.0f);

        __m256 rcp = _mm256_rcp_ps(q);
        rcp = _mm256_mul_ps(rcp, _mm256_fnmadd_ps(rcp, q, TWO));

        return rcp;

    }


    // Approximation for 1/x -- Newtons method to 0th order.
    // Same speed as _mm256_rcp_ps(), but not as accurate.
    // Error of _mm256_rcp0_ps is about 3%.
    static inline __m256 _mm256_rcp0_ps(const __m256 &q) {

        const __m256 TWO = _mm256_set1_ps(2.0f);
        const __m256i MAGIC_NUMBER = _mm256_set1_epi32(0x7EF311C2);

        __m256i x = _mm256_castps_si256(q);
        x = _mm256_sub_epi32(MAGIC_NUMBER, x);
        __m256 rcp = _mm256_castsi256_ps(x);

        return rcp;

    }


    // Approximation for 1/x -- Newtons method to 1th order.
    // Slightly slower than _mm256_rcp_ps(), but not as accurate.
    // Error of _mm256_rcp1_ps is about 0.2%.
    static inline __m256 _mm256_rcp1_ps(const __m256 &q) {

        const __m256 TWO = _mm256_set1_ps(2.0f);
        const __m256i MAGIC_NUMBER = _mm256_set1_epi32(0x7EF311C3);

        __m256i x = _mm256_castps_si256(q);
        x = _mm256_sub_epi32(MAGIC_NUMBER, x);
        __m256 rcp = _mm256_castsi256_ps(x);

        rcp = _mm256_mul_ps(rcp, _mm256_fnmadd_ps(rcp, q, TWO));

        return rcp;

    }


    // Approximation for 1/x -- Newtons method to 2nd order
    // Slightly faster than as _mm256_div_ps(ONE, x), but not as accurate.
    // More accurate than _mm256_rcp_ps().
    // Error of _mm256_rcp2_ps is about 0.001%.
    static inline __m256 _mm256_rcp2_ps(const __m256 &q) {

        const __m256 TWO = _mm256_set1_ps(2.0f);
        const __m256i MAGIC_NUMBER = _mm256_set1_epi32(0x7EF312AC);

        __m256i x = _mm256_castps_si256(q);
        x = _mm256_sub_epi32(MAGIC_NUMBER, x);
        __m256 rcp = _mm256_castsi256_ps(x);

        rcp = _mm256_mul_ps(rcp, _mm256_fnmadd_ps(rcp, q, TWO));
        rcp = _mm256_mul_ps(rcp, _mm256_fnmadd_ps(rcp, q, TWO));

        return rcp;

    }


    // Approximation for 1/x -- Newtons method to 3rd order.
    // Slower than _mm256_div_ps(ONE, x), and just as accurate.
    // Error of _mm256_rcp3_ps is about 0.00001%.
    static inline __m256 _mm256_rcp3_ps(const __m256 &q) {

        const __m256 TWO = _mm256_set1_ps(2.0f);
        const __m256i MAGIC_NUMBER = _mm256_set1_epi32(0x7EEEEBB3);

        __m256i x = _mm256_castps_si256(q);
        x = _mm256_sub_epi32(MAGIC_NUMBER, x);
        __m256 rcp = _mm256_castsi256_ps(x);

        rcp = _mm256_mul_ps(rcp, _mm256_fnmadd_ps(rcp, q, TWO));
        rcp = _mm256_mul_ps(rcp, _mm256_fnmadd_ps(rcp, q, TWO));
        rcp = _mm256_mul_ps(rcp, _mm256_fnmadd_ps(rcp, q, TWO));

        return rcp;

    }


    // Approximation for 1/x -- Newtons method to 4th order.
    // Much slower than _mm256_div_ps(ONE, x), and just as accurate.
    // Error of _mm256_rcp4_ps is about 0.00001%.
    static inline __m256 _mm256_rcp4_ps(const __m256 &q) {

        const __m256 TWO = _mm256_set1_ps(2.0f);
        const __m256i MAGIC_NUMBER = _mm256_set1_epi32(0x7EEEEEEE);

        __m256i x = _mm256_castps_si256(q);
        x = _mm256_sub_epi32(MAGIC_NUMBER, x);
        __m256 rcp = _mm256_castsi256_ps(x);

        rcp = _mm256_mul_ps(rcp, _mm256_fnmadd_ps(rcp, q, TWO));
        rcp = _mm256_mul_ps(rcp, _mm256_fnmadd_ps(rcp, q, TWO));
        rcp = _mm256_mul_ps(rcp, _mm256_fnmadd_ps(rcp, q, TWO));
        rcp = _mm256_mul_ps(rcp, _mm256_fnmadd_ps(rcp, q, TWO));

        return rcp;

    }

}

#endif



<|start_filename|>test/test.cpp<|end_filename|>
// Copyright (C) 2015 <NAME>
// Report bugs, etc at: https://github.com/andersx/simd-exp
//
// This is free and unencumbered software released into the public domain.
//
// Anyone is free to copy, modify, publish, use, compile, sell, or
// distribute this software, either in source code form or as a compiled
// binary, for any purpose, commercial or non-commercial, and by any
// means.
//
// In jurisdictions that recognize copyright laws, the author or authors
// of this software dedicate any and all copyright interest in the
// software to the public domain. We make this dedication for the benefit
// of the public at large and to the detriment of our heirs and
// successors. We intend this dedication to be an overt act of
// relinquishment in perpetuity of all present and future rights to this
// software under copyright law.
//
// 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 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.
//
// For more information, please refer to <http://unlicense.org>


#include <iostream>

#include "test_rcp.h"
#include "test_exp.h"
#include "test_rsqrt.h"


int main() {

    srand(time(NULL));

    int failed_tests = 0;

    failed_tests += test_mm256_rcp_ps();
    failed_tests += test_mm256_rcp1s_ps();
    failed_tests += test_mm256_expfaster_ps();
    failed_tests += test_mm256_expfast_ps();
    failed_tests += test_mm256_expfast1s_ps();
    failed_tests += test_mm256_rsqrt_ps();
    failed_tests += test_mm256_rsqrt1s_ps();

    std::cout << "Number of failed tests: " << failed_tests << std::endl;

    return 0;

}





<|start_filename|>include/simdrsqrt.h<|end_filename|>
// libsimdrsqrt -- Approximate RSQRT(x) implementations for Intel AVX.
// Copyright (C) 2015 <NAME>
// Report bugs, etc at: https://github.com/andersx/simd-exp
//
// This is free and unencumbered software released into the public domain.
//
// Anyone is free to copy, modify, publish, use, compile, sell, or
// distribute this software, either in source code form or as a compiled
// binary, for any purpose, commercial or non-commercial, and by any
// means.
//
// In jurisdictions that recognize copyright laws, the author or authors
// of this software dedicate any and all copyright interest in the
// software to the public domain. We make this dedication for the benefit
// of the public at large and to the detriment of our heirs and
// successors. We intend this dedication to be an overt act of
// relinquishment in perpetuity of all present and future rights to this
// software under copyright law.
//
// 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 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.
//
// For more information, please refer to <http://unlicense.org>


#ifndef INCLUDE_SIMD_RSQRT_H
#define INCLUDE_SIMD_RSQRT_H

#include <immintrin.h>


namespace simdmath {


    // Approximation to 1/sqrt(x) -- accurate to 32-bit precision,
    // but faster than the exact _mm256_div_ps(ONE, _mm256_sqrt_ps(x)).
    // Error is about 0.00002%
    static inline __m256 _mm256_rsqrt1s_ps(const __m256 &q) {

        const __m256 HALF = _mm256_set1_ps(0.5f);
        const __m256 THREE = _mm256_set1_ps(3.0f);

        // Initial guess from intrinsic rsqrt.
        __m256 rsqrt = _mm256_rsqrt_ps(q);

        // Add one iteration of Newton-Raphson.
        return _mm256_mul_ps(HALF, _mm256_mul_ps(rsqrt, 
                    _mm256_fnmadd_ps( _mm256_mul_ps(rsqrt, rsqrt), q, THREE)));

    }


}


#endif // INCLUDE_SIMD_EXP_H


<|start_filename|>graphs/optimize.cpp<|end_filename|>
// Copyright (C) 2015 <NAME>
// Report bugs, etc at: https://github.com/andersx/simd-exp
//
// This is free and unencumbered software released into the public domain.
//
// Anyone is free to copy, modify, publish, use, compile, sell, or
// distribute this software, either in source code form or as a compiled
// binary, for any purpose, commercial or non-commercial, and by any
// means.
//
// In jurisdictions that recognize copyright laws, the author or authors
// of this software dedicate any and all copyright interest in the
// software to the public domain. We make this dedication for the benefit
// of the public at large and to the detriment of our heirs and
// successors. We intend this dedication to be an overt act of
// relinquishment in perpetuity of all present and future rights to this
// software under copyright law.
//
// 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 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.
//
// For more information, please refer to <http://unlicense.org>


#include <stdio.h>
#include <immintrin.h>
#include <iostream>
#include <math.h> 
#include <time.h> 

#include "../include/simdexp.h"
#include "../include/simdtools.h"
#include "../test/test_common.h"

int main() {

    srand (time(NULL));

    __m256 ONE = _mm256_set1_ps(1.0f);
    __m256 ONE_HUNDRED = _mm256_set1_ps(100.0f);


    // float C1 = 1064872507.1541044f;
    // float C2 = 12102203.161561485f;

    float C1 = 1064870507.1541044f;
    float C2 = 12102000.161561485f;

    unsigned int steps = 100

    for (unsigned int n = 0.0; n < steps; 



    __m256 C1v = _mm256_set1_ps(C1);
    __m256 C2v = _mm256_set1_ps(C2);


    __m256 error_sum = _mm256_set1_ps(0.0f);

    __m256 c = _mm256_set1_ps(0.0f);
    
    for (unsigned int i = 0; i < 10000000; i++) {

        __m256 q = generate_vector(-63.0f, 63.0f);
    
        __m256 approx = _mm256_castsi256_ps(_mm256_cvttps_epi32(_mm256_fmadd_ps(C2v, q, C1v)));
        __m256 exact = _mm256_exp_ps(q);
        
        __m256 error =_mm256_sub_ps(ONE_HUNDRED, _mm256_mul_ps(ONE_HUNDRED, _mm256_div_ps(approx, exact)));
        error = _mm256_mul_ps(error, error);
       
       __m256 y = _mm256_sub_ps(error, c);
       __m256 t = _mm256_add_ps(error_sum, y);
       c =  _mm256_sub_ps(_mm256_sub_ps(t, error_sum), y);
       error_sum = t;


    }

        float tvec[8];
        _mm256_store_ps(tvec, error_sum); 

        float e = tvec[0] + tvec[1] + tvec[2] + tvec[3] + tvec[4] + tvec[5] + tvec[6] + tvec[7];

        std::cout << e << std::endl;


    return 0;

}




<|start_filename|>test/test_common.h<|end_filename|>
// Copyright (C) 2015 <NAME>
// Report bugs, etc at: https://github.com/andersx/simd-exp
//
// This is free and unencumbered software released into the public domain.
//
// Anyone is free to copy, modify, publish, use, compile, sell, or
// distribute this software, either in source code form or as a compiled
// binary, for any purpose, commercial or non-commercial, and by any
// means.
//
// In jurisdictions that recognize copyright laws, the author or authors
// of this software dedicate any and all copyright interest in the
// software to the public domain. We make this dedication for the benefit
// of the public at large and to the detriment of our heirs and
// successors. We intend this dedication to be an overt act of
// relinquishment in perpetuity of all present and future rights to this
// software under copyright law.
//
// 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 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.
//
// For more information, please refer to <http://unlicense.org>


#ifndef LIB_SIMD_TEST_COMMON_H
#define LIB_SIMD_TEST_COMMON_H

#include <stdlib.h>
#include <cstdlib>

#include "../include/simdtools.h"


using namespace simdmath;

// Lowest guaranteed accuracy of a float in %.
const float FLOAT_ACCURACY = 0.00002f;


// Return a random float in a given range.
float rand_float(float min, float max) {

    return ((max-min)*((float)rand()/RAND_MAX))+min;

}


// Return a SIMD-vector of random floats in a given range.
__m256 generate_vector(float min, float max) {

     return _mm256_set_ps(rand_float(min, max), rand_float(min, max),
                          rand_float(min, max), rand_float(min, max), 
                          rand_float(min, max), rand_float(min, max),
                          rand_float(min, max), rand_float(min, max));

}    


// Run a test case, given the input vector, the approximate and
// exact results for a function and a given target accuracy [%].
float compare_results(__m256 input, __m256 approx, 
                      __m256 exact, float accuracy) {

    // Calculate error in %.
    __m256 error = _mm256_mul_ps(_mm256_set1_ps(100.0f),
                   _mm256_div_ps(approx, exact));


    // Print input-vector.
    std::cout << "Random input:" << std::endl; 
    _mm256_print_ps(input);

    // Print error.
    std::cout << "Ratio deviation[%]:      Allowed error = " << accuracy << std::endl;
    _mm256_print_ps(error);

    // Determine if error is withing target accuracy.
    if ((_mm256_maxelement_ps(error) > 100.0f + accuracy) ||
        (_mm256_minelement_ps(error) < 100.0f - accuracy)) {

        std::cout << "FAILED ..." << std::endl;
        std::cout << std::endl;
        _mm256_print_ps(approx);
        _mm256_print_ps(exact);
        return 1;

    } else {

        std::cout << "PASSED ..." << std::endl;
        std::cout << std::endl;
        return 0;

    }

}


#endif // LIB_SIMD_TEST_COMMON_H


<|start_filename|>test/test_rcp.h<|end_filename|>
// Test cases for libsimdrcp
// Report bugs, etc at: https://github.com/andersx/simd-exp
//
// The MIT License (MIT)
// 
// Copyright (C) 2015 <NAME>
// 
// 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.


#ifndef LIB_SIMD_TEST_RCP_H
#define LIB_SIMD_TEST_RCP_H

#include <iostream>

#include "../include/simdrcp.h"
#include "../include/simdtools.h"
#include "test_common.h"


// Test case for the function _mm256_rcp1s_ps()
static int test_mm256_rcp1s_ps() {

    // Target accuracy
    const float accuracy = FLOAT_ACCURACY;

    // Random input data
    __m256 input = generate_vector(-10000.0f, 10000.0f);

    // Exact value of 1/x
    __m256 exact = _mm256_div_ps(_mm256_set1_ps(1.0f), input);

    // Approximate value of 1/x
    __m256 approx = _mm256_rcp1s_ps(input);

    // Print and run test
    std::cout << "Testing: _mm256_rcp1s_ps()      -10000.0 < x 10000.0" << std::endl;
    return compare_results(input, approx, exact, accuracy);

}


// Test case for the intrinsic function _mm256_rcp_ps()
static int test_mm256_rcp_ps() {

    // Target accuracy
    const float accuracy = 0.04f;

    // Generate random input
    __m256 input = generate_vector(-10000.0f, 10000.0f);

    // Exact value of 1/x
    __m256 exact = _mm256_div_ps(_mm256_set1_ps(1.0f), input);

    // Approximate value of 1/x
    __m256 approx = _mm256_rcp_ps(input);

    // Print and run test
    std::cout << "Testing: _mm256_rcp_ps()      -10000.0 < x 10000.0" << std::endl;
    return compare_results(input, approx, exact, accuracy);

}


#endif // LIB_SIMD_TEST_RCP_H


<|start_filename|>Makefile<|end_filename|>
GXX=g++
ICPC=icpc

GCC_AVX_FLAGS=-O3 -mavx2 -mfma -ffast-math
INTEL_AVX_FLAGS=-O3 -fma -march=core-avx2

all: test-intel

test-gcc:
	mkdir -p bin/
	$(GXX) test/test.cpp -o bin/test $(GCC_AVX_FLAGS)
	bin/test

test-intel:
	mkdir -p bin/
	$(ICPC) test/test.cpp -o bin/test $(INTEL_AVX_FLAGS)
	bin/test

clean:
	@rm bin/test



<|start_filename|>test/test_rsqrt.h<|end_filename|>
// Test cases for libsimdrsqrt
// Report bugs, etc at: https://github.com/andersx/simd-exp
//
// The MIT License (MIT)
// 
// Copyright (C) 2015 <NAME>
// 
// 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.


#ifndef LIB_SIMD_TEST_RSQRT_H
#define LIB_SIMD_TEST_RSQRT_H

#include <iostream>

#include "../include/simdrsqrt.h"
#include "../include/simdtools.h"
#include "test_common.h"


// Test case for the intrinsic function _mm256_rsqrt_ps()
static int test_mm256_rsqrt_ps() {

    // Target accuracy
    const float accuracy = 0.03f;

    // Random input data
    __m256 input = generate_vector(0.0f, 10000.0f);

    // Exact value of 1/sqrt(x)
    __m256 exact = _mm256_div_ps(_mm256_set1_ps(1.0f), _mm256_sqrt_ps(input));

    // Approximate value of 1/sqrt(x)
    __m256 approx = _mm256_rsqrt_ps(input);

    // Print and run test
    std::cout << "Testing: _mm256_rsqrt_ps()      0.0 < x 10000.0" << std::endl;
    return compare_results(input, approx, exact, accuracy);

}


// Test case for the function _mm256_rsqrt1s_ps()
static int test_mm256_rsqrt1s_ps() {

    // Target accuracy
    const float accuracy = FLOAT_ACCURACY;

    // Random input data
    __m256 input = generate_vector(0.0f, 10000.0f);

    // Exact value of 1/sqrt(x)
    __m256 exact = _mm256_div_ps(_mm256_set1_ps(1.0f), _mm256_sqrt_ps(input));

    // Approximate value of 1/sqrt(x)
    __m256 approx = _mm256_rsqrt1s_ps(input);

    // Print and run test
    std::cout << "Testing: _mm256_rsqrt1s_ps()      0.0 < x 10000.0" << std::endl;
    return compare_results(input, approx, exact, accuracy);

}


#endif // LIB_SIMD_TEST_COMMON_H
