diff --git a/Cargo.lock b/Cargo.lock index d088e84ff8a..4c730054598 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2115,7 +2115,7 @@ dependencies = [ "icu_provider_fs", "icu_testdata", "itertools", - "num-traits", + "libm", "serde", "serde_json", "utf8_iter", diff --git a/components/segmenter/Cargo.toml b/components/segmenter/Cargo.toml index 8b6b4192251..4a60f6f86a5 100644 --- a/components/segmenter/Cargo.toml +++ b/components/segmenter/Cargo.toml @@ -38,7 +38,7 @@ zerovec = { version = "0.9.4", path = "../../utils/zerovec", features = ["yoke"] databake = { version = "0.1.3", path = "../../utils/databake", optional = true, features = ["derive"] } serde = { version = "1.0", default-features = false, features = ["derive", "alloc"], optional = true } -num-traits = { version = "0.2", default-features = false, features = ["libm"], optional = true } +libm = { version = "0.2", default-features = false, optional = true } [dev-dependencies] criterion = "0.4" @@ -56,7 +56,7 @@ default = ["auto"] std = ["icu_collections/std", "icu_locid/std", "icu_provider/std"] serde = ["dep:serde", "zerovec/serde", "icu_collections/serde", "icu_provider/serde"] datagen = ["serde", "dep:databake", "zerovec/databake", "icu_collections/databake"] -lstm = ["dep:num-traits"] +lstm = ["dep:libm"] auto = ["lstm"] # Enabled try_new_auto_unstable constructors [lib] diff --git a/components/segmenter/src/complex/lstm/matrix.rs b/components/segmenter/src/complex/lstm/matrix.rs index faeeece1394..3e777d6e5a5 100644 --- a/components/segmenter/src/complex/lstm/matrix.rs +++ b/components/segmenter/src/complex/lstm/matrix.rs @@ -8,20 +8,24 @@ use core::ops::Range; use zerovec::ule::AsULE; use zerovec::ZeroSlice; -// Polyfill float operations with libm in case we're no_std. -#[allow(unused_imports)] -use num_traits::Float; - -/// `tanh` computes the tanh function for a scalar value. -#[inline] -fn tanh(x: f32) -> f32 { - x.tanh() +// This will be used in #[no_std] as f32::exp/f32::tanh are not in core. +trait CoreFloat { + fn exp(self) -> Self; + fn tanh(self) -> Self; } -/// `sigmoid` computes the sigmoid function for a scalar value. -#[inline] -fn sigmoid(x: f32) -> f32 { - 1.0 / (1.0 + (-x).exp()) +// TODO: Find a way to do this without libm. There's an intrinsic +// that produces `llvm.exp.f32`, but that's not exposed through +// f32. Another option would be to declare `extern "Rust"` and +// let clients provide these functions. +impl CoreFloat for f32 { + fn exp(self) -> Self { + libm::expf(self) + } + + fn tanh(self) -> Self { + libm::tanhf(self) + } } /// A `D`-dimensional, heap-allocated matrix. @@ -209,21 +213,24 @@ impl<'a, const D: usize> MatrixBorrowedMut<'a, D> { /// Mutates this matrix by applying a softmax transformation. pub(super) fn softmax_transform(&mut self) { - let sm = self.data.iter().map(|v| v.exp()).sum::(); - self.data.iter_mut().for_each(|v| { - *v = v.exp() / sm; - }); + for v in self.data.iter_mut() { + *v = v.exp(); + } + let sm = 1.0 / self.data.iter().sum::(); + for v in self.data.iter_mut() { + *v *= sm; + } } pub(super) fn sigmoid_transform(&mut self) { for x in &mut self.data.iter_mut() { - *x = sigmoid(*x); + *x = 1.0 / (1.0 + (-*x).exp()); } } pub(super) fn tanh_transform(&mut self) { for x in &mut self.data.iter_mut() { - *x = tanh(*x); + *x = x.tanh(); } } @@ -262,7 +269,7 @@ impl<'a, const D: usize> MatrixBorrowedMut<'a, D> { // Safety: The lengths are all the same (checked above) unsafe { *self.data.get_unchecked_mut(idx) = - o.get_unchecked(idx) * tanh(*c.get_unchecked(idx)); + o.get_unchecked(idx) * c.get_unchecked(idx).tanh(); } } } diff --git a/ffi/gn/Cargo.lock b/ffi/gn/Cargo.lock index fd92f2c0ec2..49830695b61 100644 --- a/ffi/gn/Cargo.lock +++ b/ffi/gn/Cargo.lock @@ -45,12 +45,6 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64cb94155d965e3d37ffbbe7cc5b82c3dd79dd33bd48e536f73d2cfb8d85506f" -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - [[package]] name = "bitflags" version = "1.3.2" @@ -456,7 +450,7 @@ dependencies = [ "icu_collections", "icu_locid", "icu_provider", - "num-traits", + "libm", "utf8_iter", "zerovec", ] @@ -564,16 +558,6 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" -[[package]] -name = "num-traits" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" -dependencies = [ - "autocfg", - "libm", -] - [[package]] name = "pretty_assertions" version = "0.5.1" diff --git a/ffi/gn/Cargo.toml b/ffi/gn/Cargo.toml index 54e2532edc3..3a940f53669 100644 --- a/ffi/gn/Cargo.toml +++ b/ffi/gn/Cargo.toml @@ -36,9 +36,6 @@ rustflags = [] [gn.package.syn."1.0.109"] rustflags = ["--cfg=syn_disable_nightly_tests"] -[gn.package.num-traits."0.2.15"] -rustflags = ["--cfg=has_i128"] - [gn.package.libm."0.2.6"] rustflags = [] diff --git a/ffi/gn/icu4x/BUILD.gn b/ffi/gn/icu4x/BUILD.gn index 7595aad36fa..530c3cded5f 100644 --- a/ffi/gn/icu4x/BUILD.gn +++ b/ffi/gn/icu4x/BUILD.gn @@ -628,7 +628,7 @@ rust_library("icu_segmenter-v1_2_1") { deps += [ ":icu_collections-v1_2_0" ] deps += [ ":icu_locid-v1_2_0" ] deps += [ ":icu_provider-v1_2_0" ] - deps += [ ":num-traits-v0_2_15" ] + deps += [ ":libm-v0_2_6" ] deps += [ ":utf8_iter-v1_0_3" ] deps += [ ":zerovec-v0_9_4" ] @@ -752,7 +752,6 @@ rust_library("libm-v0_2_6") { "--edition=2018", "-Cmetadata=6b5214f2031c6f9e", "-Cextra-filename=-6b5214f2031c6f9e", - "--cfg=feature=\"default\"", ] visibility = [ ":*" ] @@ -820,28 +819,6 @@ rust_library("memchr-v2_5_0") { visibility = [ ":*" ] } -rust_library("num-traits-v0_2_15") { - crate_name = "num_traits" - crate_root = "//ffi/gn/vendor/num-traits/src/lib.rs" - output_name = "num_traits-64c0e09f0f13aa66" - - deps = [] - deps += [ ":libm-v0_2_6" ] - - rustenv = [] - - rustflags = [ - "--cap-lints=allow", - "--edition=2015", - "-Cmetadata=64c0e09f0f13aa66", - "-Cextra-filename=-64c0e09f0f13aa66", - "--cfg=feature=\"libm\"", - "--cfg=has_i128", - ] - - visibility = [ ":*" ] -} - rust_library("proc-macro2-v1_0_56") { crate_name = "proc_macro2" crate_root = "//ffi/gn/vendor/proc-macro2/src/lib.rs" diff --git a/tools/depcheck/src/allowlist.rs b/tools/depcheck/src/allowlist.rs index 9594cb7b7c0..b29207aaedd 100644 --- a/tools/depcheck/src/allowlist.rs +++ b/tools/depcheck/src/allowlist.rs @@ -72,7 +72,7 @@ pub const EXTRA_EXPERIMENTAL_DEPS: &[&str] = &[ ]; /// Dependencies allowed when opting in to LSTM segmenter -pub const EXTRA_LSTM_DEPS: &[&str] = &["libm", "num-traits"]; +pub const EXTRA_LSTM_DEPS: &[&str] = &["libm"]; /// Dependencies allowed when opting in to fixed_decimal's `ryu` backend /// This should never change @@ -122,6 +122,7 @@ pub const EXTRA_DATAGEN_DEPS: &[&str] = &[ "ndarray", "num-complex", "num-integer", + "num-traits", "rawpointer", "regex-syntax", "rust-format",