| ... | @@ -57,8 +57,11 @@ pub fn calcSetStringLimbsBufferLen(base: u8, string_len: usize) usize { | ... | @@ -57,8 +57,11 @@ pub fn calcSetStringLimbsBufferLen(base: u8, string_len: usize) usize { |
| 57 | return calcMulLimbsBufferLen(limb_count, limb_count, 2); | 57 | return calcMulLimbsBufferLen(limb_count, limb_count, 2); |
| 58 | } | 58 | } |
| 59 | | 59 | |
| | 60 | /// Assumes `string_len` doesn't account for minus signs if the number is negative. |
| 60 | pub fn calcSetStringLimbCount(base: u8, string_len: usize) usize { | 61 | pub fn calcSetStringLimbCount(base: u8, string_len: usize) usize { |
| 61 | return (string_len + (limb_bits / base - 1)) / (limb_bits / base); | 62 | const base_f: f32 = @floatFromInt(base); |
| | 63 | const string_len_f: f32 = @floatFromInt(string_len); |
| | 64 | return 1 + @as(usize, @intFromFloat(@ceil(string_len_f * std.math.log2(base_f) / limb_bits))); |
| 62 | } | 65 | } |
| 63 | | 66 | |
| 64 | pub fn calcPowLimbsBufferLen(a_bit_count: usize, y: usize) usize { | 67 | pub fn calcPowLimbsBufferLen(a_bit_count: usize, y: usize) usize { |
| ... | @@ -280,7 +283,7 @@ pub const Mutable = struct { | ... | @@ -280,7 +283,7 @@ pub const Mutable = struct { |
| 280 | /// | 283 | /// |
| 281 | /// Asserts there is enough memory for the value in `self.limbs`. An upper bound on number of limbs can | 284 | /// Asserts there is enough memory for the value in `self.limbs`. An upper bound on number of limbs can |
| 282 | /// be determined with `calcSetStringLimbCount`. | 285 | /// be determined with `calcSetStringLimbCount`. |
| 283 | /// Asserts the base is in the range [2, 16]. | 286 | /// Asserts the base is in the range [2, 36]. |
| 284 | /// | 287 | /// |
| 285 | /// Returns an error if the value has invalid digits for the requested base. | 288 | /// Returns an error if the value has invalid digits for the requested base. |
| 286 | /// | 289 | /// |
| ... | @@ -296,7 +299,8 @@ pub const Mutable = struct { | ... | @@ -296,7 +299,8 @@ pub const Mutable = struct { |
| 296 | limbs_buffer: []Limb, | 299 | limbs_buffer: []Limb, |
| 297 | allocator: ?Allocator, | 300 | allocator: ?Allocator, |
| 298 | ) error{InvalidCharacter}!void { | 301 | ) error{InvalidCharacter}!void { |
| 299 | assert(base >= 2 and base <= 16); | 302 | assert(base >= 2); |
| | 303 | assert(base <= 36); |
| 300 | | 304 | |
| 301 | var i: usize = 0; | 305 | var i: usize = 0; |
| 302 | var positive = true; | 306 | var positive = true; |
| ... | @@ -2283,11 +2287,11 @@ pub const Const = struct { | ... | @@ -2283,11 +2287,11 @@ pub const Const = struct { |
| 2283 | | 2287 | |
| 2284 | /// Converts self to a string in the requested base. | 2288 | /// Converts self to a string in the requested base. |
| 2285 | /// Caller owns returned memory. | 2289 | /// Caller owns returned memory. |
| 2286 | /// Asserts that `base` is in the range [2, 16]. | 2290 | /// Asserts that `base` is in the range [2, 36]. |
| 2287 | /// See also `toString`, a lower level function than this. | 2291 | /// See also `toString`, a lower level function than this. |
| 2288 | pub fn toStringAlloc(self: Const, allocator: Allocator, base: u8, case: std.fmt.Case) Allocator.Error![]u8 { | 2292 | pub fn toStringAlloc(self: Const, allocator: Allocator, base: u8, case: std.fmt.Case) Allocator.Error![]u8 { |
| 2289 | assert(base >= 2); | 2293 | assert(base >= 2); |
| 2290 | assert(base <= 16); | 2294 | assert(base <= 36); |
| 2291 | | 2295 | |
| 2292 | if (self.eqlZero()) { | 2296 | if (self.eqlZero()) { |
| 2293 | return allocator.dupe(u8, "0"); | 2297 | return allocator.dupe(u8, "0"); |
| ... | @@ -2302,7 +2306,7 @@ pub const Const = struct { | ... | @@ -2302,7 +2306,7 @@ pub const Const = struct { |
| 2302 | } | 2306 | } |
| 2303 | | 2307 | |
| 2304 | /// Converts self to a string in the requested base. | 2308 | /// Converts self to a string in the requested base. |
| 2305 | /// Asserts that `base` is in the range [2, 16]. | 2309 | /// Asserts that `base` is in the range [2, 36]. |
| 2306 | /// `string` is a caller-provided slice of at least `sizeInBaseUpperBound` bytes, | 2310 | /// `string` is a caller-provided slice of at least `sizeInBaseUpperBound` bytes, |
| 2307 | /// where the result is written to. | 2311 | /// where the result is written to. |
| 2308 | /// Returns the length of the string. | 2312 | /// Returns the length of the string. |
| ... | @@ -2312,7 +2316,7 @@ pub const Const = struct { | ... | @@ -2312,7 +2316,7 @@ pub const Const = struct { |
| 2312 | /// See also `toStringAlloc`, a higher level function than this. | 2316 | /// See also `toStringAlloc`, a higher level function than this. |
| 2313 | pub fn toString(self: Const, string: []u8, base: u8, case: std.fmt.Case, limbs_buffer: []Limb) usize { | 2317 | pub fn toString(self: Const, string: []u8, base: u8, case: std.fmt.Case, limbs_buffer: []Limb) usize { |
| 2314 | assert(base >= 2); | 2318 | assert(base >= 2); |
| 2315 | assert(base <= 16); | 2319 | assert(base <= 36); |
| 2316 | | 2320 | |
| 2317 | if (self.eqlZero()) { | 2321 | if (self.eqlZero()) { |
| 2318 | string[0] = '0'; | 2322 | string[0] = '0'; |
| ... | @@ -2816,7 +2820,7 @@ pub const Managed = struct { | ... | @@ -2816,7 +2820,7 @@ pub const Managed = struct { |
| 2816 | /// | 2820 | /// |
| 2817 | /// self's allocator is used for temporary storage to boost multiplication performance. | 2821 | /// self's allocator is used for temporary storage to boost multiplication performance. |
| 2818 | pub fn setString(self: *Managed, base: u8, value: []const u8) !void { | 2822 | pub fn setString(self: *Managed, base: u8, value: []const u8) !void { |
| 2819 | if (base < 2 or base > 16) return error.InvalidBase; | 2823 | if (base < 2 or base > 36) return error.InvalidBase; |
| 2820 | try self.ensureCapacity(calcSetStringLimbCount(base, value.len)); | 2824 | try self.ensureCapacity(calcSetStringLimbCount(base, value.len)); |
| 2821 | const limbs_buffer = try self.allocator.alloc(Limb, calcSetStringLimbsBufferLen(base, value.len)); | 2825 | const limbs_buffer = try self.allocator.alloc(Limb, calcSetStringLimbsBufferLen(base, value.len)); |
| 2822 | defer self.allocator.free(limbs_buffer); | 2826 | defer self.allocator.free(limbs_buffer); |
| ... | @@ -2843,7 +2847,7 @@ pub const Managed = struct { | ... | @@ -2843,7 +2847,7 @@ pub const Managed = struct { |
| 2843 | /// Converts self to a string in the requested base. Memory is allocated from the provided | 2847 | /// Converts self to a string in the requested base. Memory is allocated from the provided |
| 2844 | /// allocator and not the one present in self. | 2848 | /// allocator and not the one present in self. |
| 2845 | pub fn toString(self: Managed, allocator: Allocator, base: u8, case: std.fmt.Case) ![]u8 { | 2849 | pub fn toString(self: Managed, allocator: Allocator, base: u8, case: std.fmt.Case) ![]u8 { |
| 2846 | if (base < 2 or base > 16) return error.InvalidBase; | 2850 | if (base < 2 or base > 36) return error.InvalidBase; |
| 2847 | return self.toConst().toStringAlloc(allocator, base, case); | 2851 | return self.toConst().toStringAlloc(allocator, base, case); |
| 2848 | } | 2852 | } |
| 2849 | | 2853 | |