mirror of
https://github.com/google/pebble.git
synced 2025-03-15 08:41:21 +00:00
536 lines
22 KiB
C
536 lines
22 KiB
C
/*
|
|
* Copyright 2024 Google LLC
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "util/math_fixed.h"
|
|
|
|
|
|
#include "clar.h"
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
// Helper Functions
|
|
////////////////////////////////////
|
|
|
|
// Stubs
|
|
////////////////////////////////////
|
|
|
|
// Tests
|
|
////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
/// Fixed_S16_3 = 1 bit sign, 12 bits integer, 3 bits fraction
|
|
////////////////////////////////////////////////////////////////
|
|
void test_math_fixed__S16_3_create(void) {
|
|
Fixed_S16_3 num;
|
|
int16_t test_num;
|
|
|
|
cl_assert(FIXED_S16_3_PRECISION == 3);
|
|
|
|
int Fixed_S16_3_size = sizeof(Fixed_S16_3);
|
|
cl_assert(Fixed_S16_3_size == sizeof(int16_t));
|
|
|
|
test_num = 1 << FIXED_S16_3_PRECISION;
|
|
num = (Fixed_S16_3){ .integer = 1, .fraction = 0 };
|
|
|
|
// Test number creation
|
|
test_num = (int16_t)((float)1 * (1 << FIXED_S16_3_PRECISION));
|
|
cl_assert(num.raw_value == test_num);
|
|
cl_assert((FIXED_S16_3_ONE.raw_value == test_num));
|
|
cl_assert(memcmp(&num, &test_num, sizeof(Fixed_S16_3)) == 0);
|
|
|
|
num = (Fixed_S16_3){ .raw_value = (int16_t)((float)3.5 * (1 << FIXED_S16_3_PRECISION)) };
|
|
test_num = (int16_t)((float)3.5 * (1 << FIXED_S16_3_PRECISION));
|
|
cl_assert(memcmp(&num, &test_num, sizeof(Fixed_S16_3)) == 0);
|
|
|
|
num = (Fixed_S16_3){ .raw_value = (int16_t)((float)-2 * (1 << FIXED_S16_3_PRECISION)) };
|
|
test_num = (int16_t)((float)-2 * (1 << FIXED_S16_3_PRECISION));
|
|
cl_assert(memcmp(&num, &test_num, sizeof(Fixed_S16_3)) == 0);
|
|
|
|
num = (Fixed_S16_3){ .raw_value = (int16_t)((float)-3.5 * (1 << FIXED_S16_3_PRECISION)) };
|
|
test_num = (int16_t)((float)-3.5 * (1 << FIXED_S16_3_PRECISION));
|
|
cl_assert(memcmp(&num, &test_num, sizeof(Fixed_S16_3)) == 0);
|
|
}
|
|
|
|
void test_math_fixed__S16_3_fraction(void) {
|
|
Fixed_S16_3 num;
|
|
int16_t test_num;
|
|
|
|
// This test shows how the values change across various fraction values
|
|
|
|
test_num = (int16_t)((float)-1.125 * (1 << FIXED_S16_3_PRECISION));
|
|
num = (Fixed_S16_3){ .raw_value = test_num };
|
|
cl_assert(num.integer == -2);
|
|
cl_assert(num.fraction == 7);
|
|
|
|
// This confirms that the fixed number is (2^FIXED_S16_3_PRECISION)*(float value)
|
|
test_num = -9;
|
|
cl_assert(memcmp(&num, &test_num, sizeof(Fixed_S16_3)) == 0);
|
|
|
|
test_num = (int16_t)((float)-1 * (1 << FIXED_S16_3_PRECISION));
|
|
num = (Fixed_S16_3){ .raw_value = test_num };
|
|
cl_assert(num.integer == -1);
|
|
cl_assert(num.fraction == 0);
|
|
|
|
test_num = (int16_t)((float)-0.875 * (1 << FIXED_S16_3_PRECISION));
|
|
num = (Fixed_S16_3){ .raw_value = test_num };
|
|
cl_assert(num.integer == -1);
|
|
cl_assert(num.fraction == 1);
|
|
|
|
test_num = (int32_t)((float)-0.750 * (1 << FIXED_S16_3_PRECISION));
|
|
num = (Fixed_S16_3){ .raw_value = test_num };
|
|
cl_assert(num.integer == -1);
|
|
cl_assert(num.fraction == 2);
|
|
|
|
test_num = (int32_t)((float)-0.625 * (1 << FIXED_S16_3_PRECISION));
|
|
num = (Fixed_S16_3){ .raw_value = test_num };
|
|
cl_assert(num.integer == -1);
|
|
cl_assert(num.fraction == 3);
|
|
|
|
test_num = (int32_t)((float)-0.500 * (1 << FIXED_S16_3_PRECISION));
|
|
num = (Fixed_S16_3){ .raw_value = test_num };
|
|
cl_assert(num.integer == -1);
|
|
cl_assert(num.fraction == 4);
|
|
|
|
test_num = (int32_t)((float)-0.375 * (1 << FIXED_S16_3_PRECISION));
|
|
num = (Fixed_S16_3){ .raw_value = test_num };
|
|
cl_assert(num.integer == -1);
|
|
cl_assert(num.fraction == 5);
|
|
|
|
test_num = (int32_t)((float)-0.250 * (1 << FIXED_S16_3_PRECISION));
|
|
num = (Fixed_S16_3){ .raw_value = test_num };
|
|
cl_assert(num.integer == -1);
|
|
cl_assert(num.fraction == 6);
|
|
|
|
test_num = (int32_t)((float)-0.125 * (1 << FIXED_S16_3_PRECISION));
|
|
num = (Fixed_S16_3){ .raw_value = test_num };
|
|
cl_assert(num.integer == -1);
|
|
cl_assert(num.fraction == 7);
|
|
|
|
test_num = (int32_t)((float)-0 * (1 << FIXED_S16_3_PRECISION));
|
|
num = (Fixed_S16_3){ .raw_value = test_num };
|
|
cl_assert(num.integer == 0);
|
|
cl_assert(num.fraction == 0);
|
|
|
|
test_num = (int32_t)((float)0 * (1 << FIXED_S16_3_PRECISION));
|
|
num = (Fixed_S16_3){ .raw_value = test_num };
|
|
cl_assert(num.integer == 0);
|
|
cl_assert(num.fraction == 0);
|
|
|
|
test_num = (int32_t)((float)0.125 * (1 << FIXED_S16_3_PRECISION));
|
|
num = (Fixed_S16_3){ .raw_value = test_num };
|
|
cl_assert(num.integer == 0);
|
|
cl_assert(num.fraction == 1);
|
|
|
|
test_num = (int32_t)((float)0.250 * (1 << FIXED_S16_3_PRECISION));
|
|
num = (Fixed_S16_3){ .raw_value = test_num };
|
|
cl_assert(num.integer == 0);
|
|
cl_assert(num.fraction == 2);
|
|
|
|
test_num = (int32_t)((float)0.375 * (1 << FIXED_S16_3_PRECISION));
|
|
num = (Fixed_S16_3){ .raw_value = test_num };
|
|
cl_assert(num.integer == 0);
|
|
cl_assert(num.fraction == 3);
|
|
|
|
test_num = (int32_t)((float)0.500 * (1 << FIXED_S16_3_PRECISION));
|
|
num = (Fixed_S16_3){ .raw_value = test_num };
|
|
cl_assert(num.integer == 0);
|
|
cl_assert(num.fraction == 4);
|
|
|
|
test_num = (int32_t)((float)0.625 * (1 << FIXED_S16_3_PRECISION));
|
|
num = (Fixed_S16_3){ .raw_value = test_num };
|
|
cl_assert(num.integer == 0);
|
|
cl_assert(num.fraction == 5);
|
|
|
|
test_num = (int32_t)((float)0.750 * (1 << FIXED_S16_3_PRECISION));
|
|
num = (Fixed_S16_3){ .raw_value = test_num };
|
|
cl_assert(num.integer == 0);
|
|
cl_assert(num.fraction == 6);
|
|
|
|
test_num = (int32_t)((float)0.875 * (1 << FIXED_S16_3_PRECISION));
|
|
num = (Fixed_S16_3){ .raw_value = test_num };
|
|
cl_assert(num.integer == 0);
|
|
cl_assert(num.fraction == 7);
|
|
|
|
test_num = (int16_t)((float)1 * (1 << FIXED_S16_3_PRECISION));
|
|
num = (Fixed_S16_3){ .raw_value = test_num };
|
|
cl_assert(num.integer == 1);
|
|
cl_assert(num.fraction == 0);
|
|
|
|
test_num = (int16_t)((float)1.125 * (1 << FIXED_S16_3_PRECISION));
|
|
num = (Fixed_S16_3){ .raw_value = test_num };
|
|
cl_assert(num.integer == 1);
|
|
cl_assert(num.fraction == 1);
|
|
}
|
|
|
|
void test_math_fixed__S16_3_range(void) {
|
|
Fixed_S16_3 num;
|
|
int16_t test_num;
|
|
|
|
// This equates to -0.125
|
|
num = (Fixed_S16_3){ .raw_value = 0xFFFF };
|
|
cl_assert(num.integer == -1);
|
|
cl_assert(num.fraction == 7);
|
|
test_num = (int32_t)((float)-0.125 * (1 << FIXED_S16_3_PRECISION));
|
|
cl_assert(memcmp(&num, &test_num, sizeof(Fixed_S16_3)) == 0);
|
|
num.raw_value++;
|
|
cl_assert(num.integer == 0);
|
|
cl_assert(num.fraction == 0);
|
|
|
|
num = (Fixed_S16_3){ .raw_value = 0x8000 };
|
|
cl_assert(num.integer == -4096);
|
|
cl_assert(num.fraction == 0);
|
|
test_num = (int32_t)((float)-4096 * (1 << FIXED_S16_3_PRECISION));
|
|
cl_assert(memcmp(&num, &test_num, sizeof(Fixed_S16_3)) == 0);
|
|
// overflowing negatively from -4096 results in going to 4095.875
|
|
num.raw_value--;
|
|
cl_assert(num.integer == 4095);
|
|
cl_assert(num.fraction == 7);
|
|
|
|
num = (Fixed_S16_3){ .raw_value = 0x7FFF };
|
|
cl_assert(num.integer == 4095);
|
|
cl_assert(num.fraction == 7);
|
|
test_num = (int32_t)((float)4095.875 * (1 << FIXED_S16_3_PRECISION));
|
|
cl_assert(memcmp(&num, &test_num, sizeof(Fixed_S16_3)) == 0);
|
|
// overflowing positively from 4095.875 results in going to -4096
|
|
num.raw_value++;
|
|
cl_assert(num.integer == -4096);
|
|
cl_assert(num.fraction == 0);
|
|
}
|
|
|
|
void test_math_fixed__Fixed_S16_3_rounded_int(void) {
|
|
cl_assert_equal_i(0, Fixed_S16_3_rounded_int(Fixed_S16_3(0)));
|
|
cl_assert_equal_i(0, Fixed_S16_3_rounded_int(Fixed_S16_3(3)));
|
|
cl_assert_equal_i(1, Fixed_S16_3_rounded_int(Fixed_S16_3(4)));
|
|
cl_assert_equal_i(1, Fixed_S16_3_rounded_int(Fixed_S16_3(8)));
|
|
cl_assert_equal_i(2, Fixed_S16_3_rounded_int(Fixed_S16_3(12)));
|
|
cl_assert_equal_i(0, Fixed_S16_3_rounded_int(Fixed_S16_3(-3)));
|
|
cl_assert_equal_i(-1, Fixed_S16_3_rounded_int(Fixed_S16_3(-4)));
|
|
cl_assert_equal_i(-1, Fixed_S16_3_rounded_int(Fixed_S16_3(-5)));
|
|
cl_assert_equal_i(-1, Fixed_S16_3_rounded_int(Fixed_S16_3(-8)));
|
|
cl_assert_equal_i(-2, Fixed_S16_3_rounded_int(Fixed_S16_3(-12)));
|
|
}
|
|
|
|
void test_math_fixed__S16_3_rounding(void) {
|
|
Fixed_S16_3 num;
|
|
int16_t test_num;
|
|
|
|
// This test shows how the in between fractional values evaluate to the fixed representation
|
|
// Positive numbers round down to nearest fraction
|
|
// Negative numbers round up to neareset fraction
|
|
test_num = (int16_t)((float)-1.249 * (1 << FIXED_S16_3_PRECISION));
|
|
num = (Fixed_S16_3){ .raw_value = test_num };
|
|
cl_assert(num.integer == -2);
|
|
cl_assert(num.fraction == 7); // rounds up to -1.125
|
|
|
|
test_num = (int16_t)((float)-1.126 * (1 << FIXED_S16_3_PRECISION));
|
|
num = (Fixed_S16_3){ .raw_value = test_num };
|
|
cl_assert(num.integer == -2);
|
|
cl_assert(num.fraction == 7); // rounds up to -1.125
|
|
|
|
test_num = (int16_t)((float)-1.124 * (1 << FIXED_S16_3_PRECISION));
|
|
num = (Fixed_S16_3){ .raw_value = test_num };
|
|
cl_assert(num.integer == -1);
|
|
cl_assert(num.fraction == 0); // rounds up to -1.000
|
|
|
|
test_num = (int16_t)((float)1.124 * (1 << FIXED_S16_3_PRECISION));
|
|
num = (Fixed_S16_3){ .raw_value = test_num };
|
|
cl_assert(num.integer == 1);
|
|
cl_assert(num.fraction == 0); // rounds down to 1.000
|
|
|
|
test_num = (int16_t)((float)1.126 * (1 << FIXED_S16_3_PRECISION));
|
|
num = (Fixed_S16_3){ .raw_value = test_num };
|
|
cl_assert(num.integer == 1);
|
|
cl_assert(num.fraction == 1); // rounds down to 1.125
|
|
|
|
test_num = (int16_t)((float)1.249 * (1 << FIXED_S16_3_PRECISION));
|
|
num = (Fixed_S16_3){ .raw_value = test_num };
|
|
cl_assert(num.integer == 1);
|
|
cl_assert(num.fraction == 1); // rounds down to 1.125
|
|
|
|
}
|
|
|
|
void test_math_fixed__S16_3_add(void) {
|
|
Fixed_S16_3 num1, num2;
|
|
Fixed_S16_3 sum, sum_c;
|
|
|
|
// Test number addition
|
|
num1 = FIXED_S16_3_ONE;
|
|
num2 = FIXED_S16_3_ONE;
|
|
sum = Fixed_S16_3_add(num1, num2);
|
|
sum_c = (Fixed_S16_3){ .raw_value = (int16_t)((float)2 * (1 << FIXED_S16_3_PRECISION)) };
|
|
cl_assert(sum.raw_value == sum_c.raw_value);
|
|
|
|
// sum = 3.5 + 1 = 4.5
|
|
num1 = (Fixed_S16_3){ .raw_value = (int16_t)((float)3.5 * (1 << FIXED_S16_3_PRECISION)) };
|
|
num2 = FIXED_S16_3_ONE;
|
|
sum = Fixed_S16_3_add(num1, num2);
|
|
sum_c = (Fixed_S16_3){ .raw_value = (int16_t)((float)4.5 * (1 << FIXED_S16_3_PRECISION)) };
|
|
cl_assert(sum.raw_value == sum_c.raw_value);
|
|
|
|
// sum = 1 + 3.5 = 4.5 - test commutative property of addition
|
|
num1 = FIXED_S16_3_ONE;
|
|
num2 = (Fixed_S16_3){ .raw_value = (int16_t)((float)3.5 * (1 << FIXED_S16_3_PRECISION)) };
|
|
sum = Fixed_S16_3_add(num1, num2);
|
|
sum_c = (Fixed_S16_3){ .raw_value = (int16_t)((float)4.5 * (1 << FIXED_S16_3_PRECISION)) };
|
|
cl_assert(sum.raw_value == sum_c.raw_value);
|
|
|
|
// sum = -2 + -3 = -5
|
|
num1 = (Fixed_S16_3){ .raw_value = (int16_t)((float)-2 * (1 << FIXED_S16_3_PRECISION)) };
|
|
num2 = (Fixed_S16_3){ .raw_value = (int16_t)((float)-3 * (1 << FIXED_S16_3_PRECISION)) };
|
|
sum = Fixed_S16_3_add(num1, num2);
|
|
sum_c = (Fixed_S16_3){ .raw_value = (int16_t)((float)-5 * (1 << FIXED_S16_3_PRECISION)) };
|
|
cl_assert(sum.raw_value == sum_c.raw_value);
|
|
|
|
// sum = -2 + 5 = 3
|
|
num1 = (Fixed_S16_3){ .raw_value = (int16_t)((float)-2 * (1 << FIXED_S16_3_PRECISION)) };
|
|
num2 = (Fixed_S16_3){ .raw_value = (int16_t)((float)5 * (1 << FIXED_S16_3_PRECISION)) };
|
|
sum = Fixed_S16_3_add(num1, num2);
|
|
sum_c = (Fixed_S16_3){ .raw_value = (int16_t)((float)3 * (1 << FIXED_S16_3_PRECISION)) };
|
|
cl_assert(sum.raw_value == sum_c.raw_value);
|
|
|
|
// sum = -2.1 + 5.4 ~= 3.375 (nearest 1/8 fraction to the expected result)
|
|
// math is as follows:
|
|
// -2.1 * (1 << 8) = -16.8 = -16 (drop fraction) ==> -2
|
|
// 5.4 * (1 << 8) = 43.2 = 43 (drop fraction) ==> 5.375
|
|
// -16 + 43 = 27 = 3.375 * (1 << 8)
|
|
num1 = (Fixed_S16_3){ .raw_value = (int16_t)((float)-2.1 * (1 << FIXED_S16_3_PRECISION)) };
|
|
num2 = (Fixed_S16_3){ .raw_value = (int16_t)((float)5.4 * (1 << FIXED_S16_3_PRECISION)) };
|
|
sum = Fixed_S16_3_add(num1, num2);
|
|
sum_c = (Fixed_S16_3){ .raw_value = (int16_t)((float)3.375 * (1 << FIXED_S16_3_PRECISION)) };
|
|
cl_assert(sum.raw_value == sum_c.raw_value);
|
|
|
|
// sum = 2.1 - 5.4 ~= -3.375 (nearest 1/8 fraction to the expected result)
|
|
// math is as follows:
|
|
// 2.1 * (1 << 8) = 16.8 = 16 (drop fraction) ==> 2
|
|
// -5.4 * (1 << 8) = -43.2 = -43 (drop fraction) ==> -5.375
|
|
// 16 - 43 = -27 = -3.375 * (1 << 8)
|
|
num1 = (Fixed_S16_3){ .raw_value = (int16_t)((float)2.1 * (1 << FIXED_S16_3_PRECISION)) };
|
|
num2 = (Fixed_S16_3){ .raw_value = (int16_t)((float)-5.4 * (1 << FIXED_S16_3_PRECISION)) };
|
|
sum = Fixed_S16_3_add(num1, num2);
|
|
sum_c = (Fixed_S16_3){ .raw_value = (int16_t)((float)-3.375 * (1 << FIXED_S16_3_PRECISION)) };
|
|
cl_assert(sum.raw_value == sum_c.raw_value);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
/// Fixed_S32_16 = 1 bit sign, 15 bits integer, 16 bits fraction
|
|
////////////////////////////////////////////////////////////////
|
|
void test_math_fixed__S32_16_create(void) {
|
|
Fixed_S32_16 num;
|
|
int32_t test_num;
|
|
|
|
cl_assert(FIXED_S32_16_PRECISION == 16);
|
|
|
|
test_num = 1 << FIXED_S32_16_PRECISION;
|
|
num = (Fixed_S32_16){ .integer = 1, .fraction = 0 };
|
|
|
|
test_num = (int32_t)((float)1 * (1 << FIXED_S32_16_PRECISION));
|
|
cl_assert(num.raw_value == test_num);
|
|
cl_assert((FIXED_S32_16_ONE.raw_value == test_num));
|
|
cl_assert(memcmp(&num, &test_num, sizeof(Fixed_S32_16)) == 0);
|
|
|
|
num = (Fixed_S32_16){ .raw_value = (int32_t)((float)3.5 * (1 << FIXED_S32_16_PRECISION)) };
|
|
test_num = (int32_t)((float)3.5 * (1 << FIXED_S32_16_PRECISION));
|
|
cl_assert(memcmp(&num, &test_num, sizeof(Fixed_S32_16)) == 0);
|
|
|
|
num = (Fixed_S32_16){ .raw_value = (int32_t)((float)-2 * (1 << FIXED_S32_16_PRECISION)) };
|
|
test_num = (int32_t)((float)-2 * (1 << FIXED_S32_16_PRECISION));
|
|
cl_assert(memcmp(&num, &test_num, sizeof(Fixed_S32_16)) == 0);
|
|
|
|
num = (Fixed_S32_16){ .raw_value = (int32_t)((float)-3.5 * (1 << FIXED_S32_16_PRECISION)) };
|
|
test_num = (int32_t)((float)-3.5 * (1 << FIXED_S32_16_PRECISION));
|
|
cl_assert(memcmp(&num, &test_num, sizeof(Fixed_S32_16)) == 0);
|
|
|
|
}
|
|
|
|
void test_math_fixed__S32_16_add(void) {
|
|
Fixed_S32_16 num1, num2;
|
|
Fixed_S32_16 sum, sum_c;
|
|
|
|
// Test number addition
|
|
num1 = FIXED_S32_16_ONE;
|
|
num2 = FIXED_S32_16_ONE;
|
|
sum = Fixed_S32_16_add(num1, num2);
|
|
sum_c = (Fixed_S32_16){ .raw_value = (int32_t)((float)2 * (1 << FIXED_S32_16_PRECISION)) };
|
|
cl_assert(sum.raw_value == sum_c.raw_value);
|
|
|
|
// sum = 3.5 + 1 = 4.5
|
|
num1 = (Fixed_S32_16){ .raw_value = (int32_t)((float)3.5 * (1 << FIXED_S32_16_PRECISION)) };
|
|
num2 = FIXED_S32_16_ONE;
|
|
sum = Fixed_S32_16_add(num1, num2);
|
|
sum_c = (Fixed_S32_16){ .raw_value = (int32_t)((float)4.5 * (1 << FIXED_S32_16_PRECISION)) };
|
|
cl_assert(sum.raw_value == sum_c.raw_value);
|
|
|
|
// sum = 1 + 3.5 = 4.5 - test commutative property of addition
|
|
num1 = FIXED_S32_16_ONE;
|
|
num2 = (Fixed_S32_16){ .raw_value = (int32_t)((float)3.5 * (1 << FIXED_S32_16_PRECISION)) };
|
|
sum = Fixed_S32_16_add(num1, num2);
|
|
sum_c = (Fixed_S32_16){ .raw_value = (int32_t)((float)4.5 * (1 << FIXED_S32_16_PRECISION)) };
|
|
cl_assert(sum.raw_value == sum_c.raw_value);
|
|
|
|
// sum = -2 + -3 = -5
|
|
num1 = (Fixed_S32_16){ .raw_value = (int32_t)((float)-2 * (1 << FIXED_S32_16_PRECISION)) };
|
|
num2 = (Fixed_S32_16){ .raw_value = (int32_t)((float)-3 * (1 << FIXED_S32_16_PRECISION)) };
|
|
sum = Fixed_S32_16_add(num1, num2);
|
|
sum_c = (Fixed_S32_16){ .raw_value = (int32_t)((float)-5 * (1 << FIXED_S32_16_PRECISION)) };
|
|
cl_assert(sum.raw_value == sum_c.raw_value);
|
|
|
|
// sum = -2 + 5 = 3
|
|
num1 = (Fixed_S32_16){ .raw_value = (int32_t)((float)-2 * (1 << FIXED_S32_16_PRECISION)) };
|
|
num2 = (Fixed_S32_16){ .raw_value = (int32_t)((float)5 * (1 << FIXED_S32_16_PRECISION)) };
|
|
sum = Fixed_S32_16_add(num1, num2);
|
|
sum_c = (Fixed_S32_16){ .raw_value = (int32_t)((float)3 * (1 << FIXED_S32_16_PRECISION)) };
|
|
cl_assert(sum.raw_value == sum_c.raw_value);
|
|
|
|
// sum = -2.1 + 5.4 = 3.3
|
|
// math is as follows:
|
|
// -2.1 * (1 << 16) = -137625.6 = -137625 (drop fraction)
|
|
// 5.4 * (1 << 16) = 353894.4 = 353894 (drop fraction)
|
|
// -137625 + 353894 = 216269 ~= 3.3
|
|
num1 = (Fixed_S32_16){ .raw_value = (int32_t)((float)-2.1 * (1 << FIXED_S32_16_PRECISION)) };
|
|
num2 = (Fixed_S32_16){ .raw_value = (int32_t)((float)5.4 * (1 << FIXED_S32_16_PRECISION)) };
|
|
sum = Fixed_S32_16_add(num1, num2);
|
|
sum_c = (Fixed_S32_16){ .raw_value = (int32_t)(216269) };
|
|
cl_assert(sum.raw_value == sum_c.raw_value);
|
|
|
|
// sum = 2.1 - 5.4 = -3.3
|
|
// math is as follows:
|
|
// 2.1 * (1 << 16) = 137625.6 = 137625 (drop fraction)
|
|
// -5.4 * (1 << 16) = -353894.4 = -353894 (drop fraction)
|
|
// 137625 - 353894 = -216269 ~= -3.3
|
|
num1 = (Fixed_S32_16){ .raw_value = (int32_t)((float)2.1 * (1 << FIXED_S32_16_PRECISION)) };
|
|
num2 = (Fixed_S32_16){ .raw_value = (int32_t)((float)-5.4 * (1 << FIXED_S32_16_PRECISION)) };
|
|
sum = Fixed_S32_16_add(num1, num2);
|
|
sum_c = (Fixed_S32_16){ .raw_value = (int32_t)(-216269) };
|
|
cl_assert(sum.raw_value == sum_c.raw_value);
|
|
}
|
|
|
|
void test_math_fixed__S32_16_add3(void) {
|
|
Fixed_S32_16 num1, num2, num3;
|
|
Fixed_S32_16 sum, sum_c;
|
|
|
|
// Test number addition
|
|
num1 = FIXED_S32_16_ONE;
|
|
num2 = FIXED_S32_16_ONE;
|
|
num3 = FIXED_S32_16_ONE;
|
|
sum = Fixed_S32_16_add3(num1, num2, num3);
|
|
sum_c = (Fixed_S32_16){ .raw_value = (int32_t)((float)3 * (1 << FIXED_S32_16_PRECISION)) };
|
|
cl_assert(sum.raw_value == sum_c.raw_value);
|
|
|
|
// sum = 3.7 + 2.3 + 1.1 = 242483.2 + 150732.8 + 72089.6
|
|
// ~= 242483 + 150732 + 72089 = 465304 ~= 7.1
|
|
num1 = (Fixed_S32_16){ .raw_value = (int32_t)((float)3.7 * (1 << FIXED_S32_16_PRECISION)) };
|
|
num2 = (Fixed_S32_16){ .raw_value = (int32_t)((float)2.3 * (1 << FIXED_S32_16_PRECISION)) };
|
|
num3 = (Fixed_S32_16){ .raw_value = (int32_t)((float)1.1 * (1 << FIXED_S32_16_PRECISION)) };
|
|
sum = Fixed_S32_16_add3(num1, num2, num3);
|
|
sum_c = (Fixed_S32_16){ .raw_value = (int32_t)(465304) };
|
|
cl_assert(sum.raw_value == sum_c.raw_value);
|
|
}
|
|
|
|
void test_math_fixed__S32_16_mul(void) {
|
|
Fixed_S32_16 num1, num2;
|
|
Fixed_S32_16 mul, mul_c;
|
|
|
|
// Test number muliplication
|
|
num1 = FIXED_S32_16_ONE;
|
|
num2 = FIXED_S32_16_ONE;
|
|
mul = Fixed_S32_16_mul(num1, num2);
|
|
mul_c = (Fixed_S32_16){ .raw_value = (int32_t)((float)1 * (1 << FIXED_S32_16_PRECISION)) };
|
|
cl_assert(mul.raw_value == mul_c.raw_value);
|
|
|
|
// 2*3 = 6
|
|
num1 = (Fixed_S32_16){ .raw_value = (int32_t)((float)2 * (1 << FIXED_S32_16_PRECISION)) };
|
|
num2 = (Fixed_S32_16){ .raw_value = (int32_t)((float)3 * (1 << FIXED_S32_16_PRECISION)) };
|
|
mul = Fixed_S32_16_mul(num1, num2);
|
|
mul_c = (Fixed_S32_16){ .raw_value = (int32_t)((float)6 * (1 << FIXED_S32_16_PRECISION)) };
|
|
cl_assert(mul.raw_value == mul_c.raw_value);
|
|
|
|
// -2*3 = -6
|
|
num1 = (Fixed_S32_16){ .raw_value = (int32_t)((float)-2 * (1 << FIXED_S32_16_PRECISION)) };
|
|
num2 = (Fixed_S32_16){ .raw_value = (int32_t)((float)3 * (1 << FIXED_S32_16_PRECISION)) };
|
|
mul = Fixed_S32_16_mul(num1, num2);
|
|
mul_c = (Fixed_S32_16){ .raw_value = (int32_t)((float)-6 * (1 << FIXED_S32_16_PRECISION)) };
|
|
cl_assert(mul.raw_value == mul_c.raw_value);
|
|
|
|
// -2*-3 = 6
|
|
num1 = (Fixed_S32_16){ .raw_value = (int32_t)((float)-2 * (1 << FIXED_S32_16_PRECISION)) };
|
|
num2 = (Fixed_S32_16){ .raw_value = (int32_t)((float)-3 * (1 << FIXED_S32_16_PRECISION)) };
|
|
mul = Fixed_S32_16_mul(num1, num2);
|
|
mul_c = (Fixed_S32_16){ .raw_value = (int32_t)((float)6 * (1 << FIXED_S32_16_PRECISION)) };
|
|
cl_assert(mul.raw_value == mul_c.raw_value);
|
|
|
|
// -2.5*-3.3 ==> 163840 * 216268.8 = 163840 * 216268 ==> 35433349120 / 65536 ==> 540670 ~= 8.25
|
|
num1 = (Fixed_S32_16){ .raw_value = (int32_t)((float)-2.5 * (1 << FIXED_S32_16_PRECISION)) };
|
|
num2 = (Fixed_S32_16){ .raw_value = (int32_t)((float)-3.3 * (1 << FIXED_S32_16_PRECISION)) };
|
|
mul = Fixed_S32_16_mul(num1, num2);
|
|
mul_c = (Fixed_S32_16){ .raw_value = (int32_t)(540670) };
|
|
cl_assert(mul.raw_value == mul_c.raw_value);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
/// Mixed operations
|
|
////////////////////////////////////////////////////////////////
|
|
void test_math_fixed__S16_3_S32_16_mul(void) {
|
|
Fixed_S16_3 num1;
|
|
Fixed_S32_16 num2;
|
|
Fixed_S16_3 mul, mul_c;
|
|
|
|
// 1*1 = 1
|
|
num1 = FIXED_S16_3_ONE;
|
|
num2 = FIXED_S32_16_ONE;
|
|
mul = Fixed_S16_3_S32_16_mul(num1, num2);
|
|
mul_c = (Fixed_S16_3){ .raw_value = (int32_t)((float)1 * (1 << FIXED_S16_3_PRECISION)) };
|
|
cl_assert(mul.raw_value == mul_c.raw_value);
|
|
|
|
// 3.5*1 = 3.5
|
|
num1 = (Fixed_S16_3){ .raw_value = (int32_t)((float)3.5 * (1 << FIXED_S16_3_PRECISION)) };
|
|
num2 = FIXED_S32_16_ONE;
|
|
mul = Fixed_S16_3_S32_16_mul(num1, num2);
|
|
mul_c = (Fixed_S16_3){ .raw_value = (int32_t)((float)3.5 * (1 << FIXED_S16_3_PRECISION)) };
|
|
cl_assert(mul.raw_value == mul_c.raw_value);
|
|
|
|
// 1*3.5 = 3.5
|
|
num1 = FIXED_S16_3_ONE;
|
|
num2 = (Fixed_S32_16){ .raw_value = (int32_t)((float)3.5 * (1 << FIXED_S32_16_PRECISION)) };
|
|
mul = Fixed_S16_3_S32_16_mul(num1, num2);
|
|
mul_c = (Fixed_S16_3){ .raw_value = (int32_t)((float)3.5 * (1 << FIXED_S16_3_PRECISION)) };
|
|
cl_assert(mul.raw_value == mul_c.raw_value);
|
|
|
|
// 2.25*3.5 = 7.875
|
|
num1 = (Fixed_S16_3){ .raw_value = (int32_t)((float)2.25 * (1 << FIXED_S16_3_PRECISION)) };
|
|
num2 = (Fixed_S32_16){ .raw_value = (int32_t)((float)3.5 * (1 << FIXED_S32_16_PRECISION)) };
|
|
mul = Fixed_S16_3_S32_16_mul(num1, num2);
|
|
mul_c = (Fixed_S16_3){ .raw_value = (int32_t)((float)7.875 * (1 << FIXED_S16_3_PRECISION)) };
|
|
cl_assert(mul.raw_value == mul_c.raw_value);
|
|
// check surrounding values
|
|
mul_c = (Fixed_S16_3){ .raw_value = (int32_t)((float)7.750 * (1 << FIXED_S16_3_PRECISION)) };
|
|
cl_assert(mul.raw_value != mul_c.raw_value);
|
|
mul_c = (Fixed_S16_3){ .raw_value = (int32_t)((float)8.0 * (1 << FIXED_S16_3_PRECISION)) };
|
|
cl_assert(mul.raw_value != mul_c.raw_value);
|
|
|
|
|
|
// 2.25*3.3 = 7.425
|
|
num1 = (Fixed_S16_3){ .raw_value = (int32_t)((float)2.25 * (1 << FIXED_S16_3_PRECISION)) };
|
|
num2 = (Fixed_S32_16){ .raw_value = (int32_t)((float)3.3 * (1 << FIXED_S32_16_PRECISION)) };
|
|
mul = Fixed_S16_3_S32_16_mul(num1, num2);
|
|
mul_c = (Fixed_S16_3){ .raw_value = (int32_t)((float)7.425 * (1 << FIXED_S16_3_PRECISION)) };
|
|
cl_assert(mul.raw_value == mul_c.raw_value);
|
|
// check surrounding values
|
|
mul_c = (Fixed_S16_3){ .raw_value = (int32_t)((float)7.375 * (1 << FIXED_S16_3_PRECISION)) };
|
|
cl_assert(mul.raw_value == mul_c.raw_value);
|
|
mul_c = (Fixed_S16_3){ .raw_value = (int32_t)((float)7.5 * (1 << FIXED_S16_3_PRECISION)) };
|
|
cl_assert(mul.raw_value != mul_c.raw_value);
|
|
}
|