Skip to content

Commit 2e6ae02

Browse files
committed
Add Ldexp
1 parent e2bd1ec commit 2e6ae02

File tree

8 files changed

+22
-132
lines changed

8 files changed

+22
-132
lines changed

cmd/counting/main.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"math"
77

88
"github.com/itsubaki/q"
9+
"github.com/itsubaki/q/math/number"
910
)
1011

1112
func oracle(qsim *q.Q, r, s []q.Qubit, c, a q.Qubit) {
@@ -77,9 +78,9 @@ func main() {
7778
qsim.InvQFT(c...)
7879

7980
// estimate
80-
N, Q := 1<<len(r), 1<<t
81+
N := 1 << len(r)
8182
for _, state := range q.Top(qsim.State(c, r, s, a), top) {
82-
phi := float64(state.Int()[0]) / float64(Q) // phi = k / 2**t
83+
phi := number.Ldexp(state.Int()[0], -t) // phi = k / 2**t
8384
theta := 2 * math.Pi * phi // theta = 2*pi*phi
8485
M := float64(N) * math.Pow(math.Sin(theta/2), 2) // M = N*(sin(theta/2))**2
8586

cmd/shor/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ func main() {
8787
var prop float64
8888
for _, state := range qsim.State(r0) {
8989
i, m := state.Int()[0], state.BinaryString()[0]
90-
s, r, d, ok := number.FindOrder(a, N, fmt.Sprintf("0.%s", m))
90+
s, r, d, ok := number.FindOrder(a, N, number.Ldexp(i, -t))
9191
if !ok || number.IsOdd(r) {
9292
fmt.Printf(" i=%4d: N=%d, a=%d, t=%d; s/r=%4d/%4d ([0.%v]~%.4f);\n", i, N, a, t, s, r, m, d)
9393
continue

math/number/fraction_test.go

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,13 @@ func ExampleContinuedFraction() {
1717
}
1818

1919
func ExampleConvergent() {
20-
m := "0.00101010101"
21-
v, err := number.ParseFloat(m)
22-
fmt.Printf("%v=%v %v\n", m, v, err)
23-
24-
c := number.ContinuedFraction(v)
20+
c := number.ContinuedFraction(number.Ldexp(341, -11))
2521
for i := range c {
2622
s, r, d := number.Convergent(c[:i+1])
2723
fmt.Printf("%v: %v/%v=%v\n", c[:i+1], s, r, d)
2824
}
2925

3026
// Output:
31-
// 0.00101010101=0.16650390625 <nil>
3227
// [0]: 0/1=0
3328
// [0 6]: 1/6=0.16666666666666666
3429
// [0 6 170]: 170/1021=0.1665034280117532

math/number/order.go

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,8 @@
11
package number
22

33
// FindOrder returns convergent s/r and its real number such that a**r mod N = 1.
4-
func FindOrder(a, N int, binary string, tol ...float64) (int, int, float64, bool) {
5-
if len(binary) < 1 {
6-
return 0, 1, 0, false
7-
}
8-
9-
v := Must(ParseFloat(binary))
10-
c := ContinuedFraction(v, tol...)
4+
func FindOrder(a, N int, m float64, tol ...float64) (int, int, float64, bool) {
5+
c := ContinuedFraction(m, tol...)
116

127
s, r, d := Convergent(c[:1])
138
for i := 1; i < len(c); i++ {

math/number/order_test.go

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import (
88
)
99

1010
func ExampleFindOrder_mod15() {
11-
s, r, d, ok := number.FindOrder(7, 15, "0.110")
11+
s, r, d, ok := number.FindOrder(7, 15, number.Ldexp(6, -3))
1212
fmt.Printf("%v/%v=%v %v\n", s, r, d, ok)
1313
fmt.Printf("%d^%d mod %d = %v\n", 7, r, 15, number.ModExp(7, r, 15))
1414

@@ -18,7 +18,7 @@ func ExampleFindOrder_mod15() {
1818
}
1919

2020
func ExampleFindOrder_mod21a2() {
21-
s, r, d, ok := number.FindOrder(2, 21, "0.001010101")
21+
s, r, d, ok := number.FindOrder(2, 21, number.Ldexp(85, -9))
2222
fmt.Printf("%v/%v=%v %v\n", s, r, d, ok)
2323
fmt.Printf("%d^%d mod %d = %v\n", 2, r, 21, number.ModExp(2, r, 21))
2424

@@ -28,7 +28,7 @@ func ExampleFindOrder_mod21a2() {
2828
}
2929

3030
func ExampleFindOrder_mod21a4() {
31-
s, r, d, ok := number.FindOrder(4, 21, "0.01010101")
31+
s, r, d, ok := number.FindOrder(4, 21, number.Ldexp(85, -8))
3232
fmt.Printf("%v/%v=%v %v\n", s, r, d, ok)
3333
fmt.Printf("%d^%d mod %d = %v\n", 4, r, 21, number.ModExp(4, r, 21))
3434

@@ -40,16 +40,15 @@ func ExampleFindOrder_mod21a4() {
4040
func TestFindOrder(t *testing.T) {
4141
cases := []struct {
4242
a, N int
43-
m string
43+
m float64
4444
s, r int
4545
d float64
4646
ok bool
4747
}{
48-
{7, 15, "0.010", 1, 4, 0.25, true},
49-
{7, 15, "0.100", 1, 2, 0.50, false},
50-
{7, 15, "0.110", 3, 4, 0.75, true},
51-
{7, 15, "0.1", 1, 2, 0.5, false},
52-
{7, 15, "", 0, 1, 0, false},
48+
{7, 15, number.Ldexp(2, -3), 1, 4, 0.25, true},
49+
{7, 15, number.Ldexp(4, -3), 1, 2, 0.50, false},
50+
{7, 15, number.Ldexp(6, -3), 3, 4, 0.75, true},
51+
{7, 15, number.Ldexp(1, -1), 1, 2, 0.5, false},
5352
}
5453

5554
for _, c := range cases {

math/number/parse.go

Lines changed: 4 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,13 @@
11
package number
22

33
import (
4-
"errors"
5-
"fmt"
4+
"math"
65
"strconv"
7-
"strings"
86
)
97

10-
var ErrInvalidParameter = errors.New("invalid parameter")
11-
12-
// ParseFloat returns float64 from binary string.
13-
func ParseFloat(binary string) (float64, error) {
14-
if binary == "" || strings.Count(binary, ".") > 1 {
15-
return 0, fmt.Errorf("binary=%q: %w", binary, ErrInvalidParameter)
16-
}
17-
18-
for _, b := range binary {
19-
if b != '0' && b != '1' && b != '.' {
20-
return 0, fmt.Errorf("binary=%q: %w", binary, ErrInvalidParameter)
21-
}
22-
}
23-
24-
// integer part
25-
bin := strings.Split(binary, ".")
26-
p, err := strconv.ParseUint(bin[0], 2, 64)
27-
if err != nil {
28-
return 0, fmt.Errorf("parse binary=%q: %v: %w", binary, err, ErrInvalidParameter)
29-
}
30-
31-
if len(bin) == 1 {
32-
return float64(p), nil
33-
}
34-
35-
// fractional part
36-
frac, f := 0.0, 0.5
37-
for _, b := range bin[1] {
38-
if b == '1' {
39-
frac += f
40-
}
41-
42-
f *= 0.5
43-
}
44-
45-
return float64(p) + frac, nil
8+
// Ldexp returns a * 2**b.
9+
func Ldexp(a, b int) float64 {
10+
return math.Ldexp(float64(a), b)
4611
}
4712

4813
// MustParseInt returns int from binary string.

math/number/parse_test.go

Lines changed: 0 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,79 +1,14 @@
11
package number_test
22

33
import (
4-
"errors"
54
"fmt"
6-
"strings"
7-
"testing"
85

96
"github.com/itsubaki/q/math/number"
107
)
118

12-
func ExampleParseFloat() {
13-
// 0.101 -> 1/2 + 1/8 = 0.5 + 0.125 = 0.625
14-
f, err := number.ParseFloat("0.101")
15-
fmt.Println(f, err)
16-
17-
// Output:
18-
// 0.625 <nil>
19-
}
20-
219
func ExampleMustParseInt() {
2210
fmt.Println(number.MustParseInt("101"))
2311

2412
// Output:
2513
// 5
2614
}
27-
28-
func TestParseFloat(t *testing.T) {
29-
cases := []struct {
30-
in string
31-
want float64
32-
err error
33-
}{
34-
{"0.000", 0.0, nil},
35-
{"0.100", 0.5, nil},
36-
{"0.010", 0.25, nil},
37-
{"0.110", 0.75, nil},
38-
{"0.001", 0.125, nil},
39-
{"0.101", 0.625, nil},
40-
{"0.011", 0.375, nil},
41-
{"0.111", 0.875, nil},
42-
{"11.000", 3.0, nil},
43-
{"11.010", 3.25, nil},
44-
{"111", 7.0, nil},
45-
{"0.01101010101", 0.41650390625, nil},
46-
{"0.001010101010101", 0.166656494140625, nil},
47-
{"a.bbb.ccc", 0, number.ErrInvalidParameter},
48-
{"a.bbb", 0, number.ErrInvalidParameter},
49-
{"a.001", 0, number.ErrInvalidParameter},
50-
{"0.bbb", 0, number.ErrInvalidParameter},
51-
{"0.1.0", 0, number.ErrInvalidParameter},
52-
{"", 0, number.ErrInvalidParameter},
53-
{strings.Repeat("1", 65), 0, number.ErrInvalidParameter},
54-
}
55-
56-
for _, c := range cases {
57-
got, err := number.ParseFloat(c.in)
58-
if err != nil && !errors.Is(err, c.err) {
59-
t.Errorf("parse float: %v", err)
60-
}
61-
62-
if got == c.want {
63-
continue
64-
}
65-
66-
t.Errorf("got=%v, want=%v", got, c.want)
67-
}
68-
}
69-
70-
func FuzzParseFloat(f *testing.F) {
71-
seed := []string{"123", "101", "1.0101", "abc", "a.bc"}
72-
for i := range seed {
73-
f.Add(seed[i])
74-
}
75-
76-
f.Fuzz(func(t *testing.T, v string) {
77-
_, _ = number.ParseFloat(v)
78-
})
79-
}

q_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -999,10 +999,10 @@ func Example_shor15() {
999999
}
10001000

10011001
// measure q0, q1, q2
1002-
m := qsim.Measure(q0, q1, q2).BinaryString()
1002+
m := qsim.Measure(q0, q1, q2)
10031003

10041004
// find s/r. 0.010 -> 0.25 -> 1/4, 0.110 -> 0.75 -> 3/4, ...
1005-
s, r, d, ok := number.FindOrder(a, N, fmt.Sprintf("0.%s", m))
1005+
s, r, d, ok := number.FindOrder(a, N, number.Ldexp(m.Int(), -3))
10061006
if !ok || number.IsOdd(r) {
10071007
return
10081008
}
@@ -1016,7 +1016,7 @@ func Example_shor15() {
10161016
return
10171017
}
10181018

1019-
fmt.Printf("N=%d, a=%d. p=%v, q=%v. s/r=%d/%d ([0.%v]~%.3f)\n", N, a, p0, p1, s, r, m, d)
1019+
fmt.Printf("N=%d, a=%d. p=%v, q=%v. s/r=%d/%d ([0.%v]~%.3f)\n", N, a, p0, p1, s, r, m.BinaryString(), d)
10201020

10211021
// Output:
10221022
// [000][ 0]( 0.5000 0.0000i): 0.2500

0 commit comments

Comments
 (0)