# Typeof(n\*n) in factorial

**URL:** <https://discourse.julialang.org/t/typeof-n-n-in-factorial/41700>\
**Category:** Internals & Design\
**Created:** [June 18, 2020, 9:45pm UTC](https://discourse.julialang.org/t/typeof-n-n-in-factorial/41700 "2020-06-18T21:45:45Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![binarygcd](https://avatars.discourse-cdn.com/v4/letter/b/ec9cab/32.png) [@binarygcd](https://discourse.julialang.org/u/binarygcd)\
**Post date:** [June 18, 2020, 9:45pm UTC](https://discourse.julialang.org/t/typeof-n-n-in-factorial/41700/1 "2020-06-18T21:45:45Z")

</div>

The implementation of factorial in Base is

```julia
function factorial(n::Integer)
    n < 0 && throw(DomainError(n, "`n` must be nonnegative."))
    f::typeof(n*n) = 1
    for i::typeof(n*n) = 2:n
        f *= i
    end
    return f
end

```

Why typeof(n\*n) instead of typeof(n)? This maybe a dumb question but I really don’t get it.

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [June 18, 2020, 9:47pm UTC](https://discourse.julialang.org/t/typeof-n-n-in-factorial/41700/2 "2020-06-18T21:47:22Z")

</div>

There are numbers who’s type is not closed under multiplication. This makes sure you get something of the right type. In practice, this will almost always just be `typof(n)` though.

---

<div class="post-metadata">

**Author:** ![binarygcd](https://avatars.discourse-cdn.com/v4/letter/b/ec9cab/32.png) [@binarygcd](https://discourse.julialang.org/u/binarygcd)\
**Post date:** [June 18, 2020, 9:48pm UTC](https://discourse.julialang.org/t/typeof-n-n-in-factorial/41700/3 "2020-06-18T21:48:50Z")

</div>

Can you please elaborate a little more? Example?

---

<div class="post-metadata">

**Author:** ![karlroyen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/karlroyen/32/9301_2.png) [@karlroyen](https://discourse.julialang.org/u/karlroyen)\
**Post date:** [June 19, 2020, 6:55am UTC](https://discourse.julialang.org/t/typeof-n-n-in-factorial/41700/4 "2020-06-19T06:55:57Z")

</div>

One example would be values with physical units, as provided by the Unitful.jl package.

The area of a square has not the same type as the length of its sides:

```julia
julia> using Unitful

julia> length = 1u"m"
1 m

julia> typeof(length)
Quantity{Int64,𝐋,Unitful.FreeUnits{(m,),𝐋,nothing}}

julia> area = length*length
1 m^2

julia> typeof(area)
Quantity{Int64,𝐋^2,Unitful.FreeUnits{(m^2,),𝐋^2,nothing}}

julia> typeof(area) == typeof(length)
false

```

edit: Hmm, maybe scratch that…since it is not applicable to the factorial method.

---

<div class="post-metadata">

**Author:** ![binarygcd](https://avatars.discourse-cdn.com/v4/letter/b/ec9cab/32.png) [@binarygcd](https://discourse.julialang.org/u/binarygcd)\
**Post date:** [June 19, 2020, 7:00am UTC](https://discourse.julialang.org/t/typeof-n-n-in-factorial/41700/5 "2020-06-19T07:00:26Z")

</div>

It’s fine. It still gave the example I was looking for.

---

<div class="post-metadata">

**Author:** ![karlroyen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/karlroyen/32/9301_2.png) [@karlroyen](https://discourse.julialang.org/u/karlroyen)\
**Post date:** [June 19, 2020, 7:01am UTC](https://discourse.julialang.org/t/typeof-n-n-in-factorial/41700/6 "2020-06-19T07:01:58Z")

</div>

Well, but now I don’t understand why it is necessary in the factorial case 🙂

---

<div class="post-metadata">

**Author:** ![binarygcd](https://avatars.discourse-cdn.com/v4/letter/b/ec9cab/32.png) [@binarygcd](https://discourse.julialang.org/u/binarygcd)\
**Post date:** [June 19, 2020, 7:03am UTC](https://discourse.julialang.org/t/typeof-n-n-in-factorial/41700/7 "2020-06-19T07:03:35Z")

</div>

I really hope someone will answer.

---

<div class="post-metadata">

**Author:** ![karlroyen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/karlroyen/32/9301_2.png) [@karlroyen](https://discourse.julialang.org/u/karlroyen)\
**Post date:** [June 19, 2020, 7:34am UTC](https://discourse.julialang.org/t/typeof-n-n-in-factorial/41700/8 "2020-06-19T07:34:36Z")

</div>

If there is some strange implementation of Integer for which `n*n` is not closed under multiplication, why should `(n*n)*n` be? And why should `1` be of the same type as `n*n`?

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [June 19, 2020, 8:43am UTC](https://discourse.julialang.org/t/typeof-n-n-in-factorial/41700/9 "2020-06-19T08:43:56Z")

</div>

Working with result types is actually one of the most irksome parts of Julia. Even restricting to `<:Number`, the interfaces are not formalized. So while it may be strange, making a `<:Number` type that is not closed under multiplication does not formally violate any contract.

While in this particular case, `typeof(n)` would be fine.

That said, I am curious where you got that code from, currently in Julia `factorial` uses a lookup table and looks very different.

---

<div class="post-metadata">

**Author:** ![Palli](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/palli/32/3380_2.png) [@Palli](https://discourse.julialang.org/u/Palli)\
**Post date:** [June 19, 2020, 9:26am UTC](https://discourse.julialang.org/t/typeof-n-n-in-factorial/41700/10 "2020-06-19T09:26:38Z")

</div>

If I recall that’s just the fallback, and probably used by BigInt, but Int64 etc. has a lookup.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [June 19, 2020, 9:36am UTC](https://discourse.julialang.org/t/typeof-n-n-in-factorial/41700/11 "2020-06-19T09:36:25Z")

</div>

I see that it’s actually in `intfuncs.jl`, but I am not sure what would call this.

`Int` & friends use lookup tables, `BigInt` [falls back to using `MPZ`](https://github.com/JuliaLang/julia/blob/d6d5208d66be637543232bec4b0c79b2811ea1c6/base/gmp.jl#L641).

---

<div class="post-metadata">

**Author:** ![Per](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/per/32/10387_2.png) [@Per](https://discourse.julialang.org/u/Per)\
**Post date:** [June 19, 2020, 9:56am UTC](https://discourse.julialang.org/t/typeof-n-n-in-factorial/41700/12 "2020-06-19T09:56:30Z")

</div>

That function gets called for user-defined types that are `<:Integer`. For example:

```julia
using StaticNumbers
factorial(static(20))

```

---

<div class="post-metadata">

**Author:** ![binarygcd](https://avatars.discourse-cdn.com/v4/letter/b/ec9cab/32.png) [@binarygcd](https://discourse.julialang.org/u/binarygcd)\
**Post date:** [June 19, 2020, 9:59am UTC](https://discourse.julialang.org/t/typeof-n-n-in-factorial/41700/13 "2020-06-19T09:59:31Z")

</div>

Is there a particular type(?) that benefits from typeof(n\*n) instead of typeof(n)?

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [June 19, 2020, 10:32am UTC](https://discourse.julialang.org/t/typeof-n-n-in-factorial/41700/14 "2020-06-19T10:32:58Z")

</div>

I think the point is that you cannot know for _certain_ that `n*n` will always have the same type as `n`, for example in types created by users. Therefore this is an extra safeguard. You want to make _sure_ that things will work out, instead of relying on that it “seems to work in most cases.”

---

<div class="post-metadata">

**Author:** ![simeonschaub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simeonschaub/32/216566_2.png) [@simeonschaub](https://discourse.julialang.org/u/simeonschaub)\
**Post date:** [June 19, 2020, 11:02am UTC](https://discourse.julialang.org/t/typeof-n-n-in-factorial/41700/15 "2020-06-19T11:02:26Z")

</div>

Seems like this was introduced by @jeff.bezanson in [https://github.com/JuliaLang/julia/commit/b6687823d0e4a61f44890325e55aded0d5e07f29](https://github.com/JuliaLang/julia/commit/b6687823d0e4a61f44890325e55aded0d5e07f29) all the way back in 2014. It does seem a bit questionable, whether the `typeof(n*n)` is sensible here. Maybe

```julia
f = one(n)
for i in oftype(n, 2):n
    f *= i
end

```

might be a better generic implementation? It won’t be type stable if `n` is not closed under multiplication, but assuming `n` and `1` can always be converted to `typeof(n*n)` is probably worse, as seen in the `Unitful` example. It is also not guaranteed that `(n*n) * n` can be converted to `typeof(n*n)`, so `typeof(n*n)` seems rather arbitrary as output type.

---

<div class="post-metadata">

**Author:** ![simeonschaub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simeonschaub/32/216566_2.png) [@simeonschaub](https://discourse.julialang.org/u/simeonschaub)\
**Post date:** [June 19, 2020, 11:13am UTC](https://discourse.julialang.org/t/typeof-n-n-in-factorial/41700/16 "2020-06-19T11:13:24Z")

</div>

Thinking about it, `oftype(n, 2)` might need to be `oneunit(n) + oneunit(n)` because otherwise, that fails for `static(true)` from `StaticNumbers`.

---

<div class="post-metadata">

**Author:** ![Per](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/per/32/10387_2.png) [@Per](https://discourse.julialang.org/u/Per)\
**Post date:** [June 19, 2020, 11:25am UTC](https://discourse.julialang.org/t/typeof-n-n-in-factorial/41700/17 "2020-06-19T11:25:02Z")

</div>

It would also fail for plain old `true` from Base…

---

<div class="post-metadata">

**Author:** ![simeonschaub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simeonschaub/32/216566_2.png) [@simeonschaub](https://discourse.julialang.org/u/simeonschaub)\
**Post date:** [June 19, 2020, 11:27am UTC](https://discourse.julialang.org/t/typeof-n-n-in-factorial/41700/18 "2020-06-19T11:27:43Z")

</div>

I thought that had a custom implementation, but apparently not.

---

<div class="post-metadata">

**Author:** ![Per](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/per/32/10387_2.png) [@Per](https://discourse.julialang.org/u/Per)\
**Post date:** [June 19, 2020, 11:31am UTC](https://discourse.julialang.org/t/typeof-n-n-in-factorial/41700/19 "2020-06-19T11:31:40Z")

</div>

It doesn’t seem to need one.

```julia
julia> @code_llvm factorial(true)

; @ intfuncs.jl:889 within `factorial'
define i8 @julia_factorial_19411(i8) {
top:
; @ intfuncs.jl:895 within `factorial'
  ret i8 1
}

```

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [June 19, 2020, 11:52am UTC](https://discourse.julialang.org/t/typeof-n-n-in-factorial/41700/20 "2020-06-19T11:52:45Z")

</div>

> [@DNF](#):
>
> you cannot know for _certain_ that `n*n` will always have the same type as `n` , for example in types created by users. Therefore this is an extra safeguard.

But if that is violated, then you cannot know if `n * n * n` will be the same type, etc, so I am not sure that is worth much.

Frankly, I don’t understand the motivation for this — if anything, I would just do some widening, eg `Int8`, `Int16`, etc to `Int`.

[Next page](https://discourse.julialang.org/t/typeof-n-n-in-factorial/41700.md?page=2)
