1 /* 2 * Copyright (c) 2019 Vestas Wind Systems A/S 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 #include <math.h> 8 #include <stdint.h> 9 #include <stdio.h> 10 #include <stdlib.h> 11 #include <zephyr/sys/util.h> 12 13 #define MAX_D_ITTERATIONS 8 /* usually converges in 5 loops */ 14 /* this ensures we break out of the loop */ 15 #define MAX_D_ERROR_COUNT 5 /* when result almost converges, stop */ 16 #define EXP_MASK64 GENMASK64(62, 52) 17 18 typedef union { 19 double d; 20 int64_t i; 21 } int64double_t; 22 sqrt(double square)23double sqrt(double square) 24 { 25 int i; 26 int64_t exponent; 27 int64double_t root; 28 int64double_t last; 29 int64double_t p_square; 30 31 p_square.d = square; 32 33 if (square == 0.0) { 34 return square; 35 } 36 if (square < 0.0) { 37 return (square - square) / (square - square); 38 } 39 40 /* we need a good starting guess so that this will converge quickly, 41 * we can do this by dividing the exponent part of the float by 2 42 * this assumes IEEE-754 format doubles 43 */ 44 exponent = ((p_square.i & EXP_MASK64) >> 52) - 1023; 45 if (exponent == 0x7FF - 1023) { 46 /* the number is a NAN or inf, return NaN or inf */ 47 return square + square; 48 } 49 exponent /= 2; 50 root.i = (p_square.i & ~EXP_MASK64) | (exponent + 1023) << 52; 51 52 for (i = 0; i < MAX_D_ITTERATIONS; i++) { 53 last = root; 54 root.d = (root.d + square / root.d) * 0.5; 55 /* if (llabs(*p_root-*p_last)<MAX_D_ERROR_COUNT) */ 56 if ((root.i ^ last.i) < MAX_D_ERROR_COUNT) { 57 break; 58 } 59 } 60 return root.d; 61 } 62