assembler assigning values too early

Hi Guys,
im mucking aorund with some code trying to work out the speed of some math operations.

Note, im using a Due board

see code below, i think the assembler is assigning micros values to Start/Finish in some funny order, rather than in the order written.
Any ideas.

#include <arduino.h>
#include "math.h"

#define Serial SerialUSB

int count = 0;
unsigned long Start = 0;
unsigned long Finish = 0;
//unsigned long result = 0;
#define pi (3.14159265358979) // pi 16 chars
#define _deg_convert (0.01745329251994) // constant for pi/180

// void test_calc_time();

void setup() {
  Serial.begin(115200);
  while (!Serial) {
    ;
  }
}

void loop() {
  
  test_calc_time();
  delay(60000);
  }


 void test_calc_time() {

  float centre_abs_x = 50;
  float centre_abs_y = 50;
  float theta = 360.0;
  float radius = 40.0;
  float hypot;
  float old_x_rel = 0;
  float old_y_rel = 40;
  float new_x_rel;
  float new_y_rel;
  float new_x_abs;
  float new_y_abs;
  
  Start = micros();
  
  hypot = 2 * (sin(theta * 0.5 * _deg_convert) * radius);
  new_x_rel = old_x_rel - (cos(theta * 0.5 * _deg_convert) * hypot);
  new_y_rel = old_y_rel - (sin(theta * 0.5 * _deg_convert) * hypot);
  new_x_abs = (centre_abs_x + new_x_rel);
  new_y_abs = (centre_abs_y + new_y_rel);

  Finish = micros();

  Serial.print(Finish - Start); Serial.println(" microseconds to complete calcs below");
  Serial.print("Start time = "); Serial.println(Start);
  Serial.print("Finish time = "); Serial.println(Finish);

  Serial.print("new_x_rel = "); Serial.println(new_x_rel, 10);
  Serial.print("new_y_rel = "); Serial.println(new_y_rel, 10);
  Serial.print("new_x_abs = "); Serial.println(new_x_abs, 10);
  Serial.print("new_y_abs = "); Serial.println(new_y_abs, 10);
  Serial.println();

  }
  hypot = 2 * (sin(theta * 0.5 deg) * radius);[color=#222222][/color]
  new_x_rel = old_x_rel + (cos(theta * 0.5 deg) * hypot);[color=#222222][/color]
  new_y_rel = old_y_rel+(sin(theta * 0.5 deg) * hypot);[color=#222222][/color]
  new_x_abs = centre_abs_x - new_x_rel;[color=#222222][/color]
  new_y_abs = centre_abs_y - new_y_rel;[color=#222222][/color]
   [color=#222222][/color]
  [color=#222222][/color]
[color=#222222][/color]
//    float a = sin(0.005 deg);   // deg is defined as 0.01745329251994[color=#222222][/color]
//    float b = sin(30 deg);[color=#222222][/color]
//    float c = sin(90 deg);[color=#222222][/color]
//    float d = sin(270 deg);[color=#222222][/color]
//    float e = sin(360 deg);[color=#222222][/color]
    [color=#222222][/color]
//  for(float d=0; d<=2*pi; d+=0.005) [color=#222222][/color]
//  {[color=#222222][/color]
//    x=rx+sin(d)*r;[color=#222222][/color]
//    y=ry+sin(d+(pi/2))*r;[color=#222222][/color]
//  }[color=#222222][/color]
   [color=#222222][/color]
  Finish = micros();[color=#222222][/color]
[color=#222222][/color]
  Serial.println(Finish - Start);[color=#222222][/color]
  Serial.println(Start);[color=#222222][/color]
  Serial.println(Finish);[color=#222222][/color]
[color=#222222][/color]
  Serial.print("new_x_rel = "); Serial.println(new_x_rel, 10);[color=#222222][/color]
  Serial.print("new_y_rel = "); Serial.println(new_y_rel, 10);[color=#222222][/color]
  Serial.print("new_x_abs = "); Serial.println(new_x_abs, 10);[color=#222222][/color]
  Serial.print("new_y_abs = "); Serial.println(new_y_abs, 10);[color=#222222][/color]

this code belongs to where?

you should not code like this, this should be in some function.

Hi sarouje
i updated the code, thats not how i code im just trying to estimate the calculation time.

im still getting a result of only 1-2 microseconds. dont get me wrong ill be supper happy if its right, but it sounds too quick for me. can anyone confirm the times for me

Cheers

The way you are using Start and Finish is correct. However for effective timing I would measure the time for, perhaps, 1000 or 10000 iterations of the code.

...R

Robin, given that he times only the math piece without serial or other things involved generating interrupts, that seem appropriate to me as the binary instructions will be the same.

I'll have a look later but the compiler is smart and can see that everything is self contained and can't vary so the preprocessor might calculate everything for you at compile time which is the right thing to do.

I'd get the values as parameters to your function and pass numbers built using the random function (and a seed from reading floating A0 ) then the compiler can't pre compute

65 microseconds, dammit. here i was thinking i ws writing super fast code :frowning:

thanks robin,
i tried that first and gave me the same time, which lead me to believe the compiler was doing something.

nice tip J,
thats actually a really good way of testing numbers instead of typing in new variable values and uploading each time.

i got the random working, whether its etup completely correctly ??, good enough that im sure the compiler isnt playing with the code.

#include <arduino.h>
#include "math.h"

#define Serial SerialUSB

int count = 0;
unsigned long Start = 0;
unsigned long Finish = 0;
//unsigned long result = 0;
#define pi (3.14159265358979) // pi 16 chars
#define _deg_convert (0.01745329251994) // constant for pi/180

long randNumber;

void setup() {
  randomSeed(analogRead(A0));
  Serial.begin(115200);
  while (!Serial) {
    ;
  }
}

void loop() {
  
  next_XY_pos_circle();
  delay(5000);
  randNumber = constrain(random(A0), 0, 360);
  }


 void next_XY_pos_circle() {

  float centre_abs_x = 50;
  float centre_abs_y = 50;
  float theta = randNumber;   // 360
  float radius = 40.0;
  float hypot;
  float old_x_rel = 0;
  float old_y_rel = 40;
  float new_x_rel;
  float new_y_rel;
  float new_x_abs;
  float new_y_abs;
  
  Start = micros();
  
  hypot = 2 * (sin(theta * 0.5 * _deg_convert) * radius);
  new_x_rel = old_x_rel - (cos(theta * 0.5 * _deg_convert) * hypot);
  new_y_rel = old_y_rel - (sin(theta * 0.5 * _deg_convert) * hypot);
  new_x_abs = (centre_abs_x + new_x_rel);
  new_y_abs = (centre_abs_y + new_y_rel);

  Finish = micros();

  Serial.print(Finish - Start); Serial.println(" microseconds to complete calcs below");
  Serial.print("Start time = "); Serial.println(Start);
  Serial.print("Finish time = "); Serial.println(Finish);
  
  Serial.print("theta = "); Serial.println(theta);
  
  Serial.print("new_x_rel = "); Serial.println(new_x_rel, 10);
  Serial.print("new_y_rel = "); Serial.println(new_y_rel, 10);
  Serial.print("new_x_abs = "); Serial.println(new_x_abs, 10);
  Serial.print("new_y_abs = "); Serial.println(new_y_abs, 10);
  Serial.println();

  }

well don't complain. I ran your last code on my UNO and got this:

212 microseconds to complete calcs below
Start time = 260
Finish time = 472
theta = 0.00
new_x_rel = 0.0000000000
new_y_rel = 40.0000000000
new_x_abs = 50.0000000000
new_y_abs = 90.0000000000

while testing your first code without the random thingy then I got

4 microseconds to complete calcs below
Start time = 48
Finish time = 52
new_x_rel = -0.0000069938
new_y_rel = 40.0000000000
new_x_abs = 49.9999923706
new_y_abs = 90.0000000000

Too good to be true if computation was done at run time :slight_smile:

and if you are curious, that's the disassembly of the code for your first version for the calculation

void test_calc_time() {
   0:	0f 93       	push	r16
   2:	1f 93       	push	r17
  float new_x_rel;
  float new_y_rel;
  float new_x_abs;
  float new_y_abs;
  
  Start = micros();
   4:	0e 94 00 00 	call	0	; 0x0 <_Z14test_calc_timev>
   8:	60 93 00 00 	sts	0x0000, r22
   c:	70 93 00 00 	sts	0x0000, r23
  10:	80 93 00 00 	sts	0x0000, r24
  14:	90 93 00 00 	sts	0x0000, r25
[color=red]  new_x_rel = old_x_rel - (cos(theta * 0.5 * _deg_convert) * hypot);
  new_y_rel = old_y_rel - (sin(theta * 0.5 * _deg_convert) * hypot);
  new_x_abs = (centre_abs_x + new_x_rel);
  new_y_abs = (centre_abs_y + new_y_rel);

[/color]  Finish = micros();
  18:	0e 94 00 00 	call	0	; 0x0 <_Z14test_calc_timev>
  1c:	60 93 00 00 	sts	0x0000, r22
  20:	70 93 00 00 	sts	0x0000, r23
  24:	80 93 00 00 	sts	0x0000, r24
  28:	90 93 00 00 	sts	0x0000, r25

You see that in red there is no math done at all :slight_smile:

while for the second version you get all this

void next_XY_pos_circle() {
   0:	4f 92       	push	r4
   2:	5f 92       	push	r5
   4:	6f 92       	push	r6
   6:	7f 92       	push	r7
   8:	8f 92       	push	r8
   a:	9f 92       	push	r9
   c:	af 92       	push	r10
   e:	bf 92       	push	r11
  10:	cf 92       	push	r12
  12:	df 92       	push	r13
  14:	ef 92       	push	r14
  16:	ff 92       	push	r15
  18:	cf 93       	push	r28
  1a:	df 93       	push	r29
  1c:	00 d0       	rcall	.+0      	; 0x1e <_Z18next_XY_pos_circlev+0x1e>
  1e:	00 d0       	rcall	.+0      	; 0x20 <_Z18next_XY_pos_circlev+0x20>
  20:	cd b7       	in	r28, 0x3d	; 61
  22:	de b7       	in	r29, 0x3e	; 62

[color=red]  float centre_abs_x = 50;
  float centre_abs_y = 50;
[/color][color=blue]  float theta = randNumber;   // 360
  24:	60 91 00 00 	lds	r22, 0x0000
  28:	70 91 00 00 	lds	r23, 0x0000
  2c:	80 91 00 00 	lds	r24, 0x0000
  30:	90 91 00 00 	lds	r25, 0x0000
  34:	0e 94 00 00 	call	0	; 0x0 <_Z18next_XY_pos_circlev>
  38:	69 83       	std	Y+1, r22	; 0x01
  3a:	7a 83       	std	Y+2, r23	; 0x02
  3c:	8b 83       	std	Y+3, r24	; 0x03
  3e:	9c 83       	std	Y+4, r25	; 0x04[/color]
  float new_x_rel;
  float new_y_rel;
  float new_x_abs;
  float new_y_abs;

  Start = micros();
  40:	0e 94 00 00 	call	0	; 0x0 <_Z18next_XY_pos_circlev>
  44:	60 93 00 00 	sts	0x0000, r22
  48:	70 93 00 00 	sts	0x0000, r23
  4c:	80 93 00 00 	sts	0x0000, r24
  50:	90 93 00 00 	sts	0x0000, r25

  [color=blue]hypot = 2 * (sin(theta * 0.5 * _deg_convert) * radius);
  54:	20 e0       	ldi	r18, 0x00	; 0
  56:	30 e0       	ldi	r19, 0x00	; 0
  58:	40 e0       	ldi	r20, 0x00	; 0
  5a:	5f e3       	ldi	r21, 0x3F	; 63
  5c:	69 81       	ldd	r22, Y+1	; 0x01
  5e:	7a 81       	ldd	r23, Y+2	; 0x02
  60:	8b 81       	ldd	r24, Y+3	; 0x03
  62:	9c 81       	ldd	r25, Y+4	; 0x04
  64:	0e 94 00 00 	call	0	; 0x0 <_Z18next_XY_pos_circlev>
  68:	25 e3       	ldi	r18, 0x35	; 53
  6a:	3a ef       	ldi	r19, 0xFA	; 250
  6c:	4e e8       	ldi	r20, 0x8E	; 142
  6e:	5c e3       	ldi	r21, 0x3C	; 60
  70:	0e 94 00 00 	call	0	; 0x0 <_Z18next_XY_pos_circlev>
  74:	6b 01       	movw	r12, r22
  76:	7c 01       	movw	r14, r24
  78:	0e 94 00 00 	call	0	; 0x0 <_Z18next_XY_pos_circlev>
  7c:	4b 01       	movw	r8, r22
  7e:	5c 01       	movw	r10, r24
  80:	20 e0       	ldi	r18, 0x00	; 0
  82:	30 e0       	ldi	r19, 0x00	; 0
  84:	40 e2       	ldi	r20, 0x20	; 32
  86:	52 e4       	ldi	r21, 0x42	; 66
  88:	0e 94 00 00 	call	0	; 0x0 <_Z18next_XY_pos_circlev>
  8c:	9b 01       	movw	r18, r22
  8e:	ac 01       	movw	r20, r24
  90:	0e 94 00 00 	call	0	; 0x0 <_Z18next_XY_pos_circlev>
  94:	2b 01       	movw	r4, r22
  96:	3c 01       	movw	r6, r24
  new_x_rel = old_x_rel - (cos(theta * 0.5 * _deg_convert) * hypot);
  98:	c7 01       	movw	r24, r14
  9a:	b6 01       	movw	r22, r12
  9c:	0e 94 00 00 	call	0	; 0x0 <_Z18next_XY_pos_circlev>
  a0:	a3 01       	movw	r20, r6
  a2:	92 01       	movw	r18, r4
  a4:	0e 94 00 00 	call	0	; 0x0 <_Z18next_XY_pos_circlev>
  a8:	9b 01       	movw	r18, r22
  aa:	ac 01       	movw	r20, r24
  ac:	60 e0       	ldi	r22, 0x00	; 0
  ae:	70 e0       	ldi	r23, 0x00	; 0
  b0:	cb 01       	movw	r24, r22
  b2:	0e 94 00 00 	call	0	; 0x0 <_Z18next_XY_pos_circlev>
  b6:	6b 01       	movw	r12, r22
  b8:	7c 01       	movw	r14, r24
  new_y_rel = old_y_rel - (sin(theta * 0.5 * _deg_convert) * hypot);
  ba:	a3 01       	movw	r20, r6
  bc:	92 01       	movw	r18, r4
  be:	c5 01       	movw	r24, r10
  c0:	b4 01       	movw	r22, r8
  c2:	0e 94 00 00 	call	0	; 0x0 <_Z18next_XY_pos_circlev>
  c6:	9b 01       	movw	r18, r22
  c8:	ac 01       	movw	r20, r24
  ca:	60 e0       	ldi	r22, 0x00	; 0
  cc:	70 e0       	ldi	r23, 0x00	; 0
  ce:	80 e2       	ldi	r24, 0x20	; 32
  d0:	92 e4       	ldi	r25, 0x42	; 66
  d2:	0e 94 00 00 	call	0	; 0x0 <_Z18next_XY_pos_circlev>
  d6:	4b 01       	movw	r8, r22
  d8:	5c 01       	movw	r10, r24
  new_x_abs = (centre_abs_x + new_x_rel);
  new_y_abs = (centre_abs_y + new_y_rel);
[/color]
  Finish = micros();
  da:	0e 94 00 00 	call	0	; 0x0 <_Z18next_XY_pos_circlev>
  de:	60 93 00 00 	sts	0x0000, r22
  e2:	70 93 00 00 	sts	0x0000, r23
  e6:	80 93 00 00 	sts	0x0000, r24
  ea:	90 93 00 00 	sts	0x0000, r25

in red you have still static pre compiler allocation but you do the math in blue, which is where the bulk of the time goes.

When I run your code (with a minor modification) I obtain 142 ns to calculate :

//#include <arduino.h>  // included in Arduino IDE
//#include "math.h"     // included in Arduino IDE

//#define Serial SerialUSB

int count = 0;
uint32_t Start = 0,Finish = 0;

//unsigned long result = 0;
//#define pi (3.14159265358979) // pi 16 chars
#define _deg_convert (0.01745329251994) // constant for pi/180

// void test_calc_time();

void setup() {
  Serial.begin(250000);
  
}

void loop() {
  
  test_calc_time();
  delay(10000);
  }


 void test_calc_time() {
float temp;
  float centre_abs_x = 50;
  float centre_abs_y = 50;
  float theta = 360.0;
  float radius = 40.0;
  float hypot;
  float old_x_rel = 0;
  float old_y_rel = 40;
  float new_x_rel;
  float new_y_rel;
  float new_x_abs;
  float new_y_abs;
  
  
  Start = SysTick->VAL;  // Systick->Val counts down from 84000 to 1 in 1 ms, then reloads with 84000
 
  hypot = 2 * (sin(theta * 0.5 * _deg_convert) * radius);
  new_x_rel = old_x_rel - (cos(theta * 0.5 * _deg_convert) * hypot);
  new_y_rel = old_y_rel - (sin(theta * 0.5 * _deg_convert) * hypot);
  new_x_abs = (centre_abs_x + new_x_rel);
  new_y_abs = (centre_abs_y + new_y_rel);
 
  Finish =  SysTick->VAL;  
  
  Serial.print(" Time to complete calcs below = ");
  temp = Start - Finish;
  if (temp <0) temp += SystemCoreClock/1000;
  temp = (float) ((temp*1000)/84);
  Serial.print(temp); Serial.println(" ns");
  

 /*Serial.print(Start - Finish); Serial.println(" microseconds to complete calcs below");
  
  Serial.print("Start time = "); Serial.println(Start);
  Serial.print("Finish time = "); Serial.println(Finish);

  Serial.print("new_x_rel = "); Serial.println(new_x_rel, 10);
  Serial.print("new_y_rel = "); Serial.println(new_y_rel, 10);
  Serial.print("new_x_abs = "); Serial.println(new_x_abs, 10);
  Serial.print("new_y_abs = "); Serial.println(new_y_abs, 10);
  Serial.println();
*/
  }

the red is fine it should be static,
is the first column clock tiks???
how do i make these magic numbers, i am guessing i could convert to ASSEMBLY? in VS7.

poor old UNO getting a bashing, thats why i went for the due, because my coding isnt up to speed and i have only 650us to do all calcs (ultra simple cnc shape machine - Project Guidance - Arduino Forum), therefore hopefully due makes up for what i cant do yet.

cheers for testing it out for me

hey ard,
i ran your code and got the same numbers, which is kind of what i was getting at the start. 1us to do the function. But as J was saying (i think), in the ccase of your code you blanked out the serial prints so the assembler didnt see any need to do any calcs at all. and in the case of my code the variables could never change, so same case, no need to calculate - just go to function and return.

put the prints back in and were back to 65us or 66000ns.

//#include <arduino.h>  // included in Arduino IDE
//#include "math.h"     // included in Arduino IDE

#define Serial SerialUSB
long randNumber;
int count = 0;
uint32_t Start = 0,Finish = 0;

//unsigned long result = 0;
//#define pi (3.14159265358979) // pi 16 chars
#define _deg_convert (0.01745329251994) // constant for pi/180

// void test_calc_time();

void setup() {
  randomSeed(analogRead(A0));
  Serial.begin(115200);
 
}

void loop() {
 
  test_calc_time();
  delay(5000);
  randNumber = constrain(random(A0), 0, 360);
  }


 void test_calc_time() {
  float temp;
  float centre_abs_x = 50;
  float centre_abs_y = 50;
  float theta = randNumber;
  float radius = 40.0;
  float hypot;
  float old_x_rel = 0;
  float old_y_rel = 40;
  float new_x_rel;
  float new_y_rel;
  float new_x_abs;
  float new_y_abs;
 
 
  Start = SysTick->VAL;  // Systick->Val counts down from 84000 to 1 in 1 ms, then reloads with 84000
 
  hypot = 2 * (sin(theta * 0.5 * _deg_convert) * radius);
  new_x_rel = old_x_rel - (cos(theta * 0.5 * _deg_convert) * hypot);
  new_y_rel = old_y_rel - (sin(theta * 0.5 * _deg_convert) * hypot);
  new_x_abs = (centre_abs_x + new_x_rel);
  new_y_abs = (centre_abs_y + new_y_rel);
 
  Finish =  SysTick->VAL; 
 
  Serial.print(" Time to complete calcs below = ");
  temp = Start - Finish;
  if (temp <0) temp += SystemCoreClock/1000;
  temp = (float) ((temp*1000)/84);
  Serial.print(temp); Serial.println(" ns");
 

 Serial.print((Start - Finish)/84); Serial.println(" microseconds to complete calcs below");
 
  Serial.print("Start time = "); Serial.println(Start);
  Serial.print("Finish time = "); Serial.println(Finish);

  Serial.print("new_x_rel = "); Serial.println(new_x_rel, 10);
  Serial.print("new_y_rel = "); Serial.println(new_y_rel, 10);
  Serial.print("new_x_abs = "); Serial.println(new_x_abs, 10);
  Serial.print("new_y_abs = "); Serial.println(new_y_abs, 10);
  Serial.println();

  }

is the first column clock tiks???
how do i make these magic numbers, i am guessing i could convert to ASSEMBLY? in VS7.

the first column is relative memory location of where the function will go - see that as the number of bytes taken by your program. if you want to calculate how long it will take to execute, then you need to look at the assembly pseudo code to the right like [color=blue]lds  r22, 0x0000[/color] and go check in the documentation for your micro processor how many clock cycles the lds command takes and then do that for each line and sum up the clock cycles. Then you know how fast is your micro processor, so you know how long it takes to execute 1 clock cycle and you just multiply by the number of clock ticks needed and you have the total time of your program. (there are a few cycles extra to put thing on the stack and remove them for each function call you can see at the beginning/end of the calls)

To see the disassembly, I go in the build directory (if you compile in verbose mode you see that in your IDE) and use objdump -dS on the [i]xxxxx[/i].ino.cpp.o file that has been generated at compile time.

half an hour objdump too hard, is that a command line thing

Modified the code slightly by replacing sin with sinf and cos with cosf.

Time to complete calcs below = 41797.62 ns
41 microseconds to complete calcs below
Start time = 83391
Finish time = 79880
new_x_rel = -14.3347177505
new_y_rel = 37.3432159424
new_x_abs = 35.6652832031
new_y_abs = 87.3432159424

//#include <arduino.h>  // included in Arduino IDE
//#include "math.h"     // included in Arduino IDE

#define Serial SerialUSB
long randNumber;
int count = 0;
uint32_t Start = 0,Finish = 0;

//unsigned long result = 0;
//#define pi (3.14159265358979) // pi 16 chars
#define _deg_convert (0.01745329251994) // constant for pi/180

// void test_calc_time();

void setup() {
  randomSeed(analogRead(A0));
  Serial.begin(115200);
 
}

void loop() {
 
  test_calc_time();
  delay(2000);
  randNumber = constrain(random(A0), 0, 360);
  }


 void test_calc_time() {
  float temp;
  float centre_abs_x = 50.0f;
  float centre_abs_y = 50.0f;
  float theta = randNumber;
  float radius = 40.0f;
  float hypot;
  float old_x_rel = 0.0f;
  float old_y_rel = 40.0f;
  float new_x_rel;
  float new_y_rel;
  float new_x_abs;
  float new_y_abs;
 
 
  Start = SysTick->VAL;  // Systick->Val counts down from 84000 to 1 in 1 ms, then reloads with 84000
 
  hypot = 2 * (sinf(theta * 0.5f * _deg_convert) * radius);
  new_x_rel = old_x_rel - (cosf(theta * 0.5f * _deg_convert) * hypot);
  new_y_rel = old_y_rel - (sinf(theta * 0.5f * _deg_convert) * hypot);
  new_x_abs = (centre_abs_x + new_x_rel);
  new_y_abs = (centre_abs_y + new_y_rel);
 
  Finish =  SysTick->VAL;
 
  Serial.print(" Time to complete calcs below = ");
  temp = Start - Finish;
  if (temp <0) temp += SystemCoreClock/1000;
  temp = (float) ((temp*1000)/84);
  Serial.print(temp); Serial.println(" ns");
 

 Serial.print((Start - Finish)/84); Serial.println(" microseconds to complete calcs below");
 
  Serial.print("Start time = "); Serial.println(Start);
  Serial.print("Finish time = "); Serial.println(Finish);

  Serial.print("new_x_rel = "); Serial.println(new_x_rel, 10);
  Serial.print("new_y_rel = "); Serial.println(new_y_rel, 10);
  Serial.print("new_x_abs = "); Serial.println(new_x_abs, 10);
  Serial.print("new_y_abs = "); Serial.println(new_y_abs, 10);
  Serial.println();

  }

joeblogs:
half an hour objdump too hard, is that a command line thing

yes something you do in the terminal

@ Joeblogs

I placed the Start and Finish variables inside the subroutine, where they should be as volatile, and I get a mere 83 ns, with or without commenting your Serial.prints !!

//#pragma GCC optimize ("-O2")
//#include <arduino.h>  // included in Arduino IDE
//#include "math.h"     // included in Arduino IDE

//#define Serial SerialUSB
long randNumber;
int count = 0;


//unsigned long result = 0;
//#define pi (3.14159265358979) // pi 16 chars
#define _deg_convert (0.01745329251994) // constant for pi/180

// void test_calc_time();

void setup() {
  randomSeed(analogRead(A0));
  Serial.begin(115200);
 
}

void loop() {
 
  test_calc_time();
  delay(5000);
  randNumber = constrain(random(A0), 0, 360);
  }


 void test_calc_time() {
  volatile uint32_t Start,Finish;
  float temp;
  float centre_abs_x = 50;
  float centre_abs_y = 50;
  float theta = 50; //randNumber; // ***********
  float radius = 40.0;
  float hypot;
  float old_x_rel = 0;
  float old_y_rel = 40;
  float new_x_rel;
  float new_y_rel;
  float new_x_abs;
  float new_y_abs;
 
 
  Start = SysTick->VAL;  // Systick->Val counts down from 84000 to 1 in 1 ms, then reloads with 84000
 
  hypot = 2 * (sin(theta * 0.5 * _deg_convert) * radius);
  new_x_rel = old_x_rel - (cos(theta * 0.5 * _deg_convert) * hypot);
  new_y_rel = old_y_rel - (sin(theta * 0.5 * _deg_convert) * hypot);
  new_x_abs = (centre_abs_x + new_x_rel);
  new_y_abs = (centre_abs_y + new_y_rel);
 
  Finish =  SysTick->VAL; 
  
 
  Serial.print(" -------> Time to complete calcs  (not prints) = ");
  temp = Start - Finish;
  if (temp <0) temp += SystemCoreClock/1000;
  temp = (float) ((temp*1000)/84);
  Serial.print(temp); Serial.println(" ns"); 
 
  Serial.print("Start ticks = "); Serial.println(Start);
  Serial.print("Finish ticks = "); Serial.println(Finish);

  Serial.print("new_x_rel = "); Serial.println(new_x_rel, 10);
  Serial.print("new_y_rel = "); Serial.println(new_y_rel, 10);
  Serial.print("new_x_abs = "); Serial.println(new_x_abs, 10);
  Serial.print("new_y_abs = "); Serial.println(new_y_abs, 10);
  Serial.println();
  
 

  }

Hey Ard

float theta = 50; //randNumber;

youve commented out the changing number. doesnt that come back to no calculations are getting done, but they are getting evaluated as constants during compile.

uncomment it and times jump back to 60 to 110 us.

If you disagree, can you show me a way so i can get the theta value to change during the loop. In the program at the max machine speed the value will get changed every1.3ms.

cheers Okio
hadnt come across those before, i take it they are better optimised for floats.
30% thats a good saving considering there is more trig to come.

You need to "confuse" the preprocessor enough so that it cannot 100% infer that all these data are going to be constant indeed. otherwise it will do the work for you at compile time and not at execution time (which makes total sense)

when using optimisation flags, even parts of code and unused variables could just be totally ignored by the compiler if it sees you will never use that part of the code.

I hear you loud and clear J, thanks for your help
this is the final code that i am happy with, OKIOs tips really help when the theta value is low.
getting times of 40 to 65 us depending on the size of theta.

#include <arduino.h>
#include "math.h"

#define Serial SerialUSB

int count = 0;
unsigned long Start = 0;
unsigned long Finish = 0;
//unsigned long result = 0;
#define pi (3.14159265358979) // pi 16 chars
#define _deg_convert (0.01745329251994) // constant for pi/180

long randNumber;

void setup() {
  randomSeed(analogRead(A0));
  Serial.begin(115200);
  while (!Serial) {
    ;
  }
}

void loop() {
  
  next_XY_pos_circle();
  delay(5000);
  randNumber = random(0, 360);    // constrain(random(A0), 0, 360);
  }


 void next_XY_pos_circle() {

  float centre_abs_x = 50;
  float centre_abs_y = 50;
  float theta = randNumber;   // 360
  float radius = 40.0;
  float hypot;
  float old_x_rel = 0;
  float old_y_rel = 40;
  float new_x_rel;
  float new_y_rel;
  float new_x_abs;
  float new_y_abs;
  
  Start = micros();
  
  hypot = 2 * (sinf(theta * 0.5f * _deg_convert) * radius);
  new_x_rel = old_x_rel - (cosf(theta * 0.5f * _deg_convert) * hypot);
  new_y_rel = old_y_rel - (sinf(theta * 0.5f * _deg_convert) * hypot);
  new_x_abs = (centre_abs_x + new_x_rel);
  new_y_abs = (centre_abs_y + new_y_rel);

  Finish = micros();

  Serial.print(Finish - Start); Serial.println(" microseconds to complete calcs below");
  Serial.print("Start time = "); Serial.println(Start);
  Serial.print("Finish time = "); Serial.println(Finish);
  
  Serial.print("theta = "); Serial.println(theta);
  
  Serial.print("new_x_rel = "); Serial.println(new_x_rel, 10);
  Serial.print("new_y_rel = "); Serial.println(new_y_rel, 10);
  Serial.print("new_x_abs = "); Serial.println(new_x_abs, 10);
  Serial.print("new_y_abs = "); Serial.println(new_y_abs, 10);
  Serial.println();

  }

dont suppose any on has any ideas on minimising the floating point overhead.

That sounds good!