From 64d9f7724834c4f1f0f5d1e15184220823565c3d Mon Sep 17 00:00:00 2001 From: "Kim, Hyeonseo" Date: Tue, 4 Jun 2024 21:36:52 +0900 Subject: [PATCH 1/7] Add doc example for math::factorize --- basm-std/src/math/pollard_rho.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/basm-std/src/math/pollard_rho.rs b/basm-std/src/math/pollard_rho.rs index d64834db..75cc0db8 100644 --- a/basm-std/src/math/pollard_rho.rs +++ b/basm-std/src/math/pollard_rho.rs @@ -62,6 +62,13 @@ fn pollard_rho(r: u64) -> u64 { } } +/// Return Vector contains result of prime factorization in ascending order +/// +/// # Examples +/// ``` +/// assert_eq!(vec![2, 2, 2, 3], basm::math::factorize(24)); +/// assert_eq!(vec![2, 2, 5, 17], basm::math::factorize(340)); +/// ``` pub fn factorize(mut n: u64) -> Vec { let mut v = Vec::new(); for p in [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37] { From f781632995ebf8fae5c3d03f04a23c40ee7669b6 Mon Sep 17 00:00:00 2001 From: "Kim, Hyeonseo" Date: Tue, 4 Jun 2024 21:57:09 +0900 Subject: [PATCH 2/7] Modify example of factorize --- basm-std/src/math/pollard_rho.rs | 50 +++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/basm-std/src/math/pollard_rho.rs b/basm-std/src/math/pollard_rho.rs index 75cc0db8..de412706 100644 --- a/basm-std/src/math/pollard_rho.rs +++ b/basm-std/src/math/pollard_rho.rs @@ -1,7 +1,10 @@ // This is a Rust port of the implementation originally written in C++ by wider93. +use crate::math::{ + gcd, is_prime_u64, + miller_rabin::{OddMont, M}, +}; use alloc::{vec, vec::Vec}; -use crate::math::{gcd, is_prime_u64, miller_rabin::{M, OddMont}}; trait PollardRhoOp { fn pollard_rho_type(r: T, init: T) -> T; @@ -24,9 +27,12 @@ macro_rules! impl_pollard_rho_type { let mut g = M::<$ty> { v: 1 }; let x = y; for _ in (0..itr).step_by(STEP as usize) { - if k != 1 { break; } + if k != 1 { + break; + } for _ in 0..STEP { - y = rm.redc(y.v as $ty_large * y.v as $ty_large + init as $ty_large); + y = rm + .redc(y.v as $ty_large * y.v as $ty_large + init as $ty_large); g = rm.mul(g, rm.to_mont(x.v.abs_diff(y.v))); } k = gcd(g.v, r); @@ -34,9 +40,13 @@ macro_rules! impl_pollard_rho_type { k = 1; let mut py = x; for _ in 0..STEP { - py = rm.redc(py.v as $ty_large * py.v as $ty_large + init as $ty_large); + py = rm.redc( + py.v as $ty_large * py.v as $ty_large + init as $ty_large, + ); k = gcd(r, x.v.abs_diff(py.v)); - if k != 1 { break; } + if k != 1 { + break; + } } if k == 1 { k = r; @@ -49,7 +59,7 @@ macro_rules! impl_pollard_rho_type { k } } - } + }; } impl_pollard_rho_type!(u32, u64); impl_pollard_rho_type!(u64, u128); @@ -63,11 +73,11 @@ fn pollard_rho(r: u64) -> u64 { } /// Return Vector contains result of prime factorization in ascending order -/// -/// # Examples +/// /// ``` -/// assert_eq!(vec![2, 2, 2, 3], basm::math::factorize(24)); -/// assert_eq!(vec![2, 2, 5, 17], basm::math::factorize(340)); +/// use basm_std::math::factorize; +/// assert_eq!(vec![2, 2, 2, 3], factorize(24)); +/// assert_eq!(vec![2, 2, 5, 17], factorize(340)); /// ``` pub fn factorize(mut n: u64) -> Vec { let mut v = Vec::new(); @@ -111,11 +121,23 @@ mod test { #[test] fn check_factorize() { assert_eq!(vec![2, 2, 3], factorize(12)); - assert_eq!(vec![3, 3, 13, 179, 271, 1381, 2423], factorize(18991325453139)); + assert_eq!( + vec![3, 3, 13, 179, 271, 1381, 2423], + factorize(18991325453139) + ); assert_eq!(vec![34421, 133978850655919], factorize(4611686018427387899)); - assert_eq!(vec![2, 2, 3, 3, 5, 5, 7, 11, 13, 31, 41, 61, 151, 331, 1321], factorize(4611686018427387900)); - assert_eq!(vec![37, 9902437, 12586817029], factorize(4611686018427387901)); + assert_eq!( + vec![2, 2, 3, 3, 5, 5, 7, 11, 13, 31, 41, 61, 151, 331, 1321], + factorize(4611686018427387900) + ); + assert_eq!( + vec![37, 9902437, 12586817029], + factorize(4611686018427387901) + ); assert_eq!(vec![2, 2305843009213693951], factorize(4611686018427387902)); - assert_eq!(vec![3, 715827883, 2147483647], factorize(4611686018427387903)); + assert_eq!( + vec![3, 715827883, 2147483647], + factorize(4611686018427387903) + ); } } From e770a389f3f3f5d3167c3f8dfa874ee4d8808847 Mon Sep 17 00:00:00 2001 From: "Kim, Hyeonseo" Date: Tue, 4 Jun 2024 22:43:09 +0900 Subject: [PATCH 3/7] doc: Add document for Writer --- basm-std/src/platform/io/writer.rs | 127 +++++++++++++++++++++++++---- 1 file changed, 113 insertions(+), 14 deletions(-) diff --git a/basm-std/src/platform/io/writer.rs b/basm-std/src/platform/io/writer.rs index 7e9b560b..a0b4aa74 100644 --- a/basm-std/src/platform/io/writer.rs +++ b/basm-std/src/platform/io/writer.rs @@ -1,6 +1,6 @@ +use crate::platform::services; use alloc::string::String; use core::mem::MaybeUninit; -use crate::platform::services; pub struct Writer { buf: [MaybeUninit; N], @@ -26,10 +26,10 @@ struct B128([u8; 16]); #[cfg(any(target_arch = "x86_64", target_arch = "x86"))] #[target_feature(enable = "avx2")] unsafe fn cvt8(out: &mut B128, n: u32) -> usize { - #[cfg(target_arch = "x86_64")] - use core::arch::x86_64::*; #[cfg(target_arch = "x86")] use core::arch::x86::*; + #[cfg(target_arch = "x86_64")] + use core::arch::x86_64::*; let x = _mm_cvtsi32_si128(n as i32); let div_10000 = _mm_set1_epi32(0xd1b71759u32 as i32); let mul_10000_merge = _mm_set1_epi32(55536); @@ -95,21 +95,31 @@ unsafe fn cvt8(out: &mut B128, mut n: u32) -> usize { impl Writer { const _DUMMY: usize = { - assert!(N >= super::MIN_BUF_SIZE, "Buffer size for Writer must be at least MIN_BUF_SIZE"); + assert!( + N >= super::MIN_BUF_SIZE, + "Buffer size for Writer must be at least MIN_BUF_SIZE" + ); 0 }; + /// Make new `Writer` with type parameter `N` buffer size. For convenient use, check out `Default::default()` + /// ```no_run + /// use basm_std::platform::io::Writer; + /// let mut writer = Writer::<100>::new(); + /// ``` pub fn new() -> Self { Self { buf: MaybeUninit::uninit_array(), - off: 0 + off: 0, } } + /// Flush buffer of `Writer`. pub fn flush(&mut self) { services::write_stdio(1, unsafe { MaybeUninit::slice_assume_init_ref(&self.buf[..self.off]) }); self.off = 0; } + /// Check readahed from offset is bigger than current buffer length, then call [`Writer::flush`]. pub fn try_flush(&mut self, readahead: usize) { if self.off + readahead > self.buf.len() { self.flush(); @@ -124,17 +134,28 @@ impl Writer { self.buf[self.off].write(b); self.off += 1; } + /// Write a single byte. + /// ```no_run + /// let writer : Writer = Default::default(); + /// writer.byte(b'c"); // c + /// ``` pub fn byte(&mut self, b: u8) { self.try_flush(2); self.byte_unchecked(b); } - // This function ensures an extra byte in the buffer to make sure that - // println() can safely use `byte_unchecked`. + /// Write multiple bytes. This function ensures an extra byte in the buffer to make sure that println() can safely use private method `byte_unchecked`. + /// ```no_run + /// let writer : Writer = Default::default(); + /// writer.bytes("Hello World".as_bytes()); // Hello World + /// ``` #[cfg(not(feature = "short"))] pub fn bytes(&mut self, mut s: &[u8]) { while !s.is_empty() { let rem = s.len().min(self.buf[self.off..].len()); - unsafe { MaybeUninit::slice_assume_init_mut(&mut self.buf[self.off..self.off + rem]).copy_from_slice(&s[..rem]); } + unsafe { + MaybeUninit::slice_assume_init_mut(&mut self.buf[self.off..self.off + rem]) + .copy_from_slice(&s[..rem]); + } self.off += rem; s = &s[rem..]; self.try_flush(1); @@ -149,21 +170,45 @@ impl Writer { self.byte(*x); } } + /// Write `&str`. + /// ```no_run + /// writer.bytes("Hello, World"); // Hello, World + /// ``` pub fn str(&mut self, s: &str) { self.bytes(s.as_bytes()); } + /// Write `i8` + /// ```no run + /// writer.bytes(i8::MIN); // -128 + /// ``` pub fn i8(&mut self, n: i8) { self.i32(n as i32); } + /// Write `u8` + /// ```no run + /// writer.u8(u8::MAX); // 255 + /// ``` pub fn u8(&mut self, n: u8) { self.u32(n as u32); } + /// Write `i16` + /// ```no run + /// writer.i16(i16::MIN); // -32768 + /// ``` pub fn i16(&mut self, n: i16) { self.i32(n as i32); } + /// Write `u16` + /// ```no run + /// writer.u16(u16::MAX); // 65535 + /// ``` pub fn u16(&mut self, n: u16) { self.u32(n as u32); } + /// Write `i32` + /// ```no run + /// writer.i32(i32::MIN); // -2147483648 + /// ``` pub fn i32(&mut self, n: i32) { if n < 0 { self.byte(b'-'); @@ -172,6 +217,10 @@ impl Writer { self.u32(n as u32); } } + /// Write `u32` + /// ```no_run + /// writer.u32(u32::MAX); // 4294967295 + /// ``` #[cfg(not(feature = "short"))] pub fn u32(&mut self, n: u32) { self.try_flush(11); @@ -191,13 +240,20 @@ impl Writer { } } let len = 16 - off; - unsafe { MaybeUninit::slice_assume_init_mut(&mut self.buf[self.off..self.off + len]).copy_from_slice(&b128.0[off..]); } + unsafe { + MaybeUninit::slice_assume_init_mut(&mut self.buf[self.off..self.off + len]) + .copy_from_slice(&b128.0[off..]); + } self.off += len; } #[cfg(feature = "short")] pub fn u32(&mut self, n: u32) { self.u64(n as u64) } + /// Write `i64` + /// ```no_run + /// writer.i64(i64::MIN); // -9223372036854775808 + /// ``` pub fn i64(&mut self, n: i64) { if n < 0 { self.byte(b'-'); @@ -206,6 +262,10 @@ impl Writer { self.u64(n as u64); } } + /// Write `u64` + /// ```no_run + /// writer.u64(u64::MAX); // 18446744073709551615 + /// ``` #[cfg(not(feature = "short"))] pub fn u64(&mut self, n: u64) { self.try_flush(21); @@ -238,10 +298,16 @@ impl Writer { } } let len = 16 - hioff; - unsafe { MaybeUninit::slice_assume_init_mut(&mut self.buf[self.off..self.off + len]).copy_from_slice(&hi128.0[hioff..]); } + unsafe { + MaybeUninit::slice_assume_init_mut(&mut self.buf[self.off..self.off + len]) + .copy_from_slice(&hi128.0[hioff..]); + } self.off += len; let len = 16 - looff; - unsafe { MaybeUninit::slice_assume_init_mut(&mut self.buf[self.off..self.off + len]).copy_from_slice(&lo128.0[looff..]); } + unsafe { + MaybeUninit::slice_assume_init_mut(&mut self.buf[self.off..self.off + len]) + .copy_from_slice(&lo128.0[looff..]); + } self.off += len; } #[cfg(feature = "short")] @@ -252,16 +318,24 @@ impl Writer { self.buf[i].write(b'0' + (n % 10) as u8); n /= 10; i += 1; - if n == 0 { break; } + if n == 0 { + break; + } } let mut j = self.off; self.off = i; while j < i { i -= 1; - unsafe { MaybeUninit::slice_assume_init_mut(&mut self.buf).swap(j, i); } + unsafe { + MaybeUninit::slice_assume_init_mut(&mut self.buf).swap(j, i); + } j += 1; } } + /// Write `i128` + /// ```no_run + /// writer.i128(i128::MIN); // -170141183460469231731687303715884105728 + /// ``` pub fn i128(&mut self, n: i128) { if n < 0 { self.byte(b'-'); @@ -270,6 +344,10 @@ impl Writer { self.u128(n as u128); } } + /// Write `u128` + /// ```no_run + /// writer.u128(u128::MAX); // 340282366920938463463374607431768211455 + /// ``` pub fn u128(&mut self, mut n: u128) { let mut buf: [MaybeUninit; 40] = MaybeUninit::uninit_array(); let mut offset = buf.len() - 1; @@ -290,10 +368,18 @@ impl Writer { pub fn usize(&mut self, n: usize) { self.u32(n as u32); } + /// Write `isize` (in BOJ, it's `i64`); + /// ```no_run + /// writer.isize(isize::MIN); // -9223372036854775808 + /// ``` #[cfg(target_pointer_width = "64")] pub fn isize(&mut self, n: isize) { self.i64(n as i64); } + /// Write `usize` (in BJO, it's `u64`); + /// ```no_run + /// writer.usize(usize::MAX); // 18446744073709551615 + /// ``` #[cfg(target_pointer_width = "64")] pub fn usize(&mut self, n: usize) { self.u64(n as u64); @@ -306,11 +392,19 @@ impl Writer { pub fn usize(&mut self, mut n: usize) { self.u128(n as u128); } + /// Write `f64` + /// ```no_run + /// writer.f64(1.23); // 1.23 + /// ``` pub fn f64(&mut self, f: f64) { let mut buffer = ryu::Buffer::new(); let printed = buffer.format(f); self.bytes(printed.as_bytes()); } + /// Write `char` + /// ```no_run + /// writer.char('c'); // c + /// ``` pub fn char(&mut self, c: char) { self.try_flush(6); let u = c as u32; @@ -342,6 +436,7 @@ pub trait Print { fn println(&mut self, x: T); } +/// Write `&[u8]` using [`Writer::bytes()`]. `print()` doesn't add newline at the end of the output, while `println()` does. impl Print<&[u8]> for Writer { fn print(&mut self, x: &[u8]) { self.bytes(x); @@ -352,6 +447,7 @@ impl Print<&[u8]> for Writer { } } +/// Write `&[u8; M]` using [`Writer::bytes()`]. `print()` doesn't add newline at the end of the output, while `println()` does. impl Print<&[u8; M]> for Writer { fn print(&mut self, x: &[u8; M]) { self.bytes(x); @@ -362,6 +458,7 @@ impl Print<&[u8; M]> for Writer { } } +/// Write `&str` using [`Writer::bytes()`] and [`str::as_bytes()`]. `print()` doesn't add newline at the end of the output, while `println()` does. impl Print<&str> for Writer { fn print(&mut self, x: &str) { self.bytes(x.as_bytes()); @@ -372,6 +469,7 @@ impl Print<&str> for Writer { } } +/// Write String using [`Writer::Print<&str>()`] and [`String::as_str()`]. `print()` doesn't add newline at the end of the output, while `println()` does. impl Print for Writer { fn print(&mut self, x: String) { self.print(x.as_str()); @@ -381,6 +479,7 @@ impl Print for Writer { } } +/// Write String using `Writer::Print<&str>()` and [`String::as_str()`]. `print()` doesn't add newline at the end of the output, while `println()` does. impl Print<&String> for Writer { fn print(&mut self, x: &String) { self.print(x.as_str()); @@ -482,4 +581,4 @@ mod test { assert_eq!(get_stdout_content(), b"123\n45\n78.9\nstr\nbytes\n"); } } -*/ \ No newline at end of file +*/ From 1aec69f0c6f7e7cc365fd4c3f3b43c03eee05671 Mon Sep 17 00:00:00 2001 From: "Kim, Hyeonseo" Date: Sat, 15 Jun 2024 07:41:29 +0000 Subject: [PATCH 4/7] doc: Update documentation for math::factorize function --- basm-std/src/math/pollard_rho.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basm-std/src/math/pollard_rho.rs b/basm-std/src/math/pollard_rho.rs index de412706..869a0aee 100644 --- a/basm-std/src/math/pollard_rho.rs +++ b/basm-std/src/math/pollard_rho.rs @@ -72,7 +72,7 @@ fn pollard_rho(r: u64) -> u64 { } } -/// Return Vector contains result of prime factorization in ascending order +/// Returns the `Vec` contains the result of prime factorization in ascending order. /// /// ``` /// use basm_std::math::factorize; From 61f401e76ecf48c7ac3fe64f35f0df9bf87ababf Mon Sep 17 00:00:00 2001 From: "Kim, Hyeonseo" Date: Sat, 15 Jun 2024 07:42:08 +0000 Subject: [PATCH 5/7] doc: Update documentation for Writer --- basm-std/src/platform/io/writer.rs | 65 +++++++++++++++--------------- 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/basm-std/src/platform/io/writer.rs b/basm-std/src/platform/io/writer.rs index a0b4aa74..08ce94f9 100644 --- a/basm-std/src/platform/io/writer.rs +++ b/basm-std/src/platform/io/writer.rs @@ -101,10 +101,12 @@ impl Writer { ); 0 }; - /// Make new `Writer` with type parameter `N` buffer size. For convenient use, check out `Default::default()` + /// Constructs a new `Writer` with the buffer size given type parameter `N`. + /// Note: For convenience, use `Default::default()`. /// ```no_run /// use basm_std::platform::io::Writer; /// let mut writer = Writer::<100>::new(); + /// let mut writer: Writer = Default::default(); /// ``` pub fn new() -> Self { Self { @@ -112,14 +114,14 @@ impl Writer { off: 0, } } - /// Flush buffer of `Writer`. + /// Flushes the buffer of the `Writer`. pub fn flush(&mut self) { services::write_stdio(1, unsafe { MaybeUninit::slice_assume_init_ref(&self.buf[..self.off]) }); self.off = 0; } - /// Check readahed from offset is bigger than current buffer length, then call [`Writer::flush`]. + /// Flushes the buffer of the `Writer` if the readahead from the offset is bigger than the buffer length. pub fn try_flush(&mut self, readahead: usize) { if self.off + readahead > self.buf.len() { self.flush(); @@ -134,7 +136,7 @@ impl Writer { self.buf[self.off].write(b); self.off += 1; } - /// Write a single byte. + /// Writes a single byte into the standard output. /// ```no_run /// let writer : Writer = Default::default(); /// writer.byte(b'c"); // c @@ -143,7 +145,8 @@ impl Writer { self.try_flush(2); self.byte_unchecked(b); } - /// Write multiple bytes. This function ensures an extra byte in the buffer to make sure that println() can safely use private method `byte_unchecked`. + /// Writes multiple bytes into the standard output. + /// Note: It ensures an extra byte in the buffer to make sure that `println()` can safely use the private method `byte_unchecked`. It is achieved by `self.try_flush(1)`. When the `--short` option is activated, it calls `self.try_flush(2)` (instead of `self.try_flush(1)`) in byte(). /// ```no_run /// let writer : Writer = Default::default(); /// writer.bytes("Hello World".as_bytes()); // Hello World @@ -161,51 +164,49 @@ impl Writer { self.try_flush(1); } } - // This function ensures an extra byte in the buffer to make sure that - // println() can safely use `byte_unchecked`. This is achieved by - // calling `self.try_flush(2)` (instead of `self.try_flush(1)`) in byte(). + #[cfg(feature = "short")] pub fn bytes(&mut self, s: &[u8]) { for x in s { self.byte(*x); } } - /// Write `&str`. + /// Writes a single `&str` into the standard output. /// ```no_run - /// writer.bytes("Hello, World"); // Hello, World + /// writer.str("Hello, World"); // Hello, World /// ``` pub fn str(&mut self, s: &str) { self.bytes(s.as_bytes()); } - /// Write `i8` + /// Writes a single `i8` into the standard output. /// ```no run - /// writer.bytes(i8::MIN); // -128 + /// writer.i8(i8::MIN); // -128 /// ``` pub fn i8(&mut self, n: i8) { self.i32(n as i32); } - /// Write `u8` + /// Writes a single `u8` into the standard output. /// ```no run /// writer.u8(u8::MAX); // 255 /// ``` pub fn u8(&mut self, n: u8) { self.u32(n as u32); } - /// Write `i16` + /// Writes a single `i16` into the standard output. /// ```no run /// writer.i16(i16::MIN); // -32768 /// ``` pub fn i16(&mut self, n: i16) { self.i32(n as i32); } - /// Write `u16` + /// Writes a single `u16` into the standard output. /// ```no run /// writer.u16(u16::MAX); // 65535 /// ``` pub fn u16(&mut self, n: u16) { self.u32(n as u32); } - /// Write `i32` + /// Writes a single `i32` into the standard output. /// ```no run /// writer.i32(i32::MIN); // -2147483648 /// ``` @@ -217,7 +218,7 @@ impl Writer { self.u32(n as u32); } } - /// Write `u32` + /// Writes a single `u32` into the standard output. /// ```no_run /// writer.u32(u32::MAX); // 4294967295 /// ``` @@ -250,7 +251,7 @@ impl Writer { pub fn u32(&mut self, n: u32) { self.u64(n as u64) } - /// Write `i64` + /// Writes a single `i64` into standard output. /// ```no_run /// writer.i64(i64::MIN); // -9223372036854775808 /// ``` @@ -262,7 +263,7 @@ impl Writer { self.u64(n as u64); } } - /// Write `u64` + /// Writes a single `u64` into standard output. /// ```no_run /// writer.u64(u64::MAX); // 18446744073709551615 /// ``` @@ -332,7 +333,7 @@ impl Writer { j += 1; } } - /// Write `i128` + /// Writes a single `i128` into the standard output. /// ```no_run /// writer.i128(i128::MIN); // -170141183460469231731687303715884105728 /// ``` @@ -344,7 +345,7 @@ impl Writer { self.u128(n as u128); } } - /// Write `u128` + /// Writes a single `u128` into the standard output. /// ```no_run /// writer.u128(u128::MAX); // 340282366920938463463374607431768211455 /// ``` @@ -368,17 +369,17 @@ impl Writer { pub fn usize(&mut self, n: usize) { self.u32(n as u32); } - /// Write `isize` (in BOJ, it's `i64`); + /// Writes a single `isize` into the standard output. It is based on the release target. /// ```no_run - /// writer.isize(isize::MIN); // -9223372036854775808 + /// writer.isize(isize::MIN); // -9223372036854775808 (On 64-bit targets) /// ``` #[cfg(target_pointer_width = "64")] pub fn isize(&mut self, n: isize) { self.i64(n as i64); } - /// Write `usize` (in BJO, it's `u64`); + /// Writes a single `usize` into the standard output. It is based on the release target. /// ```no_run - /// writer.usize(usize::MAX); // 18446744073709551615 + /// writer.usize(usize::MAX); // 18446744073709551615 (On 64-bit targets) /// ``` #[cfg(target_pointer_width = "64")] pub fn usize(&mut self, n: usize) { @@ -392,7 +393,7 @@ impl Writer { pub fn usize(&mut self, mut n: usize) { self.u128(n as u128); } - /// Write `f64` + /// Writes a single `f64` into the standard output. /// ```no_run /// writer.f64(1.23); // 1.23 /// ``` @@ -401,7 +402,7 @@ impl Writer { let printed = buffer.format(f); self.bytes(printed.as_bytes()); } - /// Write `char` + /// Writes a single `char` into the standard output. /// ```no_run /// writer.char('c'); // c /// ``` @@ -436,7 +437,7 @@ pub trait Print { fn println(&mut self, x: T); } -/// Write `&[u8]` using [`Writer::bytes()`]. `print()` doesn't add newline at the end of the output, while `println()` does. +/// Writes a single `&[u8]` using [`Writer::bytes()`] into the standard output. `print()` doesn't add a newline at the end of the output, while `println()` does. impl Print<&[u8]> for Writer { fn print(&mut self, x: &[u8]) { self.bytes(x); @@ -447,7 +448,7 @@ impl Print<&[u8]> for Writer { } } -/// Write `&[u8; M]` using [`Writer::bytes()`]. `print()` doesn't add newline at the end of the output, while `println()` does. +/// Writes a single `&[u8; M]` using [`Writer::bytes()`] into the standard output. `print()` doesn't add a newline at the end of the output, while `println()` does. impl Print<&[u8; M]> for Writer { fn print(&mut self, x: &[u8; M]) { self.bytes(x); @@ -458,7 +459,7 @@ impl Print<&[u8; M]> for Writer { } } -/// Write `&str` using [`Writer::bytes()`] and [`str::as_bytes()`]. `print()` doesn't add newline at the end of the output, while `println()` does. +/// Writes a single `&str` using [`Writer::bytes()`] and [`str::as_bytes()`] into the standard output. `print()` doesn't add a newline at the end of the output, while `println()` does. impl Print<&str> for Writer { fn print(&mut self, x: &str) { self.bytes(x.as_bytes()); @@ -469,7 +470,7 @@ impl Print<&str> for Writer { } } -/// Write String using [`Writer::Print<&str>()`] and [`String::as_str()`]. `print()` doesn't add newline at the end of the output, while `println()` does. +/// Write a single `String`` using [`Writer::Print<&str>()`] and [`String::as_str()`] into the standard output. `print()` doesn't add a newline at the end of the output, while `println()` does. impl Print for Writer { fn print(&mut self, x: String) { self.print(x.as_str()); @@ -479,7 +480,7 @@ impl Print for Writer { } } -/// Write String using `Writer::Print<&str>()` and [`String::as_str()`]. `print()` doesn't add newline at the end of the output, while `println()` does. +/// Writes `&String` using `Writer::Print<&str>()` and [`String::as_str()`] into the standard output. `print()` doesn't add a newline at the end of the output, while `println()` does. impl Print<&String> for Writer { fn print(&mut self, x: &String) { self.print(x.as_str()); From 1745ea3d0360319248da586204b8dc0587e27414 Mon Sep 17 00:00:00 2001 From: Byeongkeun Ahn <7p54ks3@naver.com> Date: Sat, 15 Jun 2024 18:57:01 +0900 Subject: [PATCH 6/7] Update services_std.rs --- basm-std/src/platform/services_std.rs | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/basm-std/src/platform/services_std.rs b/basm-std/src/platform/services_std.rs index 8a2d4d4d..cf9fab7d 100644 --- a/basm-std/src/platform/services_std.rs +++ b/basm-std/src/platform/services_std.rs @@ -10,11 +10,7 @@ pub fn read_stdio(fd: usize, buf: &mut [u8]) -> usize { match fd { 0 => { let mut stdin = io::stdin(); - if let Ok(bytes_transferred) = stdin.read(buf) { - bytes_transferred - } else { - 0 - } + stdin.read(buf).unwrap_or_default() } _ => 0, } @@ -24,19 +20,11 @@ pub fn write_stdio(fd: usize, buf: &[u8]) -> usize { match fd { 1 => { let mut stdout = io::stdout(); - if let Ok(bytes_transferred) = stdout.write(buf) { - bytes_transferred - } else { - 0 - } + stdout.write(buf).unwrap_or_default() } 2 => { let mut stderr = io::stderr(); - if let Ok(bytes_transferred) = stderr.write(buf) { - bytes_transferred - } else { - 0 - } + stderr.write(buf).unwrap_or_default() } _ => 0, } From 950874ba5d85142f6e858d0d4e4527f6ada42cee Mon Sep 17 00:00:00 2001 From: Byeongkeun Ahn <7p54ks3@naver.com> Date: Sat, 15 Jun 2024 18:56:06 +0900 Subject: [PATCH 7/7] Improve descriptions --- basm-std/src/math/pollard_rho.rs | 2 +- basm-std/src/platform/io/writer.rs | 68 ++++++++++++++++-------------- 2 files changed, 38 insertions(+), 32 deletions(-) diff --git a/basm-std/src/math/pollard_rho.rs b/basm-std/src/math/pollard_rho.rs index 869a0aee..1d12a604 100644 --- a/basm-std/src/math/pollard_rho.rs +++ b/basm-std/src/math/pollard_rho.rs @@ -72,7 +72,7 @@ fn pollard_rho(r: u64) -> u64 { } } -/// Returns the `Vec` contains the result of prime factorization in ascending order. +/// Returns a `Vec` containing the result of prime factorization in ascending order. /// /// ``` /// use basm_std::math::factorize; diff --git a/basm-std/src/platform/io/writer.rs b/basm-std/src/platform/io/writer.rs index 05e245d3..d686ccf6 100644 --- a/basm-std/src/platform/io/writer.rs +++ b/basm-std/src/platform/io/writer.rs @@ -102,11 +102,11 @@ impl Writer { ); 0 }; - /// Constructs a new `Writer` with the buffer size given type parameter `N`. + /// Constructs a new `Writer` with buffer size `N`, specified as a const generic parameter. /// Note: For convenience, use `Default::default()`. /// ```no_run /// use basm_std::platform::io::Writer; - /// let mut writer = Writer::<100>::new(); + /// let mut writer = Writer::<128>::new(); /// let mut writer: Writer = Default::default(); /// ``` pub fn new() -> Self { @@ -115,14 +115,15 @@ impl Writer { off: 0, } } - /// Flushes the buffer of the `Writer`. + /// Flushes the buffer of the current `Writer`. pub fn flush(&mut self) { services::write_stdio(1, unsafe { MaybeUninit::slice_assume_init_ref(&self.buf[..self.off]) }); self.off = 0; } - /// Flushes the buffer of the `Writer` if the readahead from the offset is bigger than the buffer length. + /// Flushes the buffer of the current `Writer` if readahead plus the current offset exceeds the buffer length, + /// thereby ensuring that at least `readahead` bytes are available in the buffer. pub fn try_flush(&mut self, readahead: usize) { if self.off + readahead > self.buf.len() { self.flush(); @@ -137,19 +138,20 @@ impl Writer { self.buf[self.off].write(b); self.off += 1; } - /// Writes a single byte into the standard output. + /// Writes a single byte to standard output. /// ```no_run - /// let writer : Writer = Default::default(); - /// writer.byte(b'c"); // c + /// let mut writer: Writer = Default::default(); + /// writer.byte(b'c'); // c /// ``` pub fn byte(&mut self, b: u8) { self.try_flush(2); self.byte_unchecked(b); } - /// Writes multiple bytes into the standard output. - /// Note: It ensures an extra byte in the buffer to make sure that `println()` can safely use the private method `byte_unchecked`. It is achieved by `self.try_flush(1)`. When the `--short` option is activated, it calls `self.try_flush(2)` (instead of `self.try_flush(1)`) in byte(). + /// Writes multiple bytes to standard output. + /// + /// This method ensures an extra byte in the buffer to make sure that `println()` can safely use the private method `byte_unchecked`. It is achieved by `self.try_flush(1)`. /// ```no_run - /// let writer : Writer = Default::default(); + /// let mut writer: Writer = Default::default(); /// writer.bytes("Hello World".as_bytes()); // Hello World /// ``` #[cfg(not(feature = "short"))] @@ -165,49 +167,53 @@ impl Writer { self.try_flush(1); } } - + /// Writes multiple bytes to standard output. + /// + /// This function ensures an extra byte in the buffer to make sure that + /// println() can safely use `byte_unchecked`. This is achieved by + /// calling `self.try_flush(2)` (instead of `self.try_flush(1)`) in byte(). #[cfg(feature = "short")] pub fn bytes(&mut self, s: &[u8]) { for x in s { self.byte(*x); } } - /// Writes a single `&str` into the standard output. + /// Writes a single `&str` to standard output. /// ```no_run /// writer.str("Hello, World"); // Hello, World /// ``` pub fn str(&mut self, s: &str) { self.bytes(s.as_bytes()); } - /// Writes a single `i8` into the standard output. + /// Writes a single `i8` to standard output. /// ```no run /// writer.i8(i8::MIN); // -128 /// ``` pub fn i8(&mut self, n: i8) { self.i32(n as i32); } - /// Writes a single `u8` into the standard output. + /// Writes a single `u8` to standard output. /// ```no run /// writer.u8(u8::MAX); // 255 /// ``` pub fn u8(&mut self, n: u8) { self.u32(n as u32); } - /// Writes a single `i16` into the standard output. + /// Writes a single `i16` to standard output. /// ```no run /// writer.i16(i16::MIN); // -32768 /// ``` pub fn i16(&mut self, n: i16) { self.i32(n as i32); } - /// Writes a single `u16` into the standard output. + /// Writes a single `u16` to standard output. /// ```no run /// writer.u16(u16::MAX); // 65535 /// ``` pub fn u16(&mut self, n: u16) { self.u32(n as u32); } - /// Writes a single `i32` into the standard output. + /// Writes a single `i32` to standard output. /// ```no run /// writer.i32(i32::MIN); // -2147483648 /// ``` @@ -219,7 +225,7 @@ impl Writer { self.u32(n as u32); } } - /// Writes a single `u32` into the standard output. + /// Writes a single `u32` to standard output. /// ```no_run /// writer.u32(u32::MAX); // 4294967295 /// ``` @@ -252,7 +258,7 @@ impl Writer { pub fn u32(&mut self, n: u32) { self.u64(n as u64) } - /// Writes a single `i64` into standard output. + /// Writes a single `i64` to standard output. /// ```no_run /// writer.i64(i64::MIN); // -9223372036854775808 /// ``` @@ -264,7 +270,7 @@ impl Writer { self.u64(n as u64); } } - /// Writes a single `u64` into standard output. + /// Writes a single `u64` to standard output. /// ```no_run /// writer.u64(u64::MAX); // 18446744073709551615 /// ``` @@ -334,7 +340,7 @@ impl Writer { j += 1; } } - /// Writes a single `i128` into the standard output. + /// Writes a single `i128` to standard output. /// ```no_run /// writer.i128(i128::MIN); // -170141183460469231731687303715884105728 /// ``` @@ -346,7 +352,7 @@ impl Writer { self.u128(n as u128); } } - /// Writes a single `u128` into the standard output. + /// Writes a single `u128` to standard output. /// ```no_run /// writer.u128(u128::MAX); // 340282366920938463463374607431768211455 /// ``` @@ -370,7 +376,7 @@ impl Writer { pub fn usize(&mut self, n: usize) { self.u32(n as u32); } - /// Writes a single `isize` into the standard output. It is based on the release target. + /// Writes a single `isize` to standard output. Note that the in-memory size of `isize` depends on the target platform. /// ```no_run /// writer.isize(isize::MIN); // -9223372036854775808 (On 64-bit targets) /// ``` @@ -378,7 +384,7 @@ impl Writer { pub fn isize(&mut self, n: isize) { self.i64(n as i64); } - /// Writes a single `usize` into the standard output. It is based on the release target. + /// Writes a single `usize` to standard output. Note that the in-memory size of `isize` depends on the target platform. /// ```no_run /// writer.usize(usize::MAX); // 18446744073709551615 (On 64-bit targets) /// ``` @@ -394,7 +400,7 @@ impl Writer { pub fn usize(&mut self, mut n: usize) { self.u128(n as u128); } - /// Writes a single `f64` into the standard output. + /// Writes a single `f64` to standard output. /// ```no_run /// writer.f64(1.23); // 1.23 /// ``` @@ -403,7 +409,7 @@ impl Writer { let printed = buffer.format(f); self.bytes(printed.as_bytes()); } - /// Writes a single `char` into the standard output. + /// Writes a single `char` to standard output, encoded as UTF-8. /// ```no_run /// writer.char('c'); // c /// ``` @@ -438,7 +444,7 @@ pub trait Print { fn println(&mut self, x: T); } -/// Writes a single `&[u8]` using [`Writer::bytes()`] into the standard output. `print()` doesn't add a newline at the end of the output, while `println()` does. +/// Writes a single `&[u8]` using [`Writer::bytes()`] to standard output. Note that `print()` doesn't add a newline at the end of the output. If a newline is needed, use `println()`. impl Print<&[u8]> for Writer { fn print(&mut self, x: &[u8]) { self.bytes(x); @@ -449,7 +455,7 @@ impl Print<&[u8]> for Writer { } } -/// Writes a single `&[u8; M]` using [`Writer::bytes()`] into the standard output. `print()` doesn't add a newline at the end of the output, while `println()` does. +/// Writes a single `&[u8; M]` using [`Writer::bytes()`] to standard output. Note that `print()` doesn't add a newline at the end of the output. If a newline is needed, use `println()`. impl Print<&[u8; M]> for Writer { fn print(&mut self, x: &[u8; M]) { self.bytes(x); @@ -460,7 +466,7 @@ impl Print<&[u8; M]> for Writer { } } -/// Writes a single `&str` using [`Writer::bytes()`] and [`str::as_bytes()`] into the standard output. `print()` doesn't add a newline at the end of the output, while `println()` does. +/// Writes a single `&str` using [`Writer::bytes()`] and [`str::as_bytes()`] to standard output. Note that `print()` doesn't add a newline at the end of the output. If a newline is needed, use `println()`. impl Print<&str> for Writer { fn print(&mut self, x: &str) { self.bytes(x.as_bytes()); @@ -471,7 +477,7 @@ impl Print<&str> for Writer { } } -/// Write a single `String`` using [`Writer::Print<&str>()`] and [`String::as_str()`] into the standard output. `print()` doesn't add a newline at the end of the output, while `println()` does. +/// Write a single `String`` using [`Writer::Print<&str>()`] and [`String::as_str()`] to standard output. Note that `print()` doesn't add a newline at the end of the output. If a newline is needed, use `println()`. impl Print for Writer { fn print(&mut self, x: String) { self.print(x.as_str()); @@ -481,7 +487,7 @@ impl Print for Writer { } } -/// Writes `&String` using `Writer::Print<&str>()` and [`String::as_str()`] into the standard output. `print()` doesn't add a newline at the end of the output, while `println()` does. +/// Writes a single `&String` using `Writer::Print<&str>()` and [`String::as_str()`] to standard output. Note that `print()` doesn't add a newline at the end of the output. If a newline is needed, use `println()`. impl Print<&String> for Writer { fn print(&mut self, x: &String) { self.print(x.as_str());