Skip to content

Commit

Permalink
Add bin() builtin function
Browse files Browse the repository at this point in the history
Signed-off-by: Brian Grenier <[email protected]>
  • Loading branch information
bgreni committed May 10, 2024
1 parent 04e984a commit 0e60cf7
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 0 deletions.
80 changes: 80 additions & 0 deletions stdlib/src/builtin/bin.mojo
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# ===----------------------------------------------------------------------=== #
# Copyright (c) 2024, Modular Inc. All rights reserved.
#
# Licensed under the Apache License v2.0 with LLVM Exceptions:
# https://llvm.org/LICENSE.txt
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ===----------------------------------------------------------------------=== #
"""Implements the `bin()` function
These are Mojo built-ins, so you don't need to import them.
"""


@always_inline("nodebug")
fn bin(b: Scalar[DType.bool]) -> String:
"""Returns the binary representation of a scalar bool.
Args:
b: A scalar bool value.
Returns:
The binary string representation of b.
"""
return bin(int(b))


fn bin[type: DType](num: Scalar[type]) -> String:
"""Return the binary string representation an integral value.
```mojo
print(bin(123))
print(bin(-123))
```
```plaintext
'0b1111011'
'-0b1111011'
```
Parameters:
type: The data type of the integral scalar.
Args:
num: An integral scalar value.
Returns:
The binary string representation of num.
"""
constrained[type.is_integral(), "Expected integral value"]()
alias BIN_PREFIX = "0b"

if num == 0:
return BIN_PREFIX + "0"

var result = String()
var cpy = abs(num)
while cpy > 0:
result += str(cpy & 1)
cpy = cpy >> 1

result = BIN_PREFIX + result[::-1]
return "-" + result if num < 0 else result


@always_inline("nodebug")
fn bin(num: Int) -> String:
"""Returns the binary representation of an Int.
Args:
num: An Int value.
Returns:
The binary string representation of num.
"""
# TODO: Should accept any type that implements the __index__ method according to Python
return bin(Scalar[DType.index](num))
44 changes: 44 additions & 0 deletions stdlib/test/builtin/test_bin.mojo
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# ===----------------------------------------------------------------------=== #
# Copyright (c) 2024, Modular Inc. All rights reserved.
#
# Licensed under the Apache License v2.0 with LLVM Exceptions:
# https://llvm.org/LICENSE.txt
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ===----------------------------------------------------------------------=== #
# RUN: %mojo -debug-level full %s

from testing import assert_equal


def test_bin_scalar():
assert_equal(bin(Int8(2)), "0b10")
assert_equal(bin(Int32(123)), "0b1111011")
assert_equal(bin(Int32(-123)), "-0b1111011")
assert_equal(bin(Scalar[DType.bool](True)), "0b1")
assert_equal(bin(Scalar[DType.bool](False)), "0b0")


def test_bin_int():
assert_equal(bin(0), "0b0")
assert_equal(bin(1), "0b1")
assert_equal(bin(-1), "-0b1")
assert_equal(bin(4), "0b100")
assert_equal(bin(Int(-4)), "-0b100")
assert_equal(bin(389703), "0b1011111001001000111")
assert_equal(bin(-10), "-0b1010")


# def test_bin_bool():
# assert_equal(bin(True), '0b1')
# assert_equal(bin(False), '0b0')


def main():
test_bin_scalar()
test_bin_int()
# test_bin_bool()

0 comments on commit 0e60cf7

Please sign in to comment.