Skip to content

Commit

Permalink
feat(stdlib): Add copySign, sqrt, min, max, round, trunc,…
Browse files Browse the repository at this point in the history
… `floor`, `ceil` to `Float32` (#2161)

Co-authored-by: Oscar Spencer <oscar.spen@gmail.com>
Co-authored-by: Oscar Spencer <oscar@grain-lang.org>
  • Loading branch information
3 people authored Sep 21, 2024
1 parent 7542d92 commit f5a3dd3
Show file tree
Hide file tree
Showing 3 changed files with 492 additions and 0 deletions.
64 changes: 64 additions & 0 deletions compiler/test/stdlib/float32.test.gr
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,24 @@ assert Float32.isInfinite(-1.0f) == false
assert Float32.isInfinite(25.76f) == false
assert Float32.isInfinite(-25.00f) == false

// min
assert Float32.min(5.0f, 5.0f) == 5.0f
assert Float32.min(5.0f, 6.0f) == 5.0f
assert Float32.min(6.0f, 5.0f) == 5.0f
assert Float32.min(0.5f, 0.25f) == 0.25f
assert Float32.min(Infinityf, 10.0f) == 10.0f
assert Float32.isNaN(Float32.min(NaNf, 10.0f))
assert Float32.isNaN(Float32.min(NaNf, Infinityf))

// max
assert Float32.max(5.0f, 5.0f) == 5.0f
assert Float32.max(6.0f, 5.0f) == 6.0f
assert Float32.max(5.0f, 6.0f) == 6.0f
assert Float32.max(0.5f, 0.25f) == 0.5f
assert Float32.max(Infinityf, 10.0f) == Infinityf
assert Float32.isNaN(Float32.max(NaNf, 10.0f))
assert Float32.isNaN(Float32.max(NaNf, Infinityf))

// abs
assert Float32.abs(-25.5f) == 25.5f
assert Float32.abs(25.5f) == 25.5f
Expand All @@ -141,3 +159,49 @@ assert Float32.neg(-25.5f) == 25.5f
assert Float32.neg(25.5f) == -25.5f
assert Float32.isNaN(-NaNf)
assert Float32.neg(Infinityf) == -Infinityf

// ceil
assert Float32.ceil(-25.5f) == -25.0f
assert Float32.ceil(25.5f) == 26.0f
assert Float32.ceil(25.0f) == 25.0f
assert Float32.isNaN(Float32.ceil(NaNf))
assert Float32.ceil(Infinityf) == Infinityf
// floor
assert Float32.floor(-25.5f) == -26.0f
assert Float32.floor(25.5f) == 25.0f
assert Float32.floor(25.0f) == 25.0f
assert Float32.isNaN(Float32.floor(NaNf))
assert Float32.floor(Infinityf) == Infinityf
// trunc
assert Float32.trunc(-25.5f) == -25.0f
assert Float32.trunc(25.5f) == 25.0f
assert Float32.trunc(25.0f) == 25.0f
assert Float32.isNaN(Float32.trunc(NaNf))
assert Float32.trunc(Infinityf) == Infinityf
// round
assert Float32.round(-25.5f) == -26.0f
assert Float32.round(-25.25f) == -25.0f
assert Float32.round(25.25f) == 25.0f
assert Float32.round(25.5f) == 26.0f
assert Float32.isNaN(Float32.round(NaNf))
assert Float32.round(Infinityf) == Infinityf
// sqrt
assert Float32.sqrt(25.0f) == 5.0f
assert Float32.sqrt(35.0f) == 5.916079783099616f
assert Float32.sqrt(9266609011276477657.0f) == 3044110545.180066f
assert Float32.sqrt(Infinityf) == Infinityf
assert Float32.isNaN(Float32.sqrt(NaNf))
// copySign
assert Float32.copySign(2.0f, 1.0f) == 2.0f
assert Float32.copySign(-2.0f, 1.0f) == 2.0f
assert Float32.copySign(1.0f, 2.0f) == 1.0f
assert Float32.copySign(2.0f, -1.0f) == -2.0f
assert Float32.copySign(1.0f, -2.0f) == -1.0f
assert Float32.copySign(Infinityf, 1.0f) == Infinityf
assert Float32.copySign(Infinityf, -1.0f) == -Infinityf
assert Float32.copySign(1.0f, Infinityf) == 1.0f
assert Float32.copySign(1.0f, -Infinityf) == -1.0f
assert Float32.isNaN(Float32.copySign(NaNf, 1.0f))
assert Float32.isNaN(Float32.copySign(NaNf, -1.0f))
assert Float32.copySign(1.0f, NaNf) == 1.0f
assert Float32.copySign(1.0f, -NaNf) == -1.0f
149 changes: 149 additions & 0 deletions stdlib/float32.gr
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,44 @@ provide let isNaN = (x: Float32) => x != x
*/
provide let isInfinite = (x: Float32) => x == Infinityf || x == -Infinityf

/**
* Returns the smaller of its operands.
*
* @param x: The first operand
* @param y: The second operand
* @returns The smaller of the two operands
*
* @example Float32.min(5.0f, 2.0f) == 2.0f
*
* @since v0.7.0
*/
@unsafe
provide let min = (x: Float32, y: Float32) => {
let xv = WasmF32.load(WasmI32.fromGrain(x), _VALUE_OFFSET)
let yv = WasmF32.load(WasmI32.fromGrain(y), _VALUE_OFFSET)
let ptr = newFloat32(WasmF32.min(xv, yv))
WasmI32.toGrain(ptr): Float32
}

/**
* Returns the larger of its operands.
*
* @param x: The first operand
* @param y: The second operand
* @returns The larger of the two operands
*
* @example Float32.max(5.0f, 2.0f) == 5.0f
*
* @since v0.7.0
*/
@unsafe
provide let max = (x: Float32, y: Float32) => {
let xv = WasmF32.load(WasmI32.fromGrain(x), _VALUE_OFFSET)
let yv = WasmF32.load(WasmI32.fromGrain(y), _VALUE_OFFSET)
let ptr = newFloat32(WasmF32.max(xv, yv))
WasmI32.toGrain(ptr): Float32
}

/**
* Returns the absolute value. That is, it returns `x` if `x` is positive or zero and the negation of `x` if `x` is negative.
*
Expand Down Expand Up @@ -341,3 +379,114 @@ provide let neg = (x: Float32) => {
let ptr = newFloat32(WasmF32.neg(xv))
WasmI32.toGrain(ptr): Float32
}

/**
* Rounds its operand up to the next largest whole value.
*
* @param x: The operand to ceil
* @returns The next largest whole value of the operand
*
* @example Float32.ceil(5.5f) == 6.0f
* @example Float32.ceil(-5.5f) == -5.0f
*
* @since v0.7.0
*/
@unsafe
provide let ceil = (x: Float32) => {
let xv = WasmF32.load(WasmI32.fromGrain(x), _VALUE_OFFSET)
let ptr = newFloat32(WasmF32.ceil(xv))
WasmI32.toGrain(ptr): Float32
}

/**
* Rounds its operand down to the largest whole value less than the operand.
*
* @param x: The operand to floor
* @returns The previous whole value of the operand
*
* @example Float32.floor(5.5f) == 5.0f
* @example Float32.floor(-5.5f) == -6.0f
*
* @since v0.7.0
*/
@unsafe
provide let floor = (x: Float32) => {
let xv = WasmF32.load(WasmI32.fromGrain(x), _VALUE_OFFSET)
let ptr = newFloat32(WasmF32.floor(xv))
WasmI32.toGrain(ptr): Float32
}

/**
* Returns the whole value part of its operand, removing any fractional value.
*
* @param x: The operand to truncate
* @returns The whole value part of the operand
*
* @example Float32.trunc(5.5f) == 5.0f
*
* @since v0.7.0
*/
@unsafe
provide let trunc = (x: Float32) => {
let xv = WasmF32.load(WasmI32.fromGrain(x), _VALUE_OFFSET)
let ptr = newFloat32(WasmF32.trunc(xv))
WasmI32.toGrain(ptr): Float32
}

/**
* Returns its operand rounded to its nearest integer.
*
* @param x: The operand to round
* @returns The nearest integer to the operand
*
* @example Float32.round(5.5f) == 6.0f
* @example Float32.round(5.4f) == 5.0f
* @example Float32.round(-5.5f) == -6.0f
* @example Float32.round(-5.4f) == -5.0f
*
* @since v0.7.0
*/
@unsafe
provide let round = (x: Float32) => {
let xv = WasmF32.load(WasmI32.fromGrain(x), _VALUE_OFFSET)
let ptr = newFloat32(WasmF32.nearest(xv))
WasmI32.toGrain(ptr): Float32
}

/**
* Computes the square root of its operand.
*
* @param x: The operand to square root
* @returns The square root of the operand
*
* @example Float32.sqrt(25.0f) == 5.0f
*
* @since v0.7.0
*/
@unsafe
provide let sqrt = (x: Float32) => {
let xv = WasmF32.load(WasmI32.fromGrain(x), _VALUE_OFFSET)
let ptr = newFloat32(WasmF32.sqrt(xv))
WasmI32.toGrain(ptr): Float32
}

/**
* Copys the sign of the second operand to the first operand.
*
* @param x: The operand to modify
* @param y: The operand to copy the sign from
* @returns The first operand with the sign of the second operand
*
* @example Float32.copySign(2.0f, 1.0f) == 2.0f
* @example Float32.copySign(3.0f, -1.0f) == -3.0f
* @example Float32.copySign(-5.0f, 1.0f) == 5.0f
*
* @since v0.7.0
*/
@unsafe
provide let copySign = (x: Float32, y: Float32) => {
let xv = WasmF32.load(WasmI32.fromGrain(x), _VALUE_OFFSET)
let yv = WasmF32.load(WasmI32.fromGrain(y), _VALUE_OFFSET)
let ptr = newFloat32(WasmF32.copySign(xv, yv))
WasmI32.toGrain(ptr): Float32
}
Loading

0 comments on commit f5a3dd3

Please sign in to comment.