Skip to content

Commit 6801690

Browse files
committed
Add fixed-point type "fixedp" into calc
The new type of fixed-point support directly add/sub and multiply/devide with shifting to correct the value To use the new fixed-point, the base type of expression is now be modified from "int" to "uint64_t"
1 parent b61fdc5 commit 6801690

File tree

5 files changed

+91
-116
lines changed

5 files changed

+91
-116
lines changed

expression.c

+66-108
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "expression.h"
2+
#include "fixed-point.h"
23

34
#include <linux/ctype.h> /* for isspace */
45
#include <linux/kernel.h>
@@ -172,28 +173,52 @@ static enum expr_type expr_op(const char *s, size_t len, int unary)
172173
return OP_UNKNOWN;
173174
}
174175

175-
static int expr_parse_number(const char *s, size_t len)
176+
static uint64_t expr_parse_number(const char *s, size_t len)
176177
{
177-
int num = 0;
178+
fixedp num = {0};
178179
int frac = 0;
179180
int dot = 0; /* FIXME: not good enough */
180181
unsigned int digits = 0;
181182
for (unsigned int i = 0; i < len; i++) {
182183
if (s[i] == '.' && dot == 0) {
183-
dot = 1;
184+
dot = i + 1;
184185
continue;
185186
}
186187
if (isdigit(s[i])) {
187-
digits++;
188188
if (dot)
189-
--frac;
190-
num = num * 10 + (s[i] - '0');
189+
frac++;
190+
else
191+
digits++;
192+
// num = num * 10 + (s[i] - '0');
191193
} else
192194
return NAN_INT;
193195
}
194196

195-
num = FP2INT(num, frac);
196-
return (digits > 0 ? num : NAN_INT);
197+
static int pow10[] = {
198+
1, 10, 100, 1000, 10000,
199+
100000, 1000000, 10000000, 100000000, 1000000000,
200+
};
201+
202+
if (dot) {
203+
uint32_t ipt = 0, tmp;
204+
uint32_t mask = pow10[frac];
205+
int i = 31;
206+
sscanf(s, "%u.%u", &tmp, &ipt);
207+
pr_alert("parse integer: %u", ipt);
208+
while (ipt && i) {
209+
ipt <<= 1;
210+
if (ipt >= mask) {
211+
num.frac |= 1 << i;
212+
ipt %= mask;
213+
}
214+
i--;
215+
}
216+
}
217+
218+
if (digits)
219+
sscanf(s, "%u", &num.inte);
220+
221+
return (digits > 0 ? num.data : NAN_INT);
197222
}
198223

199224
/*
@@ -233,36 +258,19 @@ struct expr_var *expr_var(struct expr_var_list *vars, const char *s, size_t len)
233258
return v;
234259
}
235260

236-
static int mult(int a, int b)
261+
static uint64_t mult(uint64_t a, uint64_t b)
237262
{
238-
int frac1 = GET_FRAC(a);
239-
int frac2 = GET_FRAC(b);
240-
int n1 = GET_NUM(a);
241-
int n2 = GET_NUM(b);
242-
int n3 = n1 * n2;
243-
244-
return FP2INT(n3, (frac1 + frac2));
263+
/* (a + b) * (c + d) = ac + ad + bc + bd */
264+
fixedp result = {0};
265+
fixedp fa = {.data = a}, fb = {.data = b};
266+
result.data = a * b;
267+
result.inte = fa.inte * fb.inte;
268+
return result.data;
245269
}
246270

247-
static int divid(int a, int b)
271+
static int divid(uint64_t a, uint64_t b)
248272
{
249-
int frac1 = GET_FRAC(a);
250-
int frac2 = GET_FRAC(b);
251-
int n1 = GET_NUM(a);
252-
int n2 = GET_NUM(b);
253-
if (n1 == 0 && n2 == 0)
254-
return NAN_INT;
255-
if (n2 == 0)
256-
return INF_INT;
257-
258-
while (n1 * 10 < ((1 << 25) - 1)) {
259-
--frac1;
260-
n1 *= 10;
261-
}
262-
int n3 = n1 / n2;
263-
int frac3 = frac1 - frac2;
264-
265-
return FP2INT(n3, frac3);
273+
return (a << 32) / (b << 32);
266274
}
267275

268276
static int remain(int a, int b)
@@ -289,10 +297,10 @@ static int remain(int a, int b)
289297
return FP2INT(n1, frac1);
290298
}
291299

292-
static int right_shift(int a, int b)
300+
static uint64_t right_shift(uint64_t a, int b)
293301
{
294302
/* FIXME: should use 2-base? */
295-
return divid(a, mult(2 << 4, b));
303+
return a >> b;
296304
}
297305

298306
static int power(int a, int b)
@@ -322,77 +330,30 @@ static int power(int a, int b)
322330
return FP2INT(n1, frac1);
323331
}
324332

325-
static int left_shift(int a, int b)
333+
static uint64_t left_shift(uint64_t a, int b)
326334
{
327335
/* FIXME: should use 2-base? */
328-
return mult(a, power(2 << 4, b));
336+
return a << b;
329337
}
330338

331-
static int plus(int a, int b)
339+
static uint64_t plus(uint64_t a, uint64_t b)
332340
{
333-
int frac1 = GET_FRAC(a);
334-
int frac2 = GET_FRAC(b);
335-
int n1 = GET_NUM(a);
336-
int n2 = GET_NUM(b);
337-
338-
while (frac1 != frac2) {
339-
if (frac1 > frac2) {
340-
--frac1;
341-
n1 *= 10;
342-
} else if (frac1 < frac2) {
343-
--frac2;
344-
n2 *= 10;
345-
}
346-
}
347-
348-
n1 += n2;
349-
350-
return FP2INT(n1, frac1);
341+
return a + b;
351342
}
352343

353-
static int minus(int a, int b)
344+
static uint64_t minus(uint64_t a, uint64_t b)
354345
{
355-
int frac1 = GET_FRAC(a);
356-
int frac2 = GET_FRAC(b);
357-
int n1 = GET_NUM(a);
358-
int n2 = GET_NUM(b);
359-
360-
while (frac1 != frac2) {
361-
if (frac1 > frac2) {
362-
--frac1;
363-
n1 *= 10;
364-
} else {
365-
--frac2;
366-
n2 *= 10;
367-
}
368-
}
369-
370-
n1 -= n2;
371-
return FP2INT(n1, frac1);
346+
return a - b;
372347
}
373348

374-
static int compare(int a, int b)
349+
static int compare(uint64_t a, uint64_t b)
375350
{
376-
int frac1 = GET_FRAC(a);
377-
int frac2 = GET_FRAC(b);
378-
int n1 = GET_NUM(a);
379-
int n2 = GET_NUM(b);
380-
while (frac1 != frac2) {
381-
if (frac1 > frac2) {
382-
--frac1;
383-
n1 *= 10;
384-
} else {
385-
--frac2;
386-
n2 *= 10;
387-
}
388-
}
389-
390351
int flags = 0;
391-
if (n1 < n2)
352+
if (a < b)
392353
flags |= LOWER;
393-
if (n1 > n2)
354+
if (a > b)
394355
flags |= GREATER;
395-
if (n1 == n2)
356+
if (a == b)
396357
flags |= EQUAL;
397358

398359
return flags;
@@ -443,21 +404,18 @@ static int bitwise_op(int a, int b, int op)
443404
return FP2INT(n1, frac1);
444405
}
445406

446-
static int not(int a)
407+
static uint64_t not(uint64_t a)
447408
{
448-
int frac = GET_FRAC(a);
449-
int n = GET_NUM(a);
450-
451-
return FP2INT(!n, frac);
409+
return !a;
452410
}
453411

454412
/* TODO: change logic */
455-
int expr_eval(struct expr *e)
413+
uint64_t expr_eval(struct expr *e)
456414
{
457415
int n;
458416
switch (e->type) {
459417
case OP_UNARY_MINUS: /* OK */
460-
return minus(FP2INT(0, 0), expr_eval(&e->param.op.args.buf[0]));
418+
return minus(0, expr_eval(&e->param.op.args.buf[0]));
461419
case OP_UNARY_LOGICAL_NOT: /* OK */
462420
return not(expr_eval(&e->param.op.args.buf[0]));
463421
case OP_UNARY_BITWISE_NOT: /* OK */
@@ -511,14 +469,14 @@ int expr_eval(struct expr *e)
511469
expr_eval(&e->param.op.args.buf[1])) &
512470
(EQUAL)));
513471
case OP_BITWISE_AND: /* OK */
514-
return (bitwise_op(expr_eval(&e->param.op.args.buf[0]),
515-
expr_eval(&e->param.op.args.buf[1]), 0));
472+
return expr_eval(&e->param.op.args.buf[0]) &
473+
expr_eval(&e->param.op.args.buf[1]);
516474
case OP_BITWISE_OR: /* OK */
517-
return MASK(bitwise_op(expr_eval(&e->param.op.args.buf[0]),
518-
expr_eval(&e->param.op.args.buf[1]), 1));
475+
return expr_eval(&e->param.op.args.buf[0]) |
476+
expr_eval(&e->param.op.args.buf[1]);
519477
case OP_BITWISE_XOR: /* OK */
520-
return (bitwise_op(expr_eval(&e->param.op.args.buf[0]),
521-
expr_eval(&e->param.op.args.buf[1]), 2));
478+
return expr_eval(&e->param.op.args.buf[0]) ^
479+
expr_eval(&e->param.op.args.buf[1]);
522480
case OP_LOGICAL_AND: /* OK */
523481
n = expr_eval(&e->param.op.args.buf[0]);
524482
if (GET_NUM(n) != 0) {
@@ -668,7 +626,7 @@ static int expr_bind(const char *s, size_t len, vec_expr_t *es)
668626
return 0;
669627
}
670628

671-
static struct expr expr_const(int value)
629+
static struct expr expr_const(uint64_t value)
672630
{
673631
struct expr e = expr_init();
674632
e.type = OP_CONST;
@@ -731,7 +689,7 @@ struct expr *expr_create(const char *s,
731689
struct expr_var_list *vars,
732690
struct expr_func *funcs)
733691
{
734-
int num;
692+
uint64_t num;
735693
struct expr_var *v;
736694
const char *id = NULL;
737695
size_t idn = 0;

expression.h

+4-4
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,10 @@ struct expr {
7575
int type;
7676
union {
7777
struct {
78-
int value;
78+
uint64_t value;
7979
} num;
8080
struct {
81-
int *value;
81+
uint64_t *value;
8282
} var;
8383
struct {
8484
vec_expr_t args;
@@ -120,7 +120,7 @@ struct expr_func *expr_func(struct expr_func *funcs, const char *s, size_t len);
120120
* Variables
121121
*/
122122
struct expr_var {
123-
int value;
123+
uint64_t value;
124124
struct expr_var *next;
125125
char name[];
126126
};
@@ -133,7 +133,7 @@ struct expr_var *expr_var(struct expr_var_list *vars,
133133
const char *s,
134134
size_t len);
135135

136-
int expr_eval(struct expr *e);
136+
uint64_t expr_eval(struct expr *e);
137137

138138
#define EXPR_TOP (1 << 0)
139139
#define EXPR_TOPEN (1 << 1)

fixed-point.h

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#ifndef FIXED_POINT_H
2+
3+
#ifdef __KERNEL__
4+
#include <linux/types.h>
5+
#endif
6+
7+
typedef union __fixedp {
8+
struct {
9+
uint32_t frac;
10+
uint32_t inte;
11+
};
12+
uint64_t data;
13+
} fixedp;
14+
15+
#endif /* FIXED_POINT_H */

main.c

+4-4
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ static short size_of_message;
2626
static struct class *char_class = NULL;
2727
static struct device *char_dev = NULL;
2828
static char *msg_ptr = NULL;
29-
static int result = 0;
29+
static uint64_t result = 0;
3030

3131
/* The prototype functions for the character driver */
3232
static int dev_open(struct inode *, struct file *);
@@ -61,12 +61,12 @@ static ssize_t dev_read(struct file *filep,
6161

6262
memset(message, 0, sizeof(char) * BUFF_SIZE);
6363

64-
snprintf(message, 64, "%d\n", result);
64+
snprintf(message, 64, "%lu\n", result);
6565
size_of_message = strlen(message);
6666

6767
error_count = copy_to_user(buffer, message, size_of_message);
6868
if (error_count == 0) {
69-
pr_info("size: %d result: %d\n", size_of_message, result);
69+
pr_info("size: %d result: %llu\n", size_of_message, result);
7070
while (len && *msg_ptr) {
7171
error_count = put_user(*(msg_ptr++), buffer++);
7272
len--;
@@ -143,7 +143,7 @@ static void calc(void)
143143
}
144144

145145
result = expr_eval(e);
146-
pr_info("Result: %d\n", result);
146+
pr_info("Result: %llu\n", result);
147147
expr_destroy(e, &vars);
148148
}
149149

scripts/aspell-pws

+2
Original file line numberDiff line numberDiff line change
@@ -163,3 +163,5 @@ expr
163163
fibonacci
164164
kcalc
165165
noinline
166+
fixedp
167+
calc

0 commit comments

Comments
 (0)