profile
viewpoint

bmkessler/fastdiv 78

Fast division, modulus and divisibility checks in Go for divisors known only at runtime.

bmkessler/gimli 17

golang port of Gimli, https://gimli.cr.yp.to, a 384-bit permutation designed to achieve high security with high performance across a broad range of platforms.

bmkessler/haraka 13

A golang implementation of the Haraka v2 family of hash functions

bmkessler/Kaggle_Social_Circles 3

Code for analysis in the Learning Social Circles in Networks Competition on Kaggle

bmkessler/streamstats 2

Streaming stats data structures and algorithms for golang

bmkessler/autohl-js 1

Auto-highlighter in JavaScript for chrome extension

bmkessler/2048 0

A small clone of 1024 (https://play.google.com/store/apps/details?id=com.veewo.a1024)

bmkessler/affinity-propagation 0

A visualization of the affinity propagation clustering algorithm using HTML5 canvas and javascript.

bmkessler/aprsgo 0

Golang implementation of Automatic Packet Reporting System (APRS) Tx/Rx

bmkessler/Assteroids 0

A port of asteroids to Love2D Lua game engine

issue commentgolang/go

cmd/compile: optimize division for positive integers

Yes, that is just a special case where all positive int64 are automatically less than 1<<63, so the second condition is not needed.

rillig

comment created time in a day

startedmicrosoft/ApplicationInspector

started time in a month

startedjaakkopasanen/AutoEq

started time in a month

startedmagenta/ddsp

started time in a month

startedgordonklaus/portaudio

started time in a month

startedpornin/curve9767

started time in 2 months

startedgoogle/wuffs

started time in 2 months

issue commentgolang/go

cmd/compile: optimize division for positive integers

This looks to be a limitation with prove results not being available to rewrite rules, since there are rewrite rules to handle this case:

(Div64 n (Const64 [c])) && isNonNegative(n) && isPowerOfTwo(c)            -> (Rsh64Ux64 n (Const64 <typ.UInt64> [log2(c)]))
(Mod64 <t> n (Const64 [c])) && isNonNegative(n) && isPowerOfTwo(c)            -> (And64 n (Const64 <t> [c-1]))

But the implementation of isNonNegative really only handles constants and a few special operations like len/cap.

// isNonNegative reports whether v is known to be greater or equal to zero.
func isNonNegative(v *Value) bool {
	switch v.Op {
	case OpConst64:
		return v.AuxInt >= 0

	case OpConst32:
		return int32(v.AuxInt) >= 0

	case OpStringLen, OpSliceLen, OpSliceCap,
		OpZeroExt8to64, OpZeroExt16to64, OpZeroExt32to64:
		return true

	case OpRsh64Ux64:
		by := v.Args[1]
		return by.Op == OpConst64 && by.AuxInt > 0

	case OpRsh64x64:
		return isNonNegative(v.Args[0])
	}
	return false
}

The division could be handled if the factsTable version of isNonNegative were available.

// isNonNegative reports whether v is known to be non-negative.
func (ft *factsTable) isNonNegative(v *Value) bool

Unfortunately, the first opt pass happens before prove even has a chance to deduce the numerator is non-negative, so the generic rule has already fired.

// Signed divide by power of 2.
// n / c =       n >> log(c) if n >= 0
//       = (n+c-1) >> log(c) if n < 0
// We conditionally add c-1 by adding n>>63>>(64-log(c)) (first shift signed, second shift unsigned).
(Div64 <t> n (Const64 [c])) && isPowerOfTwo(c) ->
  (Rsh64x64
    (Add64 <t> n (Rsh64Ux64 <t> (Rsh64x64 <t> n (Const64 <typ.UInt64> [63])) (Const64 <typ.UInt64> [64-log2(c)])))
    (Const64 <typ.UInt64> [log2(c)]))

Currently, the prove pass only removes redundant BlockIf branches, but I don't see any reason why it shouldn't be able to make other simplifications as well. In this case, it could use the knowledge that ft.isNonNegative(n) to simplify (Rsh64x64 <t> n (Const64 <typ.UInt64> [63])) -> 0 and equivalent for 32/16/8, that should eliminate all the unnecessary division fixups for constant division I believe after late opt does some further simplification. Note that there are other closely related rewrites that would be available to prove such as zeroing right shifts of known to be small numbers, (RshU64x64 n [c]) is 0 whenever 0 <= n < 1<<c.

rillig

comment created time in 2 months

startedyandex/odyssey

started time in 2 months

startedsegmentio/encoding

started time in 3 months

issue commentgolang/go

math: discrepancy in Atan2 special case

This causes s390x test failures on https://github.com/golang/go/issues/29320 for cmplx.Log and cmplx.Log10

bmkessler

comment created time in 4 months

issue commentgolang/go

math: discrepancy in Atan2 special case

@griesemer @ianlancetaylor @mundaym

bmkessler

comment created time in 4 months

issue openedgolang/go

math: discrepancy in Atan2 special case

<pre> $ go version go version go1.13.4 linux/amd64 </pre>

Does this issue reproduce with the latest release?

yes

The special cases for Atan2 are

// Special cases are (in order):
//	Atan2(y, NaN) = NaN
//	Atan2(NaN, x) = NaN
//	Atan2(+0, x>=0) = +0
//	Atan2(-0, x>=0) = -0
//	Atan2(+0, x<=-0) = +Pi
//	Atan2(-0, x<=-0) = -Pi
//	Atan2(y>0, 0) = +Pi/2
//	Atan2(y<0, 0) = -Pi/2
//	Atan2(+Inf, +Inf) = +Pi/4
//	Atan2(-Inf, +Inf) = -Pi/4
//	Atan2(+Inf, -Inf) = 3Pi/4
//	Atan2(-Inf, -Inf) = -3Pi/4
//	Atan2(y, +Inf) = 0
//	Atan2(y>0, -Inf) = +Pi
//	Atan2(y<0, -Inf) = -Pi
//	Atan2(+Inf, x) = +Pi/2
//	Atan2(-Inf, x) = -Pi/2

Atan2(y, +Inf) = 0 is handled differently between the pure go code and the s390x implementation.

The pure go implementation actually conforms to C99 Annex F. 9.1.4 which specifies:

atan2(±y,+∞) returns ± 0 for finite y>0.

Specifically, the sign of zero depends on the sign of y, while the s390x implementation returns +0 for all values of y.

Note that this behavior affects special case handling of math/cmplx as well since those functions rely on math for the underlying implementations.

A decision should be made on what the specification should state for the sign of zero in this case. I am not sure if updating the go specification to depend on the sign of y (C99) would be incompatible with the go compatibility promise since the current specification doesn't explicitly state that the sign should be positive. It seems that the majority implementation is already conforming to the C99 specification in any case.

created time in 4 months

issue commentgolang/go

math/cmplx: TestAtan and friends failing on several platforms

for s390x

--- FAIL: TestAtan (0.00s)
    cmath_test.go:1018: Atan((1+0i)) = (0.7853981633974484+0i), want (0.7853981633974483+0i)
    cmath_test.go:1026: Atan((1-0i)) = (0.7853981633974484-0i), want (0.7853981633974483-0i)
    cmath_test.go:1030: Atan((-1-0i)) = (-0.7853981633974484-0i), want (-0.7853981633974483-0i)
--- FAIL: TestLog (0.00s)
    cmath_test.go:1163: Log((+Inf-1i)) = (+Inf+0i), want (+Inf-0i)
--- FAIL: TestLog10 (0.00s)
    cmath_test.go:1184: Log10((+Inf-1i)) = (+Inf+0i), want (+Inf-0i)

The first failures are due to the test being too strict for checking the value of math.Atan(re) it should be converted to use cVeryClose instead of cAlike

The failures on Log are actually a discrepancy in s390x handling of math.Atan2(imag(x), real(x))

Log(x) == complex(math.Log(Abs(x)), Phase(x)) == complex(math.Log(Abs(x)), math.Atan2(imag(x), real(x))

so the issue is that math.Atan2(-1, +Inf) should equal -0, but does not on s390x.

Note C99 Annex F. 9.1.4 specifies:

atan2(±y,+∞) returns ± 0 for finite y>0.

But the go documentation for math.Atan2 doesn't actually specify the sign.

// Atan2(y, +Inf) = 0

However, the pure go implementation matches the C99 handling of the sign of zero.

The mips failures

--- FAIL: TestAtan (0.00s)
    cmath_test.go:1030: Atan((-Inf+NaNi)) = (-1.5707963267948966+0i), want (-1.5707963267948966-0i)
--- FAIL: TestCosh (0.00s)
    cmath_test.go:1124: Cosh((-0+NaNi)) = (NaN-0i), want (NaN+0i)
--- FAIL: TestTanh (0.00s)
    cmath_test.go:1357: Tanh((-Inf+NaNi)) = (-1+0i), want (-1-0i)

are due to errors in the test code with respect to NaN sign handling. The tests have cases that check f(x) == f(-x) for appropriate functions, but -x does not necessarily change the sign bit of NaN and math.Copysign should be used instead.

The two issues with the test code are easy fixes, but a decision should be made about the Atan2 special case that disagrees between the Go documentation (s390x implementation) and the C99 standard (pure go implementation).

mknyszek

comment created time in 4 months

starteddarold/pgbadger

started time in 4 months

startedjfcoz/postgresqltuner

started time in 4 months

startedapache/incubator-superset

started time in 4 months

startedmgartner/pg_flame

started time in 4 months

startedjrfonseca/xdot.py

started time in 6 months

issue commentgolang/go

cmd/compile: optimize int % powerOfTwo != 0

Note https://github.com/golang/go/commit/44343c777ca8c02262d1d381a2cc24866b3c5414 added rules for signed divisibility checks for powers of two, i.e. x%(1<<k) == 0 So that

func bitTestArith(i int) int {
	if i%2 == 0 {
		return 0
	}
	return 1
}

func bitTestBinary(i int) int {
	if i&1 == 0 {
		return 0
	}
	return 1
}

func bitTestNegArith(i int) int {
	if !(i%2 == 0) {
		return 1
	}
	return 0
}

all compile identically using go 1.13 https://godbolt.org/z/bhDShH. Adding the not divisible rules is just identical copies of the existing rules but matching the not equal condition.

rillig

comment created time in 6 months

more