I do not understand exactly how A, n, p are chosen.

If I understand right:

– “The scale of the outcome (i.e., the amplitude): 2^A”

The A is chosen A=12, because the sine value return is Q12.

– “The scale on the inside the parentheses: 2^p. This is necessary to keep the multiplications from overflowing.”

The p is chosen p=15, because the final sine function isin_S3 is on 32bit and has the argument on 32bit and when e multiply 2 operands, in order to avoid overflow, then each operand must be 15 binary digits after the decimal point plus the sign.

– “The angle-scale: 2^n. This is basically the value of ½π in the fixed-point system. Using x for the angle, you have z = x/2^n.”

The n is chosen n=13, because if full circle (0…2PI) uses 2^15 angles for resolution, then for 1 quarter of circle (0..PI/2) we need only (2^15)/4=(2^15)/(2^2)=2^13, so n=13.

Is my interpretation right/proper? Please correct me if I am wrong.

I would like to port and test these calculations with a 16bit PIC24 microcontroller.

]]>Parentheses? Do you mean at line 17 or line 28? Also, I’m still new to the curve fitting thing, so I haven’t “got” what makes a good target value to plug into the target method. Is it any value that intersects the x axis on the normal sine func? Right now I’m not using the optimized version as I’m still trying to wrap my head around the basics.

RMS is probably my end method for figuring out the optimized constants, but I have no experience with Goalseek or Solver, I will check those out.

As far as precision goes, my target from the beginning was a complete set of elementary trig functions that use Q16 nums inside of int64_t for all inputs and outputs. 48 bits above the radix should be more than enough scratchspace for the intermediary calcs, and I dislike factoring out the shifts for what should be a separate func/concern. Do you used Q24 for the extra precision on the bottom end? Additionally, both Gcc and Clang should be able to do the final bitshift optimization/algebraic reduction during compile if I set MULT() and DIVD() to allow for inlining.

In fact, here is a paste of my MULT() and DIVD() func for Q16 numbers stored in 64 bit registers: https://pastebin.com/2mC2GxJx

]]> I’ve done a quick test with my own implementation of sine5 (https://pastebin.com/0x70eeQa). Notice that I do most of the math in Q24, because why not.

At α = π/4 I get 0xB518. The true value should be 0xB504, which makes my S5 approximation off by roughly 0.05%. This is about the accuracy I expected from Fig 5.

For true Q16 precision, it’s necessary to do the intermediary calculations at higher precision. The range of calculations is around [-4.0, +4.0] I think, so you should have bits to spare.

As for the constraints for D: they can be whatever you want :D No really, you can choose the constraints yourself. Suggestions are:

- sin(π/4) = 1/&sqrt;2 (extra intermediary point)
- sin(π/6) = ½ (extra intermediary point)
- ∫ sin dx (0, π/2) = 2/π (area under curve; minimizes average error)
- Minimize the root-mean square. For this you’ll need something like Excel’s GoalSeek or Solver.

I discuss some of these options in section 3.3. The point is that you can decide on what the characteristics of the curve. I kinda like an extra intermediate point or average error, but for true minimal error, RMS is probably the best option. However, you can’t solve for that analytically.

]]>Here is a pastebin of the corrected code: https://pastebin.com/TXF9V2GK

]]>I also have a func for doing square roots with fixed point numbers that is fairly interesting, I would like to learn about using the sort of analytical graphs you have here to evaluate it’s output over a range, do you have a link to a good guide?

]]>I can also recommend this playlist: https://www.youtube.com/playlist?list=PLZHQObOWTQDPD3MizzM2xVFitgF8hE_ab

The stuff I’m talking about here are discussed in part 4, if I recall correctly.

]]>