mirror of
https://github.com/odin-lang/Odin.git
synced 2026-04-29 17:53:58 +00:00
Merge pull request #3667 from Feoramund/fix-fmt-compquat-sign
Fix printing of duplicate signs in complex and quaternion types
This commit is contained in:
@@ -2,6 +2,7 @@ package fmt
|
||||
|
||||
import "base:intrinsics"
|
||||
import "base:runtime"
|
||||
import "core:math"
|
||||
import "core:math/bits"
|
||||
import "core:mem"
|
||||
import "core:io"
|
||||
@@ -2968,6 +2969,21 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) {
|
||||
fmt_bit_field(fi, v, verb, info, "")
|
||||
}
|
||||
}
|
||||
// This proc helps keep some of the code around whether or not to print an
|
||||
// intermediate plus sign in complexes and quaternions more readable.
|
||||
@(private)
|
||||
_cq_should_print_intermediate_plus :: proc "contextless" (fi: ^Info, f: f64) -> bool {
|
||||
if !fi.plus && f >= 0 {
|
||||
#partial switch math.classify(f) {
|
||||
case .Neg_Zero, .Inf:
|
||||
// These two classes print their own signs.
|
||||
return false
|
||||
case:
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
// Formats a complex number based on the given formatting verb
|
||||
//
|
||||
// Inputs:
|
||||
@@ -2981,7 +2997,7 @@ fmt_complex :: proc(fi: ^Info, c: complex128, bits: int, verb: rune) {
|
||||
case 'f', 'F', 'v', 'h', 'H', 'w':
|
||||
r, i := real(c), imag(c)
|
||||
fmt_float(fi, r, bits/2, verb)
|
||||
if !fi.plus && i >= 0 {
|
||||
if _cq_should_print_intermediate_plus(fi, i) {
|
||||
io.write_rune(fi.writer, '+', &fi.n)
|
||||
}
|
||||
fmt_float(fi, i, bits/2, verb)
|
||||
@@ -3007,19 +3023,19 @@ fmt_quaternion :: proc(fi: ^Info, q: quaternion256, bits: int, verb: rune) {
|
||||
|
||||
fmt_float(fi, r, bits/4, verb)
|
||||
|
||||
if !fi.plus && i >= 0 {
|
||||
if _cq_should_print_intermediate_plus(fi, i) {
|
||||
io.write_rune(fi.writer, '+', &fi.n)
|
||||
}
|
||||
fmt_float(fi, i, bits/4, verb)
|
||||
io.write_rune(fi.writer, 'i', &fi.n)
|
||||
|
||||
if !fi.plus && j >= 0 {
|
||||
if _cq_should_print_intermediate_plus(fi, j) {
|
||||
io.write_rune(fi.writer, '+', &fi.n)
|
||||
}
|
||||
fmt_float(fi, j, bits/4, verb)
|
||||
io.write_rune(fi.writer, 'j', &fi.n)
|
||||
|
||||
if !fi.plus && k >= 0 {
|
||||
if _cq_should_print_intermediate_plus(fi, k) {
|
||||
io.write_rune(fi.writer, '+', &fi.n)
|
||||
}
|
||||
fmt_float(fi, k, bits/4, verb)
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package test_core_fmt
|
||||
|
||||
import "base:runtime"
|
||||
import "core:fmt"
|
||||
import "core:math"
|
||||
import "core:mem"
|
||||
import "core:testing"
|
||||
|
||||
@@ -22,6 +24,70 @@ test_fmt_memory :: proc(t: ^testing.T) {
|
||||
check(t, "0b", "%m", u8(0))
|
||||
}
|
||||
|
||||
@(test)
|
||||
test_fmt_complex_quaternion :: proc(t: ^testing.T) {
|
||||
neg_inf := math.inf_f64(-1)
|
||||
pos_inf := math.inf_f64(+1)
|
||||
neg_zero := f64(0h80000000_00000000)
|
||||
nan := math.nan_f64()
|
||||
|
||||
// NOTE(Feoramund): Doing it this way, because complex construction is broken.
|
||||
// Reported in issue #3665.
|
||||
c: complex128
|
||||
cptr := cast(^runtime.Raw_Complex128)&c
|
||||
|
||||
cptr^ = {0, 0}
|
||||
check(t, "0+0i", "%v", c)
|
||||
cptr^ = {1, 1}
|
||||
check(t, "1+1i", "%v", c)
|
||||
cptr^ = {1, 0}
|
||||
check(t, "1+0i", "%v", c)
|
||||
cptr^ = {-1, -1}
|
||||
check(t, "-1-1i", "%v", c)
|
||||
cptr^ = {0, neg_zero}
|
||||
check(t, "0-0i", "%v", c)
|
||||
cptr^ = {nan, nan}
|
||||
check(t, "NaNNaNi", "%v", c)
|
||||
cptr^ = {pos_inf, pos_inf}
|
||||
check(t, "+Inf+Infi", "%v", c)
|
||||
cptr^ = {neg_inf, neg_inf}
|
||||
check(t, "-Inf-Infi", "%v", c)
|
||||
|
||||
// Check forced plus signs.
|
||||
cptr^ = {0, neg_zero}
|
||||
check(t, "+0-0i", "%+v", c)
|
||||
cptr^ = {1, 1}
|
||||
check(t, "+1+1i", "%+v", c)
|
||||
cptr^ = {nan, nan}
|
||||
check(t, "NaNNaNi", "%+v", c)
|
||||
cptr^ = {pos_inf, pos_inf}
|
||||
check(t, "+Inf+Infi", "%+v", c)
|
||||
cptr^ = {neg_inf, neg_inf}
|
||||
check(t, "-Inf-Infi", "%+v", c)
|
||||
|
||||
// Remember that the real number is the last in a quaternion's data layout,
|
||||
// opposed to a complex, where it is the first.
|
||||
q: quaternion256
|
||||
qptr := cast(^runtime.Raw_Quaternion256)&q
|
||||
|
||||
qptr^ = {0, 0, 0, 0}
|
||||
check(t, "0+0i+0j+0k", "%v", q)
|
||||
qptr^ = {1, 1, 1, 1}
|
||||
check(t, "1+1i+1j+1k", "%v", q)
|
||||
qptr^ = {2, 3, 4, 1}
|
||||
check(t, "1+2i+3j+4k", "%v", q)
|
||||
qptr^ = {-1, -1, -1, -1}
|
||||
check(t, "-1-1i-1j-1k", "%v", q)
|
||||
qptr^ = {2, neg_zero, neg_zero, 1}
|
||||
check(t, "1+2i-0j-0k", "%v", q)
|
||||
qptr^ = {neg_inf, neg_inf, neg_inf, -1}
|
||||
check(t, "-1-Infi-Infj-Infk", "%v", q)
|
||||
qptr^ = {pos_inf, pos_inf, pos_inf, -1}
|
||||
check(t, "-1+Infi+Infj+Infk", "%v", q)
|
||||
qptr^ = {nan, nan, nan, -1}
|
||||
check(t, "-1NaNiNaNjNaNk", "%v", q)
|
||||
}
|
||||
|
||||
@(test)
|
||||
test_fmt_doc_examples :: proc(t: ^testing.T) {
|
||||
// C-like syntax
|
||||
|
||||
Reference in New Issue
Block a user