162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Kunit tests for IIO rescale conversions 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2021 Liam Beguin <liambeguin@gmail.com> 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/gcd.h> 962306a36Sopenharmony_ci#include <linux/overflow.h> 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <linux/iio/afe/rescale.h> 1262306a36Sopenharmony_ci#include <linux/iio/iio.h> 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#include <kunit/test.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_cistruct rescale_tc_data { 1762306a36Sopenharmony_ci const char *name; 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci const s32 numerator; 2062306a36Sopenharmony_ci const s32 denominator; 2162306a36Sopenharmony_ci const s32 offset; 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci const int schan_val; 2462306a36Sopenharmony_ci const int schan_val2; 2562306a36Sopenharmony_ci const int schan_off; 2662306a36Sopenharmony_ci const int schan_scale_type; 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci const char *expected; 2962306a36Sopenharmony_ci const char *expected_off; 3062306a36Sopenharmony_ci}; 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_cistatic const struct rescale_tc_data scale_cases[] = { 3362306a36Sopenharmony_ci /* 3462306a36Sopenharmony_ci * Typical use cases 3562306a36Sopenharmony_ci */ 3662306a36Sopenharmony_ci { 3762306a36Sopenharmony_ci .name = "typical IIO_VAL_INT, positive", 3862306a36Sopenharmony_ci .numerator = 1000000, 3962306a36Sopenharmony_ci .denominator = 8060, 4062306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_INT, 4162306a36Sopenharmony_ci .schan_val = 42, 4262306a36Sopenharmony_ci .expected = "5210.918114143", 4362306a36Sopenharmony_ci }, 4462306a36Sopenharmony_ci { 4562306a36Sopenharmony_ci .name = "typical IIO_VAL_INT, negative", 4662306a36Sopenharmony_ci .numerator = -1000000, 4762306a36Sopenharmony_ci .denominator = 8060, 4862306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_INT, 4962306a36Sopenharmony_ci .schan_val = 42, 5062306a36Sopenharmony_ci .expected = "-5210.918114143", 5162306a36Sopenharmony_ci }, 5262306a36Sopenharmony_ci { 5362306a36Sopenharmony_ci .name = "typical IIO_VAL_FRACTIONAL, positive", 5462306a36Sopenharmony_ci .numerator = 1000000, 5562306a36Sopenharmony_ci .denominator = 8060, 5662306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_FRACTIONAL, 5762306a36Sopenharmony_ci .schan_val = 42, 5862306a36Sopenharmony_ci .schan_val2 = 20, 5962306a36Sopenharmony_ci .expected = "260.545905707", 6062306a36Sopenharmony_ci }, 6162306a36Sopenharmony_ci { 6262306a36Sopenharmony_ci .name = "typical IIO_VAL_FRACTIONAL, negative", 6362306a36Sopenharmony_ci .numerator = -1000000, 6462306a36Sopenharmony_ci .denominator = 8060, 6562306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_FRACTIONAL, 6662306a36Sopenharmony_ci .schan_val = 42, 6762306a36Sopenharmony_ci .schan_val2 = 20, 6862306a36Sopenharmony_ci .expected = "-260.545905707", 6962306a36Sopenharmony_ci }, 7062306a36Sopenharmony_ci { 7162306a36Sopenharmony_ci .name = "typical IIO_VAL_FRACTIONAL_LOG2, positive", 7262306a36Sopenharmony_ci .numerator = 42, 7362306a36Sopenharmony_ci .denominator = 53, 7462306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_FRACTIONAL_LOG2, 7562306a36Sopenharmony_ci .schan_val = 4096, 7662306a36Sopenharmony_ci .schan_val2 = 16, 7762306a36Sopenharmony_ci .expected = "0.049528301", 7862306a36Sopenharmony_ci }, 7962306a36Sopenharmony_ci { 8062306a36Sopenharmony_ci .name = "typical IIO_VAL_FRACTIONAL_LOG2, negative", 8162306a36Sopenharmony_ci .numerator = -42, 8262306a36Sopenharmony_ci .denominator = 53, 8362306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_FRACTIONAL_LOG2, 8462306a36Sopenharmony_ci .schan_val = 4096, 8562306a36Sopenharmony_ci .schan_val2 = 16, 8662306a36Sopenharmony_ci .expected = "-0.049528301", 8762306a36Sopenharmony_ci }, 8862306a36Sopenharmony_ci { 8962306a36Sopenharmony_ci .name = "typical IIO_VAL_INT_PLUS_NANO, positive", 9062306a36Sopenharmony_ci .numerator = 1000000, 9162306a36Sopenharmony_ci .denominator = 8060, 9262306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_INT_PLUS_NANO, 9362306a36Sopenharmony_ci .schan_val = 10, 9462306a36Sopenharmony_ci .schan_val2 = 123456, 9562306a36Sopenharmony_ci .expected = "1240.710106203", 9662306a36Sopenharmony_ci }, 9762306a36Sopenharmony_ci { 9862306a36Sopenharmony_ci .name = "typical IIO_VAL_INT_PLUS_NANO, negative", 9962306a36Sopenharmony_ci .numerator = -1000000, 10062306a36Sopenharmony_ci .denominator = 8060, 10162306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_INT_PLUS_NANO, 10262306a36Sopenharmony_ci .schan_val = 10, 10362306a36Sopenharmony_ci .schan_val2 = 123456, 10462306a36Sopenharmony_ci .expected = "-1240.710106203", 10562306a36Sopenharmony_ci }, 10662306a36Sopenharmony_ci { 10762306a36Sopenharmony_ci .name = "typical IIO_VAL_INT_PLUS_MICRO, positive", 10862306a36Sopenharmony_ci .numerator = 1000000, 10962306a36Sopenharmony_ci .denominator = 8060, 11062306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_INT_PLUS_MICRO, 11162306a36Sopenharmony_ci .schan_val = 10, 11262306a36Sopenharmony_ci .schan_val2 = 1234, 11362306a36Sopenharmony_ci .expected = "1240.84789", 11462306a36Sopenharmony_ci }, 11562306a36Sopenharmony_ci { 11662306a36Sopenharmony_ci .name = "typical IIO_VAL_INT_PLUS_MICRO, negative", 11762306a36Sopenharmony_ci .numerator = -1000000, 11862306a36Sopenharmony_ci .denominator = 8060, 11962306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_INT_PLUS_MICRO, 12062306a36Sopenharmony_ci .schan_val = 10, 12162306a36Sopenharmony_ci .schan_val2 = 1234, 12262306a36Sopenharmony_ci .expected = "-1240.84789", 12362306a36Sopenharmony_ci }, 12462306a36Sopenharmony_ci /* 12562306a36Sopenharmony_ci * Use cases with small scales involving divisions 12662306a36Sopenharmony_ci */ 12762306a36Sopenharmony_ci { 12862306a36Sopenharmony_ci .name = "small IIO_VAL_FRACTIONAL, 261/509 scaled by 90/1373754273", 12962306a36Sopenharmony_ci .numerator = 261, 13062306a36Sopenharmony_ci .denominator = 509, 13162306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_FRACTIONAL, 13262306a36Sopenharmony_ci .schan_val = 90, 13362306a36Sopenharmony_ci .schan_val2 = 1373754273, 13462306a36Sopenharmony_ci .expected = "0.000000033594", 13562306a36Sopenharmony_ci }, 13662306a36Sopenharmony_ci { 13762306a36Sopenharmony_ci .name = "small IIO_VAL_FRACTIONAL, 90/1373754273 scaled by 261/509", 13862306a36Sopenharmony_ci .numerator = 90, 13962306a36Sopenharmony_ci .denominator = 1373754273, 14062306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_FRACTIONAL, 14162306a36Sopenharmony_ci .schan_val = 261, 14262306a36Sopenharmony_ci .schan_val2 = 509, 14362306a36Sopenharmony_ci .expected = "0.000000033594", 14462306a36Sopenharmony_ci }, 14562306a36Sopenharmony_ci { 14662306a36Sopenharmony_ci .name = "small IIO_VAL_FRACTIONAL, 760/1373754273 scaled by 427/2727", 14762306a36Sopenharmony_ci .numerator = 760, 14862306a36Sopenharmony_ci .denominator = 1373754273, 14962306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_FRACTIONAL, 15062306a36Sopenharmony_ci .schan_val = 427, 15162306a36Sopenharmony_ci .schan_val2 = 2727, 15262306a36Sopenharmony_ci .expected = "0.000000086626", 15362306a36Sopenharmony_ci }, 15462306a36Sopenharmony_ci { 15562306a36Sopenharmony_ci .name = "small IIO_VAL_FRACTIONAL, 761/1373754273 scaled by 427/2727", 15662306a36Sopenharmony_ci .numerator = 761, 15762306a36Sopenharmony_ci .denominator = 1373754273, 15862306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_FRACTIONAL, 15962306a36Sopenharmony_ci .schan_val = 427, 16062306a36Sopenharmony_ci .schan_val2 = 2727, 16162306a36Sopenharmony_ci .expected = "0.000000086740", 16262306a36Sopenharmony_ci }, 16362306a36Sopenharmony_ci { 16462306a36Sopenharmony_ci .name = "small IIO_VAL_FRACTIONAL, 5/32768 scaled by 3/10000", 16562306a36Sopenharmony_ci .numerator = 5, 16662306a36Sopenharmony_ci .denominator = 32768, 16762306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_FRACTIONAL, 16862306a36Sopenharmony_ci .schan_val = 3, 16962306a36Sopenharmony_ci .schan_val2 = 10000, 17062306a36Sopenharmony_ci .expected = "0.0000000457763671875", 17162306a36Sopenharmony_ci }, 17262306a36Sopenharmony_ci { 17362306a36Sopenharmony_ci .name = "small IIO_VAL_FRACTIONAL, 0 < scale < 1", 17462306a36Sopenharmony_ci .numerator = 6, 17562306a36Sopenharmony_ci .denominator = 6, 17662306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_FRACTIONAL, 17762306a36Sopenharmony_ci .schan_val = 1, 17862306a36Sopenharmony_ci .schan_val2 = 3, 17962306a36Sopenharmony_ci .expected = "0.3333333333333333", 18062306a36Sopenharmony_ci }, 18162306a36Sopenharmony_ci { 18262306a36Sopenharmony_ci .name = "small IIO_VAL_FRACTIONAL, -1 < scale < 0", 18362306a36Sopenharmony_ci .numerator = -6, 18462306a36Sopenharmony_ci .denominator = 6, 18562306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_FRACTIONAL, 18662306a36Sopenharmony_ci .schan_val = 1, 18762306a36Sopenharmony_ci .schan_val2 = 3, 18862306a36Sopenharmony_ci .expected = "-0.3333333333333333", 18962306a36Sopenharmony_ci }, 19062306a36Sopenharmony_ci { 19162306a36Sopenharmony_ci .name = "small IIO_VAL_FRACTIONAL, 0 < scale < 2", 19262306a36Sopenharmony_ci .numerator = 8, 19362306a36Sopenharmony_ci .denominator = 2, 19462306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_FRACTIONAL, 19562306a36Sopenharmony_ci .schan_val = 1, 19662306a36Sopenharmony_ci .schan_val2 = 3, 19762306a36Sopenharmony_ci .expected = "1.3333333333333333", 19862306a36Sopenharmony_ci }, 19962306a36Sopenharmony_ci { 20062306a36Sopenharmony_ci .name = "small IIO_VAL_FRACTIONAL, -2 < scale < 0", 20162306a36Sopenharmony_ci .numerator = -8, 20262306a36Sopenharmony_ci .denominator = 2, 20362306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_FRACTIONAL, 20462306a36Sopenharmony_ci .schan_val = 1, 20562306a36Sopenharmony_ci .schan_val2 = 3, 20662306a36Sopenharmony_ci .expected = "-1.3333333333333333", 20762306a36Sopenharmony_ci }, 20862306a36Sopenharmony_ci { 20962306a36Sopenharmony_ci .name = "small IIO_VAL_FRACTIONAL_LOG2, 760/32768 scaled by 15/22", 21062306a36Sopenharmony_ci .numerator = 760, 21162306a36Sopenharmony_ci .denominator = 32768, 21262306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_FRACTIONAL_LOG2, 21362306a36Sopenharmony_ci .schan_val = 15, 21462306a36Sopenharmony_ci .schan_val2 = 22, 21562306a36Sopenharmony_ci .expected = "0.000000082946", 21662306a36Sopenharmony_ci }, 21762306a36Sopenharmony_ci { 21862306a36Sopenharmony_ci .name = "small IIO_VAL_FRACTIONAL_LOG2, 761/32768 scaled by 15/22", 21962306a36Sopenharmony_ci .numerator = 761, 22062306a36Sopenharmony_ci .denominator = 32768, 22162306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_FRACTIONAL_LOG2, 22262306a36Sopenharmony_ci .schan_val = 15, 22362306a36Sopenharmony_ci .schan_val2 = 22, 22462306a36Sopenharmony_ci .expected = "0.000000083055", 22562306a36Sopenharmony_ci }, 22662306a36Sopenharmony_ci { 22762306a36Sopenharmony_ci .name = "small IIO_VAL_FRACTIONAL_LOG2, 0 < scale < 1", 22862306a36Sopenharmony_ci .numerator = 16, 22962306a36Sopenharmony_ci .denominator = 3, 23062306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_FRACTIONAL_LOG2, 23162306a36Sopenharmony_ci .schan_val = 1, 23262306a36Sopenharmony_ci .schan_val2 = 4, 23362306a36Sopenharmony_ci .expected = "0.3333333333333333", 23462306a36Sopenharmony_ci }, 23562306a36Sopenharmony_ci { 23662306a36Sopenharmony_ci .name = "small IIO_VAL_FRACTIONAL_LOG2, -1 < scale < 0", 23762306a36Sopenharmony_ci .numerator = -16, 23862306a36Sopenharmony_ci .denominator = 3, 23962306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_FRACTIONAL_LOG2, 24062306a36Sopenharmony_ci .schan_val = 1, 24162306a36Sopenharmony_ci .schan_val2 = 4, 24262306a36Sopenharmony_ci .expected = "-0.3333333333333333", 24362306a36Sopenharmony_ci }, 24462306a36Sopenharmony_ci { 24562306a36Sopenharmony_ci .name = "small IIO_VAL_FRACTIONAL_LOG2, 0 < scale < 2", 24662306a36Sopenharmony_ci .numerator = 8, 24762306a36Sopenharmony_ci .denominator = 3, 24862306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_FRACTIONAL_LOG2, 24962306a36Sopenharmony_ci .schan_val = 1, 25062306a36Sopenharmony_ci .schan_val2 = 1, 25162306a36Sopenharmony_ci .expected = "1.3333333333333333", 25262306a36Sopenharmony_ci }, 25362306a36Sopenharmony_ci { 25462306a36Sopenharmony_ci .name = "small IIO_VAL_FRACTIONAL_LOG2, -2 < scale < 0", 25562306a36Sopenharmony_ci .numerator = -8, 25662306a36Sopenharmony_ci .denominator = 3, 25762306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_FRACTIONAL_LOG2, 25862306a36Sopenharmony_ci .schan_val = 1, 25962306a36Sopenharmony_ci .schan_val2 = 1, 26062306a36Sopenharmony_ci .expected = "-1.3333333333333333", 26162306a36Sopenharmony_ci }, 26262306a36Sopenharmony_ci { 26362306a36Sopenharmony_ci .name = "small IIO_VAL_INT_PLUS_MICRO, positive", 26462306a36Sopenharmony_ci .numerator = 1, 26562306a36Sopenharmony_ci .denominator = 2, 26662306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_INT_PLUS_MICRO, 26762306a36Sopenharmony_ci .schan_val = 5, 26862306a36Sopenharmony_ci .schan_val2 = 1234, 26962306a36Sopenharmony_ci .expected = "2.500617", 27062306a36Sopenharmony_ci }, 27162306a36Sopenharmony_ci { 27262306a36Sopenharmony_ci .name = "small IIO_VAL_INT_PLUS_MICRO, negative", 27362306a36Sopenharmony_ci .numerator = -1, 27462306a36Sopenharmony_ci .denominator = 2, 27562306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_INT_PLUS_MICRO, 27662306a36Sopenharmony_ci .schan_val = 5, 27762306a36Sopenharmony_ci .schan_val2 = 1234, 27862306a36Sopenharmony_ci .expected = "-2.500617", 27962306a36Sopenharmony_ci }, 28062306a36Sopenharmony_ci /* 28162306a36Sopenharmony_ci * INT_PLUS_{MICRO,NANO} positive/negative corner cases 28262306a36Sopenharmony_ci */ 28362306a36Sopenharmony_ci { 28462306a36Sopenharmony_ci .name = "negative IIO_VAL_INT_PLUS_NANO, negative schan", 28562306a36Sopenharmony_ci .numerator = 1000000, 28662306a36Sopenharmony_ci .denominator = 8060, 28762306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_INT_PLUS_NANO, 28862306a36Sopenharmony_ci .schan_val = -10, 28962306a36Sopenharmony_ci .schan_val2 = 123456, 29062306a36Sopenharmony_ci .expected = "-1240.710106203", 29162306a36Sopenharmony_ci }, 29262306a36Sopenharmony_ci { 29362306a36Sopenharmony_ci .name = "negative IIO_VAL_INT_PLUS_NANO, both negative", 29462306a36Sopenharmony_ci .numerator = -1000000, 29562306a36Sopenharmony_ci .denominator = 8060, 29662306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_INT_PLUS_NANO, 29762306a36Sopenharmony_ci .schan_val = -10, 29862306a36Sopenharmony_ci .schan_val2 = 123456, 29962306a36Sopenharmony_ci .expected = "1240.710106203", 30062306a36Sopenharmony_ci }, 30162306a36Sopenharmony_ci { 30262306a36Sopenharmony_ci .name = "negative IIO_VAL_INT_PLUS_NANO, 3 negative", 30362306a36Sopenharmony_ci .numerator = -1000000, 30462306a36Sopenharmony_ci .denominator = -8060, 30562306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_INT_PLUS_NANO, 30662306a36Sopenharmony_ci .schan_val = -10, 30762306a36Sopenharmony_ci .schan_val2 = 123456, 30862306a36Sopenharmony_ci .expected = "-1240.710106203", 30962306a36Sopenharmony_ci }, 31062306a36Sopenharmony_ci { 31162306a36Sopenharmony_ci .name = "negative IIO_VAL_INT_PLUS_NANO, 4 negative", 31262306a36Sopenharmony_ci .numerator = -1000000, 31362306a36Sopenharmony_ci .denominator = -8060, 31462306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_INT_PLUS_NANO, 31562306a36Sopenharmony_ci .schan_val = -10, 31662306a36Sopenharmony_ci .schan_val2 = -123456, 31762306a36Sopenharmony_ci .expected = "-1240.710106203", 31862306a36Sopenharmony_ci }, 31962306a36Sopenharmony_ci { 32062306a36Sopenharmony_ci .name = "negative IIO_VAL_INT_PLUS_NANO, negative, *val = 0", 32162306a36Sopenharmony_ci .numerator = 1, 32262306a36Sopenharmony_ci .denominator = -10, 32362306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_INT_PLUS_NANO, 32462306a36Sopenharmony_ci .schan_val = 0, 32562306a36Sopenharmony_ci .schan_val2 = 123456789, 32662306a36Sopenharmony_ci .expected = "-0.012345678", 32762306a36Sopenharmony_ci }, 32862306a36Sopenharmony_ci /* 32962306a36Sopenharmony_ci * INT_PLUS_{MICRO,NANO} decimal part overflow 33062306a36Sopenharmony_ci */ 33162306a36Sopenharmony_ci { 33262306a36Sopenharmony_ci .name = "decimal overflow IIO_VAL_INT_PLUS_NANO, positive", 33362306a36Sopenharmony_ci .numerator = 1000000, 33462306a36Sopenharmony_ci .denominator = 8060, 33562306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_INT_PLUS_NANO, 33662306a36Sopenharmony_ci .schan_val = 10, 33762306a36Sopenharmony_ci .schan_val2 = 123456789, 33862306a36Sopenharmony_ci .expected = "1256.01200856", 33962306a36Sopenharmony_ci }, 34062306a36Sopenharmony_ci { 34162306a36Sopenharmony_ci .name = "decimal overflow IIO_VAL_INT_PLUS_NANO, negative", 34262306a36Sopenharmony_ci .numerator = -1000000, 34362306a36Sopenharmony_ci .denominator = 8060, 34462306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_INT_PLUS_NANO, 34562306a36Sopenharmony_ci .schan_val = 10, 34662306a36Sopenharmony_ci .schan_val2 = 123456789, 34762306a36Sopenharmony_ci .expected = "-1256.01200856", 34862306a36Sopenharmony_ci }, 34962306a36Sopenharmony_ci { 35062306a36Sopenharmony_ci .name = "decimal overflow IIO_VAL_INT_PLUS_NANO, negative schan", 35162306a36Sopenharmony_ci .numerator = 1000000, 35262306a36Sopenharmony_ci .denominator = 8060, 35362306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_INT_PLUS_NANO, 35462306a36Sopenharmony_ci .schan_val = -10, 35562306a36Sopenharmony_ci .schan_val2 = 123456789, 35662306a36Sopenharmony_ci .expected = "-1256.01200856", 35762306a36Sopenharmony_ci }, 35862306a36Sopenharmony_ci { 35962306a36Sopenharmony_ci .name = "decimal overflow IIO_VAL_INT_PLUS_MICRO, positive", 36062306a36Sopenharmony_ci .numerator = 1000000, 36162306a36Sopenharmony_ci .denominator = 8060, 36262306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_INT_PLUS_MICRO, 36362306a36Sopenharmony_ci .schan_val = 10, 36462306a36Sopenharmony_ci .schan_val2 = 123456789, 36562306a36Sopenharmony_ci .expected = "16557.914267", 36662306a36Sopenharmony_ci }, 36762306a36Sopenharmony_ci { 36862306a36Sopenharmony_ci .name = "decimal overflow IIO_VAL_INT_PLUS_MICRO, negative", 36962306a36Sopenharmony_ci .numerator = -1000000, 37062306a36Sopenharmony_ci .denominator = 8060, 37162306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_INT_PLUS_MICRO, 37262306a36Sopenharmony_ci .schan_val = 10, 37362306a36Sopenharmony_ci .schan_val2 = 123456789, 37462306a36Sopenharmony_ci .expected = "-16557.914267", 37562306a36Sopenharmony_ci }, 37662306a36Sopenharmony_ci { 37762306a36Sopenharmony_ci .name = "decimal overflow IIO_VAL_INT_PLUS_MICRO, negative schan", 37862306a36Sopenharmony_ci .numerator = 1000000, 37962306a36Sopenharmony_ci .denominator = 8060, 38062306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_INT_PLUS_MICRO, 38162306a36Sopenharmony_ci .schan_val = -10, 38262306a36Sopenharmony_ci .schan_val2 = 123456789, 38362306a36Sopenharmony_ci .expected = "-16557.914267", 38462306a36Sopenharmony_ci }, 38562306a36Sopenharmony_ci /* 38662306a36Sopenharmony_ci * 32-bit overflow conditions 38762306a36Sopenharmony_ci */ 38862306a36Sopenharmony_ci { 38962306a36Sopenharmony_ci .name = "overflow IIO_VAL_FRACTIONAL, positive", 39062306a36Sopenharmony_ci .numerator = 2, 39162306a36Sopenharmony_ci .denominator = 20, 39262306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_FRACTIONAL, 39362306a36Sopenharmony_ci .schan_val = S32_MAX, 39462306a36Sopenharmony_ci .schan_val2 = 1, 39562306a36Sopenharmony_ci .expected = "214748364.7", 39662306a36Sopenharmony_ci }, 39762306a36Sopenharmony_ci { 39862306a36Sopenharmony_ci .name = "overflow IIO_VAL_FRACTIONAL, negative", 39962306a36Sopenharmony_ci .numerator = -2, 40062306a36Sopenharmony_ci .denominator = 20, 40162306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_FRACTIONAL, 40262306a36Sopenharmony_ci .schan_val = S32_MAX, 40362306a36Sopenharmony_ci .schan_val2 = 1, 40462306a36Sopenharmony_ci .expected = "-214748364.7", 40562306a36Sopenharmony_ci }, 40662306a36Sopenharmony_ci { 40762306a36Sopenharmony_ci .name = "overflow IIO_VAL_FRACTIONAL_LOG2, positive", 40862306a36Sopenharmony_ci .numerator = S32_MAX, 40962306a36Sopenharmony_ci .denominator = 4096, 41062306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_FRACTIONAL_LOG2, 41162306a36Sopenharmony_ci .schan_val = 4096, 41262306a36Sopenharmony_ci .schan_val2 = 16, 41362306a36Sopenharmony_ci .expected = "32767.99998474121", 41462306a36Sopenharmony_ci }, 41562306a36Sopenharmony_ci { 41662306a36Sopenharmony_ci .name = "overflow IIO_VAL_FRACTIONAL_LOG2, negative", 41762306a36Sopenharmony_ci .numerator = S32_MAX, 41862306a36Sopenharmony_ci .denominator = 4096, 41962306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_FRACTIONAL_LOG2, 42062306a36Sopenharmony_ci .schan_val = -4096, 42162306a36Sopenharmony_ci .schan_val2 = 16, 42262306a36Sopenharmony_ci .expected = "-32767.99998474121", 42362306a36Sopenharmony_ci }, 42462306a36Sopenharmony_ci { 42562306a36Sopenharmony_ci .name = "overflow IIO_VAL_INT_PLUS_NANO, positive", 42662306a36Sopenharmony_ci .numerator = 2, 42762306a36Sopenharmony_ci .denominator = 20, 42862306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_INT_PLUS_NANO, 42962306a36Sopenharmony_ci .schan_val = 10, 43062306a36Sopenharmony_ci .schan_val2 = S32_MAX, 43162306a36Sopenharmony_ci .expected = "1.214748364", 43262306a36Sopenharmony_ci }, 43362306a36Sopenharmony_ci { 43462306a36Sopenharmony_ci .name = "overflow IIO_VAL_INT_PLUS_NANO, negative", 43562306a36Sopenharmony_ci .numerator = -2, 43662306a36Sopenharmony_ci .denominator = 20, 43762306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_INT_PLUS_NANO, 43862306a36Sopenharmony_ci .schan_val = 10, 43962306a36Sopenharmony_ci .schan_val2 = S32_MAX, 44062306a36Sopenharmony_ci .expected = "-1.214748364", 44162306a36Sopenharmony_ci }, 44262306a36Sopenharmony_ci { 44362306a36Sopenharmony_ci .name = "overflow IIO_VAL_INT_PLUS_NANO, negative schan", 44462306a36Sopenharmony_ci .numerator = 2, 44562306a36Sopenharmony_ci .denominator = 20, 44662306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_INT_PLUS_NANO, 44762306a36Sopenharmony_ci .schan_val = -10, 44862306a36Sopenharmony_ci .schan_val2 = S32_MAX, 44962306a36Sopenharmony_ci .expected = "-1.214748364", 45062306a36Sopenharmony_ci }, 45162306a36Sopenharmony_ci { 45262306a36Sopenharmony_ci .name = "overflow IIO_VAL_INT_PLUS_MICRO, positive", 45362306a36Sopenharmony_ci .numerator = 2, 45462306a36Sopenharmony_ci .denominator = 20, 45562306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_INT_PLUS_MICRO, 45662306a36Sopenharmony_ci .schan_val = 10, 45762306a36Sopenharmony_ci .schan_val2 = S32_MAX, 45862306a36Sopenharmony_ci .expected = "215.748364", 45962306a36Sopenharmony_ci }, 46062306a36Sopenharmony_ci { 46162306a36Sopenharmony_ci .name = "overflow IIO_VAL_INT_PLUS_MICRO, negative", 46262306a36Sopenharmony_ci .numerator = -2, 46362306a36Sopenharmony_ci .denominator = 20, 46462306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_INT_PLUS_MICRO, 46562306a36Sopenharmony_ci .schan_val = 10, 46662306a36Sopenharmony_ci .schan_val2 = S32_MAX, 46762306a36Sopenharmony_ci .expected = "-215.748364", 46862306a36Sopenharmony_ci }, 46962306a36Sopenharmony_ci { 47062306a36Sopenharmony_ci .name = "overflow IIO_VAL_INT_PLUS_MICRO, negative schan", 47162306a36Sopenharmony_ci .numerator = 2, 47262306a36Sopenharmony_ci .denominator = 20, 47362306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_INT_PLUS_MICRO, 47462306a36Sopenharmony_ci .schan_val = -10, 47562306a36Sopenharmony_ci .schan_val2 = S32_MAX, 47662306a36Sopenharmony_ci .expected = "-215.748364", 47762306a36Sopenharmony_ci }, 47862306a36Sopenharmony_ci}; 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_cistatic const struct rescale_tc_data offset_cases[] = { 48162306a36Sopenharmony_ci /* 48262306a36Sopenharmony_ci * Typical use cases 48362306a36Sopenharmony_ci */ 48462306a36Sopenharmony_ci { 48562306a36Sopenharmony_ci .name = "typical IIO_VAL_INT, positive", 48662306a36Sopenharmony_ci .offset = 1234, 48762306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_INT, 48862306a36Sopenharmony_ci .schan_val = 123, 48962306a36Sopenharmony_ci .schan_val2 = 0, 49062306a36Sopenharmony_ci .schan_off = 14, 49162306a36Sopenharmony_ci .expected_off = "24", /* 23.872 */ 49262306a36Sopenharmony_ci }, 49362306a36Sopenharmony_ci { 49462306a36Sopenharmony_ci .name = "typical IIO_VAL_INT, negative", 49562306a36Sopenharmony_ci .offset = -1234, 49662306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_INT, 49762306a36Sopenharmony_ci .schan_val = 12, 49862306a36Sopenharmony_ci .schan_val2 = 0, 49962306a36Sopenharmony_ci .schan_off = 14, 50062306a36Sopenharmony_ci .expected_off = "-88", /* -88.83333333333333 */ 50162306a36Sopenharmony_ci }, 50262306a36Sopenharmony_ci { 50362306a36Sopenharmony_ci .name = "typical IIO_VAL_FRACTIONAL, positive", 50462306a36Sopenharmony_ci .offset = 1234, 50562306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_FRACTIONAL, 50662306a36Sopenharmony_ci .schan_val = 12, 50762306a36Sopenharmony_ci .schan_val2 = 34, 50862306a36Sopenharmony_ci .schan_off = 14, 50962306a36Sopenharmony_ci .expected_off = "3510", /* 3510.333333333333 */ 51062306a36Sopenharmony_ci }, 51162306a36Sopenharmony_ci { 51262306a36Sopenharmony_ci .name = "typical IIO_VAL_FRACTIONAL, negative", 51362306a36Sopenharmony_ci .offset = -1234, 51462306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_FRACTIONAL, 51562306a36Sopenharmony_ci .schan_val = 12, 51662306a36Sopenharmony_ci .schan_val2 = 34, 51762306a36Sopenharmony_ci .schan_off = 14, 51862306a36Sopenharmony_ci .expected_off = "-3482", /* -3482.333333333333 */ 51962306a36Sopenharmony_ci }, 52062306a36Sopenharmony_ci { 52162306a36Sopenharmony_ci .name = "typical IIO_VAL_FRACTIONAL_LOG2, positive", 52262306a36Sopenharmony_ci .offset = 1234, 52362306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_FRACTIONAL_LOG2, 52462306a36Sopenharmony_ci .schan_val = 12, 52562306a36Sopenharmony_ci .schan_val2 = 16, 52662306a36Sopenharmony_ci .schan_off = 14, 52762306a36Sopenharmony_ci .expected_off = "6739299", /* 6739299.333333333 */ 52862306a36Sopenharmony_ci }, 52962306a36Sopenharmony_ci { 53062306a36Sopenharmony_ci .name = "typical IIO_VAL_FRACTIONAL_LOG2, negative", 53162306a36Sopenharmony_ci .offset = -1234, 53262306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_FRACTIONAL_LOG2, 53362306a36Sopenharmony_ci .schan_val = 12, 53462306a36Sopenharmony_ci .schan_val2 = 16, 53562306a36Sopenharmony_ci .schan_off = 14, 53662306a36Sopenharmony_ci .expected_off = "-6739271", /* -6739271.333333333 */ 53762306a36Sopenharmony_ci }, 53862306a36Sopenharmony_ci { 53962306a36Sopenharmony_ci .name = "typical IIO_VAL_INT_PLUS_NANO, positive", 54062306a36Sopenharmony_ci .offset = 1234, 54162306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_INT_PLUS_NANO, 54262306a36Sopenharmony_ci .schan_val = 10, 54362306a36Sopenharmony_ci .schan_val2 = 123456789, 54462306a36Sopenharmony_ci .schan_off = 14, 54562306a36Sopenharmony_ci .expected_off = "135", /* 135.8951219647469 */ 54662306a36Sopenharmony_ci }, 54762306a36Sopenharmony_ci { 54862306a36Sopenharmony_ci .name = "typical IIO_VAL_INT_PLUS_NANO, negative", 54962306a36Sopenharmony_ci .offset = -1234, 55062306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_INT_PLUS_NANO, 55162306a36Sopenharmony_ci .schan_val = 10, 55262306a36Sopenharmony_ci .schan_val2 = 123456789, 55362306a36Sopenharmony_ci .schan_off = 14, 55462306a36Sopenharmony_ci .expected_off = "-107", /* -107.89512196474689 */ 55562306a36Sopenharmony_ci }, 55662306a36Sopenharmony_ci { 55762306a36Sopenharmony_ci .name = "typical IIO_VAL_INT_PLUS_MICRO, positive", 55862306a36Sopenharmony_ci .offset = 1234, 55962306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_INT_PLUS_MICRO, 56062306a36Sopenharmony_ci .schan_val = 10, 56162306a36Sopenharmony_ci .schan_val2 = 123456789, 56262306a36Sopenharmony_ci .schan_off = 14, 56362306a36Sopenharmony_ci .expected_off = "23", /* 23.246438560723952 */ 56462306a36Sopenharmony_ci }, 56562306a36Sopenharmony_ci { 56662306a36Sopenharmony_ci .name = "typical IIO_VAL_INT_PLUS_MICRO, negative", 56762306a36Sopenharmony_ci .offset = -12345, 56862306a36Sopenharmony_ci .schan_scale_type = IIO_VAL_INT_PLUS_MICRO, 56962306a36Sopenharmony_ci .schan_val = 10, 57062306a36Sopenharmony_ci .schan_val2 = 123456789, 57162306a36Sopenharmony_ci .schan_off = 14, 57262306a36Sopenharmony_ci .expected_off = "-78", /* -78.50185091745313 */ 57362306a36Sopenharmony_ci }, 57462306a36Sopenharmony_ci}; 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_cistatic void case_to_desc(const struct rescale_tc_data *t, char *desc) 57762306a36Sopenharmony_ci{ 57862306a36Sopenharmony_ci strcpy(desc, t->name); 57962306a36Sopenharmony_ci} 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_ciKUNIT_ARRAY_PARAM(iio_rescale_scale, scale_cases, case_to_desc); 58262306a36Sopenharmony_ciKUNIT_ARRAY_PARAM(iio_rescale_offset, offset_cases, case_to_desc); 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ci/** 58562306a36Sopenharmony_ci * iio_str_to_nano() - Parse a fixed-point string to get an 58662306a36Sopenharmony_ci * IIO_VAL_INT_PLUS_NANO value 58762306a36Sopenharmony_ci * @str: The string to parse 58862306a36Sopenharmony_ci * @nano: The number as an integer 58962306a36Sopenharmony_ci * 59062306a36Sopenharmony_ci * Returns 0 on success, or a negative error code if the string cound not be 59162306a36Sopenharmony_ci * parsed. 59262306a36Sopenharmony_ci */ 59362306a36Sopenharmony_cistatic int iio_str_to_nano(const char *str, s64 *nano) 59462306a36Sopenharmony_ci{ 59562306a36Sopenharmony_ci int tmp, tmp2; 59662306a36Sopenharmony_ci int ret = 0; 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci /* 59962306a36Sopenharmony_ci * iio_str_to_fixpoint() uses 10^8 here instead of 10^9 as fract_mult is 60062306a36Sopenharmony_ci * the multiplier for the first decimal place. 60162306a36Sopenharmony_ci */ 60262306a36Sopenharmony_ci ret = iio_str_to_fixpoint(str, 100000000, &tmp, &tmp2); 60362306a36Sopenharmony_ci if (ret < 0) 60462306a36Sopenharmony_ci return ret; 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_ci if (tmp < 0) 60762306a36Sopenharmony_ci tmp2 *= -1; 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_ci *nano = (s64)tmp * 1000000000UL + tmp2; 61062306a36Sopenharmony_ci 61162306a36Sopenharmony_ci return ret; 61262306a36Sopenharmony_ci} 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci/** 61562306a36Sopenharmony_ci * iio_test_relative_error_ppm() - Compute relative error (in parts-per-million) 61662306a36Sopenharmony_ci * between two fixed-point strings 61762306a36Sopenharmony_ci * @real_str: The real value as a string 61862306a36Sopenharmony_ci * @exp_str: The expected value as a string 61962306a36Sopenharmony_ci * 62062306a36Sopenharmony_ci * Returns a negative error code if the strings cound not be parsed, or the 62162306a36Sopenharmony_ci * relative error in parts-per-million. 62262306a36Sopenharmony_ci */ 62362306a36Sopenharmony_cistatic int iio_test_relative_error_ppm(const char *real_str, const char *exp_str) 62462306a36Sopenharmony_ci{ 62562306a36Sopenharmony_ci s64 real, exp, err; 62662306a36Sopenharmony_ci int ret; 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_ci ret = iio_str_to_nano(real_str, &real); 62962306a36Sopenharmony_ci if (ret < 0) 63062306a36Sopenharmony_ci return ret; 63162306a36Sopenharmony_ci 63262306a36Sopenharmony_ci ret = iio_str_to_nano(exp_str, &exp); 63362306a36Sopenharmony_ci if (ret < 0) 63462306a36Sopenharmony_ci return ret; 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ci if (!exp) { 63762306a36Sopenharmony_ci pr_err("Expected value is null, relative error is undefined\n"); 63862306a36Sopenharmony_ci return -EINVAL; 63962306a36Sopenharmony_ci } 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_ci err = 1000000UL * abs(exp - real); 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci return (int)div64_u64(err, abs(exp)); 64462306a36Sopenharmony_ci} 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_cistatic void iio_rescale_test_scale(struct kunit *test) 64762306a36Sopenharmony_ci{ 64862306a36Sopenharmony_ci struct rescale_tc_data *t = (struct rescale_tc_data *)test->param_value; 64962306a36Sopenharmony_ci char *buff = kunit_kmalloc(test, PAGE_SIZE, GFP_KERNEL); 65062306a36Sopenharmony_ci struct rescale rescale; 65162306a36Sopenharmony_ci int values[2]; 65262306a36Sopenharmony_ci int rel_ppm; 65362306a36Sopenharmony_ci int ret; 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_ci rescale.numerator = t->numerator; 65662306a36Sopenharmony_ci rescale.denominator = t->denominator; 65762306a36Sopenharmony_ci rescale.offset = t->offset; 65862306a36Sopenharmony_ci values[0] = t->schan_val; 65962306a36Sopenharmony_ci values[1] = t->schan_val2; 66062306a36Sopenharmony_ci 66162306a36Sopenharmony_ci ret = rescale_process_scale(&rescale, t->schan_scale_type, 66262306a36Sopenharmony_ci &values[0], &values[1]); 66362306a36Sopenharmony_ci 66462306a36Sopenharmony_ci ret = iio_format_value(buff, ret, 2, values); 66562306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, (int)strlen(buff), ret); 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_ci rel_ppm = iio_test_relative_error_ppm(buff, t->expected); 66862306a36Sopenharmony_ci KUNIT_EXPECT_GE_MSG(test, rel_ppm, 0, "failed to compute ppm\n"); 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_ci KUNIT_EXPECT_EQ_MSG(test, rel_ppm, 0, 67162306a36Sopenharmony_ci "\t real=%s" 67262306a36Sopenharmony_ci "\texpected=%s\n", 67362306a36Sopenharmony_ci buff, t->expected); 67462306a36Sopenharmony_ci} 67562306a36Sopenharmony_ci 67662306a36Sopenharmony_cistatic void iio_rescale_test_offset(struct kunit *test) 67762306a36Sopenharmony_ci{ 67862306a36Sopenharmony_ci struct rescale_tc_data *t = (struct rescale_tc_data *)test->param_value; 67962306a36Sopenharmony_ci char *buff_off = kunit_kmalloc(test, PAGE_SIZE, GFP_KERNEL); 68062306a36Sopenharmony_ci struct rescale rescale; 68162306a36Sopenharmony_ci int values[2]; 68262306a36Sopenharmony_ci int ret; 68362306a36Sopenharmony_ci 68462306a36Sopenharmony_ci rescale.numerator = t->numerator; 68562306a36Sopenharmony_ci rescale.denominator = t->denominator; 68662306a36Sopenharmony_ci rescale.offset = t->offset; 68762306a36Sopenharmony_ci values[0] = t->schan_val; 68862306a36Sopenharmony_ci values[1] = t->schan_val2; 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_ci ret = rescale_process_offset(&rescale, t->schan_scale_type, 69162306a36Sopenharmony_ci t->schan_val, t->schan_val2, t->schan_off, 69262306a36Sopenharmony_ci &values[0], &values[1]); 69362306a36Sopenharmony_ci 69462306a36Sopenharmony_ci ret = iio_format_value(buff_off, ret, 2, values); 69562306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, (int)strlen(buff_off), ret); 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_ci KUNIT_EXPECT_STREQ(test, strim(buff_off), t->expected_off); 69862306a36Sopenharmony_ci} 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_cistatic struct kunit_case iio_rescale_test_cases[] = { 70162306a36Sopenharmony_ci KUNIT_CASE_PARAM(iio_rescale_test_scale, iio_rescale_scale_gen_params), 70262306a36Sopenharmony_ci KUNIT_CASE_PARAM(iio_rescale_test_offset, iio_rescale_offset_gen_params), 70362306a36Sopenharmony_ci {} 70462306a36Sopenharmony_ci}; 70562306a36Sopenharmony_ci 70662306a36Sopenharmony_cistatic struct kunit_suite iio_rescale_test_suite = { 70762306a36Sopenharmony_ci .name = "iio-rescale", 70862306a36Sopenharmony_ci .test_cases = iio_rescale_test_cases, 70962306a36Sopenharmony_ci}; 71062306a36Sopenharmony_cikunit_test_suite(iio_rescale_test_suite); 71162306a36Sopenharmony_ci 71262306a36Sopenharmony_ciMODULE_AUTHOR("Liam Beguin <liambeguin@gmail.com>"); 71362306a36Sopenharmony_ciMODULE_DESCRIPTION("Test IIO rescale conversion functions"); 71462306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 71562306a36Sopenharmony_ciMODULE_IMPORT_NS(IIO_RESCALE); 716