# Arithmetic operators on bool type

**URL:** <https://discourse.julialang.org/t/arithmetic-operators-on-bool-type/61192>\
**Category:** New to Julia\
**Tags:** question\
**Created:** [May 15, 2021, 8:04am UTC](https://discourse.julialang.org/t/arithmetic-operators-on-bool-type/61192 "2021-05-15T08:04:15Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![roi.holtzman](https://avatars.discourse-cdn.com/v4/letter/r/f05b48/32.png) [@roi.holtzman](https://discourse.julialang.org/u/roi.holtzman)\
**Post date:** [May 15, 2021, 8:04am UTC](https://discourse.julialang.org/t/arithmetic-operators-on-bool-type/61192/1 "2021-05-15T08:04:16Z")

</div>

I need to manipulate an array that can take the values -1,+1. I was thinking that it would be memory efficient to use a `Bool` array.  
I also need to perform calculations, and when I operate on a `false` it gives back `0`. Is there an efficient way to make julia consider `false` as `-1`?

---

<div class="post-metadata">

**Author:** ![roflmaostc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/roflmaostc/32/30123_2.png) [@roflmaostc](https://discourse.julialang.org/u/roflmaostc)\
**Post date:** [May 15, 2021, 8:30am UTC](https://discourse.julialang.org/t/arithmetic-operators-on-bool-type/61192/2 "2021-05-15T08:30:09Z")

</div>

A `Bool` takes currently one byte (8 bit) , so it needs the same memory as a `Int8`. In your case an `Array{Int8} ` probably makes sense.

---

<div class="post-metadata">

**Author:** ![roi.holtzman](https://avatars.discourse-cdn.com/v4/letter/r/f05b48/32.png) [@roi.holtzman](https://discourse.julialang.org/u/roi.holtzman)\
**Post date:** [May 15, 2021, 9:09am UTC](https://discourse.julialang.org/t/arithmetic-operators-on-bool-type/61192/3 "2021-05-15T09:09:11Z")

</div>

In that case, you’re right:) thanks!

---

<div class="post-metadata">

**Author:** ![RGerzaguet](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rgerzaguet/32/45492_2.png) [@RGerzaguet](https://discourse.julialang.org/u/RGerzaguet)\
**Post date:** [May 15, 2021, 11:31am UTC](https://discourse.julialang.org/t/arithmetic-operators-on-bool-type/61192/4 "2021-05-15T11:31:08Z")

</div>

> [@roi.holtzman](#):
>
> I also need to perform calculations, and when I operate on a `false` it gives back `0` . Is there an efficient way to make julia consider `false` as `-1` ?

Not really sure on what computation you envision but the easiest way is probably to directly use woolen operation such as `&`that returns a 0 (or false)

---

<div class="post-metadata">

**Author:** ![gustaphe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gustaphe/32/18174_2.png) [@gustaphe](https://discourse.julialang.org/u/gustaphe)\
**Post date:** [May 15, 2021, 11:31am UTC](https://discourse.julialang.org/t/arithmetic-operators-on-bool-type/61192/5 "2021-05-15T11:31:39Z")

</div>

This is true for `Bool`, but the question stands with the correction that op is looking for `BitArray`.

You should probably define your own type that wraps a `BitArray`, and define arithmetic operations on it.

---

<div class="post-metadata">

**Author:** ![gustaphe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gustaphe/32/18174_2.png) [@gustaphe](https://discourse.julialang.org/u/gustaphe)\
**Post date:** [May 15, 2021, 12:01pm UTC](https://discourse.julialang.org/t/arithmetic-operators-on-bool-type/61192/6 "2021-05-15T12:01:41Z")

</div>

Here’s a start:

```julia
struct FlipFlop{N} <: AbstractArray{Int8, N}
    x::BitArray{N}
end

FlipFlop(x::AbstractArray) = FlipFlop(x .> 0)

size(x::FlipFlop) = size(x.x)
getindex(x::FlipFlop, i) = x.x[i] ? Int8(1) : Int8(-1)

```

I don’t know what kind of operations you need, but this will do the basic stuff – displaying reasonably, returning a `-1` if you ask for one, and mathematics. The maths will not be optimized though, it will convert into an `Array{Int8}` on any operation. But you can redefine the operators you care about to stay in the `FlipFlop` realm.

---

<div class="post-metadata">

**Author:** ![roi.holtzman](https://avatars.discourse-cdn.com/v4/letter/r/f05b48/32.png) [@roi.holtzman](https://discourse.julialang.org/u/roi.holtzman)\
**Post date:** [May 17, 2021, 9:44am UTC](https://discourse.julialang.org/t/arithmetic-operators-on-bool-type/61192/7 "2021-05-17T09:44:50Z")

</div>

Thanks for this explanation!  
So if I define the math operations I need for `FlipFlop`, does this mean that the operations would be done fast? Will there be an overhead in this case?

---

<div class="post-metadata">

**Author:** ![gustaphe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gustaphe/32/18174_2.png) [@gustaphe](https://discourse.julialang.org/u/gustaphe)\
**Post date:** [May 17, 2021, 11:24am UTC](https://discourse.julialang.org/t/arithmetic-operators-on-bool-type/61192/8 "2021-05-17T11:24:56Z")

</div>

I’m not sure. For large arrays it will be smaller in storage. A speedup would require you to either redefine broadcasting (which I don’t know how to do, or whether it’s possible for this case), or cheat by defining hard-coded broadcasts.

Here is the start of something that I think is an even better idea:

```julia
struct FlipFlop <: Number
    x::Bool
end

FlipFlop(x::Number) = FlipFlop(x > 0)

show(io::IO, x::FlipFlop) = show(io, Int8(x.x ? 1 : -1))

convert(::Type{FlipFlop}, x::FlipFlop) = x
convert(T::Type{<:Number}, x::FlipFlop) = T(x.x ? 1 : -1)

*(x::FlipFlop, y::FlipFlop) = FlipFlop(!xor(x.x, y.x))
^(x::FlipFlop, y::Integer) = FlipFlop(x.x || y % 2 == 0)

struct FlipFlopArray{N} <: AbstractArray{FlipFlop, N}
    x::BitArray{N}
end

FlipFlopArray(x::AbstractArray) = FlipFlopArray(x .> 0)

size(x::FlipFlopArray) = size(x.x)
getindex(x::FlipFlopArray, i) = FlipFlop(getindex(x.x, i))

```

Unfortunately, currently `a.^2` is a `Vector{FlipFlop}` instead of a `FlipFlopArray`, so it will store it in a generic vector, removing the space benefit. I’m pretty sure this can be fixed by following the steps in the [interfaces manual](https://docs.julialang.org/en/v1/manual/interfaces/#man-interfaces-broadcasting), but I haven’t quite gotten it to work yet. If someone is comfortable with this stuff, please let me know.

---

<div class="post-metadata">

**Author:** ![gustaphe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gustaphe/32/18174_2.png) [@gustaphe](https://discourse.julialang.org/u/gustaphe)\
**Post date:** [May 17, 2021, 4:47pm UTC](https://discourse.julialang.org/t/arithmetic-operators-on-bool-type/61192/9 "2021-05-17T16:47:21Z")

</div>

I’m actually making some headway, thanks for the fun challenge, I’m learning a lot.

Could you tell me some operations you would want to be able to do? Right now it successfully multiplies two `FlipFlopArray`s, but fails at raising one to a scalar integer.

Some benchmarking shows that the operation `a .* b` is marginally faster for `FlipFlopArray`s than `Array{Int8}`s first at about 1M elements. And even at 100M elements it’s only a small difference, so there is either something going wrong in the benchmark, or the multiplication of `Int8` arrays is just so optimized it’s hard to keep up.

Looking at allocations though, `FlipFlopArray` definitely does use less memory.

---

<div class="post-metadata">

**Author:** ![roi.holtzman](https://avatars.discourse-cdn.com/v4/letter/r/f05b48/32.png) [@roi.holtzman](https://discourse.julialang.org/u/roi.holtzman)\
**Post date:** [May 17, 2021, 5:49pm UTC](https://discourse.julialang.org/t/arithmetic-operators-on-bool-type/61192/10 "2021-05-17T17:49:27Z")

</div>

I am happy you’re having fun!!  
I think I need only multiplication and addition.  
I am actually interested in modeling an [ising model](https://en.wikipedia.org/wiki/Ising_model). I know that there are some packages written for that, but I am first trying to write something of my own.

---

<div class="post-metadata">

**Author:** ![gustaphe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gustaphe/32/18174_2.png) [@gustaphe](https://discourse.julialang.org/u/gustaphe)\
**Post date:** [May 17, 2021, 6:27pm UTC](https://discourse.julialang.org/t/arithmetic-operators-on-bool-type/61192/11 "2021-05-17T18:27:19Z")

</div>

Note that flipflops aren’t an abelian group, addition of flipflops can give numbers like 0 which are not part of the set.

However, this implementation does a decent job of representing them space-efficiently, though I can’t say anything about speed (except in the case of `sum` and `prod`, which are _massively_ improved by `FlipFlopArray`). It’s a bit rough around the edges, I’m not happy about what happens if you try to `a .+ 3` for instance, but I would guess that stuff could be ironed out with a bit of hard reading.

## Usage examples

```julia
julia> using FlipFlops

julia> a = rand(FlipFlop, 4)
4-element FlipFlopArray{1}:
-1
-1
-1
 1

julia> b = rand(FlipFlop, 4)
4-element FlipFlopArray{1}:
-1
 1
 1
 1

julia> a .* b
4-element FlipFlopArray{1}
 1
-1
-1
 1

julia> a .^ 1
4-element FlipFlopArray{1}:
-1
-1
-1
 1

julia> a .^ 2
4-element FlipFlopArray{1}
 1
 1
 1
 1

julia> prod(a)
-1

julia> sum(a)
-2

```

## Code

```julia
module FlipFlops
export FlipFlop, FlipFlopArray
import Base:
    show,
    size,
    getindex,
    setindex!,
    convert,
    *,
    ^,
    <,
    similar,
    BroadcastStyle,
    rand,
    sum,
    prod

struct FlipFlop <: Number
    x::Bool
end

FlipFlop(x::Number) = FlipFlop(x > 0)

show(io::IO, x::FlipFlop) = show(io, Int8(x.x ? 1 : -1))

convert(::Type{FlipFlop}, x::FlipFlop) = x
convert(T::Type{<:Number}, x::FlipFlop) = T(x.x ? 1 : -1)

*(x::FlipFlop, y::FlipFlop) = FlipFlop(!xor(x.x, y.x))
^(x::FlipFlop, y::Integer) = FlipFlop(x.x || y % 2 == 0)

<(x::FlipFlop, y::Number) = <(convert(Int8, x), y)
<(x::Number, y::FlipFlop) = <(x, convert(Int8, y))

rand(::Type{FlipFlop}) = FlipFlop(rand(Bool))
rand(::Type{FlipFlop}, d::Integer, dims::Integer...) = FlipFlopArray(rand(Bool, d, dims...))

struct FlipFlopArray{N} <: AbstractArray{FlipFlop,N}
    x::BitArray{N}
end

FlipFlopArray(x::AbstractArray) = FlipFlopArray(x .> 0)
FlipFlopArray(x::FlipFlopArray) = x

size(x::FlipFlopArray) = size(x.x)
getindex(x::FlipFlopArray, i) = FlipFlop(getindex(x.x, i))
function setindex!(x::FlipFlopArray, val::Number, inds::Vararg{Int,N}) where {N}
    return setindex!(x.x, val .> 0, inds...)
end

struct FlipFlopStyle{N} <: Broadcast.AbstractArrayStyle{N} end # If FlipFlopArray is broadcasted with anything not explicitly FlipFlop-y, use as an array
BroadcastStyle(::Type{<:FlipFlopArray{N}}) where {N} = FlipFlopStyle{N}()
function BroadcastStyle(::FlipFlopStyle{N}, ::Broadcast.AbstractArrayStyle{0}) where {N}
    return FlipFlopStyle{N}()
end # Broadcasting with a scalar, FlipFlop wins
function BroadcastStyle(::FlipFlopStyle{N}, ::Broadcast.DefaultArrayStyle{0}) where {N}
    return FlipFlopStyle{N}()
end

function similar(bc::Broadcast.Broadcasted{FlipFlopStyle{N}}, ::Type{FlipFlop}) where {N}
    return FlipFlopArray(similar(BitArray, axes(bc)))
end

function similar(bc::Broadcast.Broadcasted{FlipFlopStyle{N}}, ::Type{Bool}) where {N}
    return FlipFlopArray(similar(Bitarray, axes(bc)))
end

sum(x::FlipFlopArray) = 2 * count(x.x) - length(x)
prod(x::FlipFlopArray) = 1 - 2 * ((count(x.x) + length(x)) % 2)

end

```
