pebble/tests/libutil/test_math_fixed.c

537 lines
22 KiB
C
Raw Permalink Normal View History

/*
* 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);
}