╭ math.zig ─────────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭ find file ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╮ ╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │ │ │http│ ssh │ │ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╯ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
1 const builtin = @import("builtin"); 2 3 const std = @import("std"); 4 const math = std.math; 5 const ld = math.long_double; 6 7 const symbol = @import("../c.zig").symbol; 8 9 comptime { 10 if (builtin.target.isMinGW()) { 11 symbol(&isnan, "isnan"); 12 symbol(&isnan, "__isnan"); 13 symbol(&isnanf, "isnanf"); 14 symbol(&isnanf, "__isnanf"); 15 symbol(&isnanl, "isnanl"); 16 symbol(&isnanl, "__isnanl"); 17 18 symbol(&math.floatTrueMin(f64), "__DENORM"); 19 symbol(&math.inf(f64), "__INF"); 20 symbol(&math.nan(f64), "__QNAN"); 21 symbol(&math.snan(f64), "__SNAN"); 22 23 symbol(&math.floatTrueMin(f32), "__DENORMF"); 24 symbol(&math.inf(f32), "__INFF"); 25 symbol(&math.nan(f32), "__QNANF"); 26 symbol(&math.snan(f32), "__SNANF"); 27 28 symbol(&math.floatTrueMin(c_longdouble), "__DENORML"); 29 symbol(&math.inf(c_longdouble), "__INFL"); 30 symbol(&math.nan(c_longdouble), "__QNANL"); 31 symbol(&math.snan(c_longdouble), "__SNANL"); 32 } 33 34 if (builtin.target.isMinGW() or builtin.target.isMuslLibC() or builtin.target.isWasiLibC()) { 35 symbol(&frexpf, "frexpf"); 36 symbol(&frexpl, "frexpl"); 37 symbol(&hypotf, "hypotf"); 38 symbol(&hypotl, "hypotl"); 39 symbol(&lrintl, "lrintl"); 40 symbol(&lroundl, "lroundl"); 41 symbol(&modfl, "modfl"); 42 symbol(&rintl, "rintl"); 43 } 44 45 if ((builtin.target.isMinGW() and @sizeOf(f64) != @sizeOf(c_longdouble)) or builtin.target.isMuslLibC() or builtin.target.isWasiLibC()) { 46 symbol(&atanl, "atanl"); 47 symbol(&copysignl, "copysignl"); 48 symbol(&fdiml, "fdiml"); 49 symbol(&nanl, "nanl"); 50 } 51 52 if ((builtin.target.isMinGW() and builtin.cpu.arch == .x86) or builtin.target.isMuslLibC() or builtin.target.isWasiLibC()) { 53 symbol(&acosf, "acosf"); 54 symbol(&atanf, "atanf"); 55 symbol(&coshf, "coshf"); 56 symbol(&modff, "modff"); 57 symbol(&tanhf, "tanhf"); 58 } 59 60 if (builtin.target.isMuslLibC() or builtin.target.isWasiLibC()) { 61 symbol(&acos, "acos"); 62 symbol(&acoshf, "acoshf"); 63 symbol(&asin, "asin"); 64 symbol(&atan, "atan"); 65 symbol(&cbrt, "cbrt"); 66 symbol(&cbrtf, "cbrtf"); 67 symbol(&cosh, "cosh"); 68 symbol(&exp10, "exp10"); 69 symbol(&exp10f, "exp10f"); 70 symbol(&fdim, "fdim"); 71 symbol(&fdimf, "fdimf"); 72 symbol(&finite, "finite"); 73 symbol(&finitef, "finitef"); 74 symbol(&frexp, "frexp"); 75 symbol(&hypot, "hypot"); 76 symbol(&log1p, "log1p"); 77 symbol(&log1pf, "log1pf"); 78 symbol(&lrint, "lrint"); 79 symbol(&lrintf, "lrintf"); 80 symbol(&lround, "lround"); 81 symbol(&lroundf, "lroundf"); 82 symbol(&modf, "modf"); 83 symbol(&nan, "nan"); 84 symbol(&nanf, "nanf"); 85 symbol(&pow10, "pow10"); 86 symbol(&pow10f, "pow10f"); 87 symbol(&tanh, "tanh"); 88 } 89 90 if (builtin.target.isMuslLibC()) { 91 symbol(&copysign, "copysign"); 92 symbol(&copysignf, "copysignf"); 93 symbol(&rint, "rint"); 94 symbol(&rintf, "rintf"); 95 } 96 } 97 98 fn acos(x: f64) callconv(.c) f64 { 99 return math.acos(x); 100 } 101 102 fn acosf(x: f32) callconv(.c) f32 { 103 return math.acos(x); 104 } 105 106 fn acoshf(x: f32) callconv(.c) f32 { 107 return math.acosh(x); 108 } 109 110 fn asin(x: f64) callconv(.c) f64 { 111 return math.asin(x); 112 } 113 114 fn atan(x: f64) callconv(.c) f64 { 115 return math.atan(x); 116 } 117 118 fn atanf(x: f32) callconv(.c) f32 { 119 return math.atan(x); 120 } 121 122 fn atanl(x: c_longdouble) callconv(.c) c_longdouble { 123 return switch (@typeInfo(c_longdouble).float.bits) { 124 64 => std.c.atan(x), 125 else => math.atan(x), 126 }; 127 } 128 129 fn cbrt(x: f64) callconv(.c) f64 { 130 return math.cbrt(x); 131 } 132 133 fn cbrtf(x: f32) callconv(.c) f32 { 134 return math.cbrt(x); 135 } 136 137 fn copysign(x: f64, y: f64) callconv(.c) f64 { 138 return math.copysign(x, y); 139 } 140 141 fn copysignf(x: f32, y: f32) callconv(.c) f32 { 142 return math.copysign(x, y); 143 } 144 145 fn copysignl(x: c_longdouble, y: c_longdouble) callconv(.c) c_longdouble { 146 return switch (@typeInfo(c_longdouble).float.bits) { 147 64 => std.c.copysign(x, y), 148 else => math.copysign(x, y), 149 }; 150 } 151 152 fn cosh(x: f64) callconv(.c) f64 { 153 return math.cosh(x); 154 } 155 156 fn coshf(x: f32) callconv(.c) f32 { 157 return math.cosh(x); 158 } 159 160 fn exp10(x: f64) callconv(.c) f64 { 161 return math.pow(f64, 10.0, x); 162 } 163 164 fn exp10f(x: f32) callconv(.c) f32 { 165 return math.pow(f32, 10.0, x); 166 } 167 168 fn fdimGeneric(comptime T: type, x: T, y: T) T { 169 if (math.isNan(x)) 170 return x; 171 172 if (math.isNan(y)) 173 return y; 174 175 if (x > y) 176 return x - y; 177 return 0; 178 } 179 180 fn fdim(x: f64, y: f64) callconv(.c) f64 { 181 return fdimGeneric(f64, x, y); 182 } 183 184 fn fdimf(x: f32, y: f32) callconv(.c) f32 { 185 return fdimGeneric(f32, x, y); 186 } 187 188 fn fdiml(x: c_longdouble, y: c_longdouble) callconv(.c) c_longdouble { 189 return switch (@typeInfo(c_longdouble).float.bits) { 190 64 => std.c.fdim(x, y), 191 else => fdimGeneric(c_longdouble, x, y), 192 }; 193 } 194 195 fn finite(x: f64) callconv(.c) c_int { 196 return @intFromBool(math.isFinite(x)); 197 } 198 199 fn finitef(x: f32) callconv(.c) c_int { 200 return @intFromBool(math.isFinite(x)); 201 } 202 203 fn frexpGeneric(comptime T: type, x: T, e: *c_int) T { 204 // libc expects `*e` to be unspecified in this case; an unspecified C value 205 // should be a valid value of the relevant type, yet Zig's std 206 // implementation sets it to `undefined` -- which can even be nonsense 207 // according to the type (int). Therefore, we're setting it to a valid 208 // int value in Zig -- a zero. 209 // 210 // This mirrors the handling of infinities, where libc also expects 211 // unspecified for the value of `*e` and Zig std sets it to a zero. 212 if (math.isNan(x)) { 213 e.* = 0; 214 return x; 215 } 216 217 const r = math.frexp(x); 218 e.* = r.exponent; 219 return r.significand; 220 } 221 222 fn frexp(x: f64, e: *c_int) callconv(.c) f64 { 223 return frexpGeneric(f64, x, e); 224 } 225 226 fn frexpf(x: f32, e: *c_int) callconv(.c) f32 { 227 return frexpGeneric(f32, x, e); 228 } 229 230 fn frexpl(x: c_longdouble, e: *c_int) callconv(.c) c_longdouble { 231 return switch (@typeInfo(c_longdouble).float.bits) { 232 64 => std.c.frexp(x, e), 233 else => frexpGeneric(c_longdouble, x, e), 234 }; 235 } 236 237 fn hypot(x: f64, y: f64) callconv(.c) f64 { 238 return math.hypot(x, y); 239 } 240 241 fn hypotf(x: f32, y: f32) callconv(.c) f32 { 242 return math.hypot(x, y); 243 } 244 245 fn hypotl(x: c_longdouble, y: c_longdouble) callconv(.c) c_longdouble { 246 return switch (@typeInfo(c_longdouble).float.bits) { 247 64 => std.c.hypot(x, y), 248 else => math.hypot(x, y), 249 }; 250 } 251 252 fn isnan(x: f64) callconv(.c) c_int { 253 return @intFromBool(math.isNan(x)); 254 } 255 256 fn isnanf(x: f32) callconv(.c) c_int { 257 return @intFromBool(math.isNan(x)); 258 } 259 260 fn isnanl(x: c_longdouble) callconv(.c) c_int { 261 return @intFromBool(math.isNan(x)); 262 } 263 264 fn log1p(x: f64) callconv(.c) f64 { 265 return math.log1p(x); 266 } 267 268 fn log1pf(x: f32) callconv(.c) f32 { 269 return math.log1p(x); 270 } 271 272 fn lrint(x: f64) callconv(.c) c_long { 273 return @trunc(rint(x)); 274 } 275 276 fn lrintf(x: f32) callconv(.c) c_long { 277 return @trunc(rintf(x)); 278 } 279 280 fn lrintl(x: c_longdouble) callconv(.c) c_long { 281 return @trunc(rintl(x)); 282 } 283 284 fn lround(x: f64) callconv(.c) c_long { 285 return @round(x); 286 } 287 288 fn lroundf(x: f32) callconv(.c) c_long { 289 return @round(x); 290 } 291 292 fn lroundl(x: c_longdouble) callconv(.c) c_long { 293 return @round(x); 294 } 295 296 fn modfGeneric(comptime T: type, x: T, iptr: *T) T { 297 if (math.isNegativeInf(x)) { 298 iptr.* = -math.inf(T); 299 return -0.0; 300 } 301 302 if (math.isPositiveInf(x)) { 303 iptr.* = math.inf(T); 304 return 0.0; 305 } 306 307 if (math.isNan(x)) { 308 iptr.* = math.nan(T); 309 return math.nan(T); 310 } 311 312 const r = math.modf(x); 313 iptr.* = r.ipart; 314 315 // If the result is a negative zero, we must be explicit about 316 // returning a negative zero. 317 return if (math.isNegativeZero(x) or (x < 0.0 and x == r.ipart)) -0.0 else r.fpart; 318 } 319 320 fn modf(x: f64, iptr: *f64) callconv(.c) f64 { 321 return modfGeneric(f64, x, iptr); 322 } 323 324 fn modff(x: f32, iptr: *f32) callconv(.c) f32 { 325 return modfGeneric(f32, x, iptr); 326 } 327 328 fn modfl(x: c_longdouble, iptr: *c_longdouble) callconv(.c) c_longdouble { 329 return switch (@typeInfo(c_longdouble).float.bits) { 330 64 => std.c.modf(x, iptr), 331 else => modfGeneric(c_longdouble, x, iptr), 332 }; 333 } 334 335 fn nan(_: [*:0]const c_char) callconv(.c) f64 { 336 return math.nan(f64); 337 } 338 339 fn nanf(_: [*:0]const c_char) callconv(.c) f32 { 340 return math.nan(f32); 341 } 342 343 fn nanl(_: [*:0]const c_char) callconv(.c) c_longdouble { 344 return math.nan(c_longdouble); 345 } 346 347 fn pow10(x: f64) callconv(.c) f64 { 348 return exp10(x); 349 } 350 351 fn pow10f(x: f32) callconv(.c) f32 { 352 return exp10f(x); 353 } 354 355 fn rint(x: f64) callconv(.c) f64 { 356 const toint: f64 = 1.0 / math.floatEps(f64); 357 const a: u64 = @bitCast(x); 358 const e = a >> 52 & 0x7ff; 359 const s = a >> 63; 360 var y: f64 = undefined; 361 362 if (e >= 0x3ff + 52) { 363 return x; 364 } 365 if (s == 1) { 366 y = x - toint + toint; 367 } else { 368 y = x + toint - toint; 369 } 370 if (y == 0) { 371 return if (s == 1) -0.0 else 0; 372 } 373 return y; 374 } 375 376 fn rintf(x: f32) callconv(.c) f32 { 377 const toint: f32 = 1.0 / math.floatEps(f32); 378 const a: u32 = @bitCast(x); 379 const e = a >> 23 & 0xff; 380 const s = a >> 31; 381 var y: f32 = undefined; 382 383 if (e >= 0x7f + 23) { 384 return x; 385 } 386 387 if (s == 1) { 388 y = x - toint + toint; 389 } else { 390 y = x + toint - toint; 391 } 392 393 if (y == 0) { 394 return if (s == 1) -0.0 else 0; 395 } 396 return y; 397 } 398 399 fn rintl(x: c_longdouble) callconv(.c) c_longdouble { 400 if (@typeInfo(c_longdouble).float.bits == 64) 401 return rint(x); 402 403 const toint: c_longdouble = 1 << math.floatFractionalBits(c_longdouble); 404 const se = ld.signExponent(x); 405 406 if (se & 0x7fff >= 0x3fff + math.floatFractionalBits(c_longdouble)) 407 return x; 408 409 var y: c_longdouble = undefined; 410 if ((se >> 15) == 1) { 411 y = x - toint + toint; 412 } else { 413 y = x + toint - toint; 414 } 415 416 if (y == 0) 417 return 0 * x; 418 return y; 419 } 420 421 fn tanh(x: f64) callconv(.c) f64 { 422 return math.tanh(x); 423 } 424 425 fn tanhf(x: f32) callconv(.c) f32 { 426 return math.tanh(x); 427 } 428