v / vlib / builtin
Raw file | 207 loc (189 sloc) | 4.9 KB | Latest commit hash 7df8f063e
1// Copyright (c) 2019-2023 Alexander Medvednikov. All rights reserved.
2// Use of this source code is governed by an MIT license that can be found in the LICENSE file.
3module builtin
4
5// TODO implement compile time conditional include
6// [if !nofloat]
7import strconv
8
9#include <float.h>
10/*
11-----------------------------------
12----- f64 to string functions -----
13*/
14// str return a `f64` as `string` in suitable notation.
15[inline]
16pub fn (x f64) str() string {
17 unsafe {
18 f := strconv.Float64u{
19 f: x
20 }
21 if f.u == strconv.double_minus_zero {
22 return '-0.0'
23 }
24 if f.u == strconv.double_plus_zero {
25 return '0.0'
26 }
27 }
28 abs_x := f64_abs(x)
29 if abs_x >= 0.0001 && abs_x < 1.0e6 {
30 return strconv.f64_to_str_l(x)
31 } else {
32 return strconv.ftoa_64(x)
33 }
34}
35
36// strg return a `f64` as `string` in "g" printf format
37[inline]
38pub fn (x f64) strg() string {
39 if x == 0 {
40 return '0.0'
41 }
42 abs_x := f64_abs(x)
43 if abs_x >= 0.0001 && abs_x < 1.0e6 {
44 return strconv.f64_to_str_l_with_dot(x)
45 } else {
46 return strconv.ftoa_64(x)
47 }
48}
49
50// str returns the value of the `float_literal` as a `string`.
51[inline]
52pub fn (d float_literal) str() string {
53 return f64(d).str()
54}
55
56// strsci returns the `f64` as a `string` in scientific notation with `digit_num` decimals displayed, max 17 digits.
57// Example: assert f64(1.234).strsci(3) == '1.234e+00'
58[inline]
59pub fn (x f64) strsci(digit_num int) string {
60 mut n_digit := digit_num
61 if n_digit < 1 {
62 n_digit = 1
63 } else if n_digit > 17 {
64 n_digit = 17
65 }
66 return strconv.f64_to_str(x, n_digit)
67}
68
69// strlong returns a decimal notation of the `f64` as a `string`.
70// Example: assert f64(1.23456).strlong() == '1.23456'
71[inline]
72pub fn (x f64) strlong() string {
73 return strconv.f64_to_str_l(x)
74}
75
76/*
77-----------------------------------
78----- f32 to string functions -----
79*/
80// str returns a `f32` as `string` in suitable notation.
81[inline]
82pub fn (x f32) str() string {
83 unsafe {
84 f := strconv.Float32u{
85 f: x
86 }
87 if f.u == strconv.single_minus_zero {
88 return '-0.0'
89 }
90 if f.u == strconv.single_plus_zero {
91 return '0.0'
92 }
93 }
94 abs_x := f32_abs(x)
95 if abs_x >= 0.0001 && abs_x < 1.0e6 {
96 return strconv.f32_to_str_l(x)
97 } else {
98 return strconv.ftoa_32(x)
99 }
100}
101
102// strg return a `f32` as `string` in "g" printf format
103[inline]
104pub fn (x f32) strg() string {
105 if x == 0 {
106 return '0.0'
107 }
108 abs_x := f32_abs(x)
109 if abs_x >= 0.0001 && abs_x < 1.0e6 {
110 return strconv.f32_to_str_l_with_dot(x)
111 } else {
112 return strconv.ftoa_32(x)
113 }
114}
115
116// strsci returns the `f32` as a `string` in scientific notation with `digit_num` decimals displayed, max 8 digits.
117// Example: assert f32(1.234).strsci(3) == '1.234e+00'
118[inline]
119pub fn (x f32) strsci(digit_num int) string {
120 mut n_digit := digit_num
121 if n_digit < 1 {
122 n_digit = 1
123 } else if n_digit > 8 {
124 n_digit = 8
125 }
126 return strconv.f32_to_str(x, n_digit)
127}
128
129// strlong returns a decimal notation of the `f32` as a `string`.
130[inline]
131pub fn (x f32) strlong() string {
132 return strconv.f32_to_str_l(x)
133}
134
135/*
136-----------------------
137----- C functions -----
138*/
139// f32_abs returns the absolute value of `a` as a `f32` value.
140// Example: assert f32_abs(-2.0) == 2.0
141[inline]
142pub fn f32_abs(a f32) f32 {
143 return if a < 0 { -a } else { a }
144}
145
146// f64_abs returns the absolute value of `a` as a `f64` value.
147// Example: assert f64_abs(-2.0) == f64(2.0)
148[inline]
149fn f64_abs(a f64) f64 {
150 return if a < 0 { -a } else { a }
151}
152
153// f32_max returns the largest `f32` of input `a` and `b`.
154// Example: assert f32_max(2.0,3.0) == 3.0
155[inline]
156pub fn f32_max(a f32, b f32) f32 {
157 return if a > b { a } else { b }
158}
159
160// f32_min returns the smallest `f32` of input `a` and `b`.
161// Example: assert f32_min(2.0,3.0) == 2.0
162[inline]
163pub fn f32_min(a f32, b f32) f32 {
164 return if a < b { a } else { b }
165}
166
167// f64_max returns the largest `f64` of input `a` and `b`.
168// Example: assert f64_max(2.0,3.0) == 3.0
169[inline]
170pub fn f64_max(a f64, b f64) f64 {
171 return if a > b { a } else { b }
172}
173
174// f64_min returns the smallest `f64` of input `a` and `b`.
175// Example: assert f64_min(2.0,3.0) == 2.0
176[inline]
177fn f64_min(a f64, b f64) f64 {
178 return if a < b { a } else { b }
179}
180
181// eq_epsilon returns true if the `f32` is equal to input `b`.
182// using an epsilon of typically 1E-5 or higher (backend/compiler dependent).
183// Example: assert f32(2.0).eq_epsilon(2.0)
184[inline]
185pub fn (a f32) eq_epsilon(b f32) bool {
186 hi := f32_max(f32_abs(a), f32_abs(b))
187 delta := f32_abs(a - b)
188 if hi > f32(1.0) {
189 return delta <= hi * (4 * f32(C.FLT_EPSILON))
190 } else {
191 return (1 / (4 * f32(C.FLT_EPSILON))) * delta <= hi
192 }
193}
194
195// eq_epsilon returns true if the `f64` is equal to input `b`.
196// using an epsilon of typically 1E-9 or higher (backend/compiler dependent).
197// Example: assert f64(2.0).eq_epsilon(2.0)
198[inline]
199pub fn (a f64) eq_epsilon(b f64) bool {
200 hi := f64_max(f64_abs(a), f64_abs(b))
201 delta := f64_abs(a - b)
202 if hi > 1.0 {
203 return delta <= hi * (4 * f64(C.DBL_EPSILON))
204 } else {
205 return (1 / (4 * f64(C.DBL_EPSILON))) * delta <= hi
206 }
207}