Should conversions between different fixed point representations work (example below) ?

Also I’d like to use the library for some DSP algorithm implementation, so doing things like automatic promotion of multiplies to more bits would be really nice.

Thinking about it, I decided that FixedPointNumbers should not do that, I like the fact that it maintains consistency in the results.

So what I need to do is -

- create a value of 15 bits of precision
- extend to 31 bits
- perform a multiplication
- truncate back to 15 bits

However it looks like the only way to perform that sequence to do intermediate conversions to float and then back.

am I missing something ?

```
julia> using FixedPointNumbers
julia> t1=Fixed{Int32,15}
FixedPointNumbers.Fixed{Int32,15}
julia> t2=Fixed{Int16,15}
FixedPointNumbers.Fixed{Int16,15}
julia> a=t1(0.25)
0.25Q16f15
julia> b=convert(t2, a)
ERROR: MethodError: Cannot `convert` an object of type FixedPointNumbers.Fixed{Int32,15} to an object of type FixedPointNumbers.Fixed{Int16,15}
This may have arisen from a call to the constructor FixedPointNumbers.Fixed{Int16,15}(...),
since type constructors fall back to convert methods.
julia>
```

In practice, the `Normed`

numbers have gotten a lot more practical testing (they are used by the Colors/Images suite), and so we seem to have the following:

```
julia> using FixedPointNumbers
julia> x = rand(N2f6) # Normed numbers example
1.1N2f6
julia> convert(N6f10, x)
1.0948N6f10
julia> x = rand(Q2f5) # Fixed numbers example
1.66Q2f5
julia> convert(Q6f9, x)
ERROR: MethodError: Cannot `convert` an object of type FixedPointNumbers.Fixed{Int8,5} to an object of type FixedPointNumbers.Fixed{Int16,9}
This may have arisen from a call to the constructor FixedPointNumbers.Fixed{Int16,9}(...),
since type constructors fall back to convert methods.
```

Any chance you could tweak the implementation for `Normed`

to build one for `Fixed`

? And then contribute it?

yes that is something i could do. i’ve only done a PR once, so it will take me a bit to get things figured out again. I’ve already looked at the code and it seems to be straightforward.

However in thinking about this what I really want to be able to do, and this is a generic Julia question is something like

a= Int8(127)

b= Int8(127)

a*b => automatic promotion to Int16

Is there a way through macro-fu or some other method for me to set up a system where I can automatically do that ?

I’m thinking that it simply requires me to generate an operator/method that would capture the types and do so.

```
function op1(a::Int8, b::Int8) :: Int16
a1 = Int16(a)
b1 = Int16(b)
return a1*b1
end
```

Should be that easy, right ? well I know it is, I tried it. The problem is that if I try to use the standard multiplication operator, i.e. ‘*’, then I figure it will almost certainly clash with the built in assignment which is to maintain the same type. Interestingly that would not be a problem if the method was actually matched using the return type- which I don’t think is true at this time.

Thanks

One problem with making this the default strategy: `Int8^2`

→ `Int16`

, `Int16^2`

→ `Int32`

, and `Int32^2`

→ `Int64`

. It becomes almost impossible to predict the output type from a computation: go from 2 to 3 multiplies and suddenly the output type changes. Of course sometimes you can compute the same thing in two different ways (e.g., `x^4`

can be computed in either 2 multiplies or 3), and it would be crazy if the output type depended on how you chose to implement the computation. A lesson is that If you’re going to widen, you need to widen “all the way” immediately.

We used to widen, e.g., `UInt8`

→ `UInt`

, and interestingly it was not very popular. I think the lesson is that if you *aren’t* using one of the “default” types (`Int`

, `UInt`

, and `Float64`

), you probably have a reason and therefore want some manual control. Consequently the dominant behavior (with a few exceptions) is that any widening has to be implemented manually.

2 Likes

I agree. I didn’t mean to imply it should be default behavior . I was just describing what I was trying to do and figuring out a way to make it “look nice”.

I like the fact that the type is precisely conserved and that any modification must be done with an explicit operation.