OLD | NEW |
---|---|
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include <math.h> | 5 #include <math.h> |
6 | 6 |
7 #include "vm/bootstrap_natives.h" | 7 #include "vm/bootstrap_natives.h" |
8 | 8 |
9 #include "vm/bigint_operations.h" | 9 #include "vm/bigint_operations.h" |
10 #include "vm/double_conversion.h" | 10 #include "vm/double_conversion.h" |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
72 } | 72 } |
73 | 73 |
74 | 74 |
75 DEFINE_NATIVE_ENTRY(Double_trunc_div, 2) { | 75 DEFINE_NATIVE_ENTRY(Double_trunc_div, 2) { |
76 double left = Double::CheckedHandle(arguments->NativeArgAt(0)).value(); | 76 double left = Double::CheckedHandle(arguments->NativeArgAt(0)).value(); |
77 GET_NON_NULL_NATIVE_ARGUMENT(Double, right_object, arguments->NativeArgAt(1)); | 77 GET_NON_NULL_NATIVE_ARGUMENT(Double, right_object, arguments->NativeArgAt(1)); |
78 double right = right_object.value(); | 78 double right = right_object.value(); |
79 if (FLAG_trace_intrinsified_natives) { | 79 if (FLAG_trace_intrinsified_natives) { |
80 OS::Print("Double_trunc_div %f ~/ %f\n", left, right); | 80 OS::Print("Double_trunc_div %f ~/ %f\n", left, right); |
81 } | 81 } |
82 return Double::New(trunc(left / right)); | 82 double result = trunc(left / right); |
83 if (isinf(result) || isnan(result)) { | |
floitsch
2013/01/03 18:23:17
From here on same as 'toInt' on the left (except t
| |
84 const Array& args = Array::Handle(Array::New(1)); | |
85 args.SetAt(0, String::Handle(String::New( | |
86 "Result of truncating division is Infinity or NaN"))); | |
87 Exceptions::ThrowByType(Exceptions::kFormat, args); | |
Lasse Reichstein Nielsen
2013/01/04 10:29:42
Consider using UnsupportedError instead of FormatE
| |
88 } | |
89 if ((Smi::kMinValue <= result) && (result <= Smi::kMaxValue)) { | |
90 return Smi::New(static_cast<intptr_t>(result)); | |
91 } else if ((Mint::kMinValue <= result) && (result <= Mint::kMaxValue)) { | |
92 return Mint::New(static_cast<int64_t>(result)); | |
93 } else { | |
94 return BigintOperations::NewFromDouble(result); | |
95 } | |
83 } | 96 } |
84 | 97 |
85 | 98 |
86 DEFINE_NATIVE_ENTRY(Double_modulo, 2) { | 99 DEFINE_NATIVE_ENTRY(Double_modulo, 2) { |
87 double left = Double::CheckedHandle(arguments->NativeArgAt(0)).value(); | 100 double left = Double::CheckedHandle(arguments->NativeArgAt(0)).value(); |
88 GET_NON_NULL_NATIVE_ARGUMENT(Double, right_object, arguments->NativeArgAt(1)); | 101 GET_NON_NULL_NATIVE_ARGUMENT(Double, right_object, arguments->NativeArgAt(1)); |
89 double right = right_object.value(); | 102 double right = right_object.value(); |
90 | 103 |
91 double remainder = fmod_ieee(left, right); | 104 double remainder = fmod_ieee(left, right); |
92 if (remainder == 0.0) { | 105 if (remainder == 0.0) { |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
144 | 157 |
145 DEFINE_NATIVE_ENTRY(Double_equalToInteger, 2) { | 158 DEFINE_NATIVE_ENTRY(Double_equalToInteger, 2) { |
146 const Double& left = Double::CheckedHandle(arguments->NativeArgAt(0)); | 159 const Double& left = Double::CheckedHandle(arguments->NativeArgAt(0)); |
147 GET_NON_NULL_NATIVE_ARGUMENT(Integer, right, arguments->NativeArgAt(1)); | 160 GET_NON_NULL_NATIVE_ARGUMENT(Integer, right, arguments->NativeArgAt(1)); |
148 return Bool::Get(left.value() == right.AsDoubleValue()); | 161 return Bool::Get(left.value() == right.AsDoubleValue()); |
149 } | 162 } |
150 | 163 |
151 | 164 |
152 DEFINE_NATIVE_ENTRY(Double_round, 1) { | 165 DEFINE_NATIVE_ENTRY(Double_round, 1) { |
153 const Double& arg = Double::CheckedHandle(arguments->NativeArgAt(0)); | 166 const Double& arg = Double::CheckedHandle(arguments->NativeArgAt(0)); |
154 return Double::New(round(arg.value())); | 167 if (isinf(arg.value()) || isnan(arg.value())) { |
floitsch
2013/01/03 18:23:17
same as "toInt" on the left. Only change: error-me
Lasse Reichstein Nielsen
2013/01/04 10:29:42
Repeated code should be abstracted into a helper m
| |
168 const Array& args = Array::Handle(Array::New(1)); | |
169 args.SetAt(0, String::Handle(String::New("Infinity or NaN round"))); | |
170 Exceptions::ThrowByType(Exceptions::kFormat, args); | |
171 } | |
172 double result = round(arg.value()); | |
173 if ((Smi::kMinValue <= result) && (result <= Smi::kMaxValue)) { | |
174 return Smi::New(static_cast<intptr_t>(result)); | |
175 } else if ((Mint::kMinValue <= result) && (result <= Mint::kMaxValue)) { | |
176 return Mint::New(static_cast<int64_t>(result)); | |
177 } else { | |
178 return BigintOperations::NewFromDouble(result); | |
179 } | |
155 } | 180 } |
156 | 181 |
157 DEFINE_NATIVE_ENTRY(Double_floor, 1) { | 182 DEFINE_NATIVE_ENTRY(Double_floor, 1) { |
158 const Double& arg = Double::CheckedHandle(arguments->NativeArgAt(0)); | 183 const Double& arg = Double::CheckedHandle(arguments->NativeArgAt(0)); |
159 return Double::New(floor(arg.value())); | 184 if (isinf(arg.value()) || isnan(arg.value())) { |
185 const Array& args = Array::Handle(Array::New(1)); | |
186 args.SetAt(0, String::Handle(String::New("Infinity or NaN floor"))); | |
187 Exceptions::ThrowByType(Exceptions::kFormat, args); | |
188 } | |
189 double result = floor(arg.value()); | |
190 if ((Smi::kMinValue <= result) && (result <= Smi::kMaxValue)) { | |
191 return Smi::New(static_cast<intptr_t>(result)); | |
192 } else if ((Mint::kMinValue <= result) && (result <= Mint::kMaxValue)) { | |
193 return Mint::New(static_cast<int64_t>(result)); | |
194 } else { | |
195 return BigintOperations::NewFromDouble(result); | |
196 } | |
160 } | 197 } |
161 | 198 |
162 DEFINE_NATIVE_ENTRY(Double_ceil, 1) { | 199 DEFINE_NATIVE_ENTRY(Double_ceil, 1) { |
163 const Double& arg = Double::CheckedHandle(arguments->NativeArgAt(0)); | 200 const Double& arg = Double::CheckedHandle(arguments->NativeArgAt(0)); |
164 return Double::New(ceil(arg.value())); | 201 if (isinf(arg.value()) || isnan(arg.value())) { |
202 const Array& args = Array::Handle(Array::New(1)); | |
203 args.SetAt(0, String::Handle(String::New("Infinity or NaN ceil"))); | |
204 Exceptions::ThrowByType(Exceptions::kFormat, args); | |
205 } | |
206 double result = ceil(arg.value()); | |
207 if ((Smi::kMinValue <= result) && (result <= Smi::kMaxValue)) { | |
208 return Smi::New(static_cast<intptr_t>(result)); | |
209 } else if ((Mint::kMinValue <= result) && (result <= Mint::kMaxValue)) { | |
210 return Mint::New(static_cast<int64_t>(result)); | |
211 } else { | |
212 return BigintOperations::NewFromDouble(result); | |
213 } | |
165 } | 214 } |
166 | 215 |
167 | 216 |
168 DEFINE_NATIVE_ENTRY(Double_truncate, 1) { | 217 DEFINE_NATIVE_ENTRY(Double_truncate, 1) { |
169 const Double& arg = Double::CheckedHandle(arguments->NativeArgAt(0)); | 218 const Double& arg = Double::CheckedHandle(arguments->NativeArgAt(0)); |
170 return Double::New(trunc(arg.value())); | 219 if (isinf(arg.value()) || isnan(arg.value())) { |
220 const Array& args = Array::Handle(Array::New(1)); | |
221 args.SetAt(0, String::Handle(String::New("Infinity or NaN truncate"))); | |
222 Exceptions::ThrowByType(Exceptions::kFormat, args); | |
223 } | |
224 double result = trunc(arg.value()); | |
225 if ((Smi::kMinValue <= result) && (result <= Smi::kMaxValue)) { | |
226 return Smi::New(static_cast<intptr_t>(result)); | |
227 } else if ((Mint::kMinValue <= result) && (result <= Mint::kMaxValue)) { | |
228 return Mint::New(static_cast<int64_t>(result)); | |
229 } else { | |
230 return BigintOperations::NewFromDouble(result); | |
231 } | |
171 } | 232 } |
172 | 233 |
173 | 234 |
174 DEFINE_NATIVE_ENTRY(Double_pow, 2) { | 235 DEFINE_NATIVE_ENTRY(Double_pow, 2) { |
175 const double operand = | 236 const double operand = |
176 Double::CheckedHandle(arguments->NativeArgAt(0)).value(); | 237 Double::CheckedHandle(arguments->NativeArgAt(0)).value(); |
177 GET_NON_NULL_NATIVE_ARGUMENT( | 238 GET_NON_NULL_NATIVE_ARGUMENT( |
178 Double, exponent_object, arguments->NativeArgAt(1)); | 239 Double, exponent_object, arguments->NativeArgAt(1)); |
179 const double exponent = exponent_object.value(); | 240 const double exponent = exponent_object.value(); |
180 return Double::New(pow(operand, exponent)); | 241 return Double::New(pow(operand, exponent)); |
181 } | 242 } |
182 | 243 |
183 | 244 |
184 #if defined(TARGET_OS_MACOS) | 245 #if defined(TARGET_OS_MACOS) |
185 // MAC OSX math library produces old style cast warning. | 246 // MAC OSX math library produces old style cast warning. |
186 #pragma GCC diagnostic ignored "-Wold-style-cast" | 247 #pragma GCC diagnostic ignored "-Wold-style-cast" |
187 #endif | 248 #endif |
188 | 249 |
189 DEFINE_NATIVE_ENTRY(Double_toInt, 1) { | |
190 const Double& arg = Double::CheckedHandle(arguments->NativeArgAt(0)); | |
191 if (isinf(arg.value()) || isnan(arg.value())) { | |
192 const Array& args = Array::Handle(Array::New(1)); | |
193 args.SetAt(0, String::Handle(String::New("Infinity or NaN toInt"))); | |
194 Exceptions::ThrowByType(Exceptions::kFormat, args); | |
195 } | |
196 double result = trunc(arg.value()); | |
197 if ((Smi::kMinValue <= result) && (result <= Smi::kMaxValue)) { | |
198 return Smi::New(static_cast<intptr_t>(result)); | |
199 } else if ((Mint::kMinValue <= result) && (result <= Mint::kMaxValue)) { | |
200 return Mint::New(static_cast<int64_t>(result)); | |
201 } else { | |
202 return BigintOperations::NewFromDouble(result); | |
203 } | |
204 } | |
205 | |
206 | |
207 DEFINE_NATIVE_ENTRY(Double_parse, 1) { | 250 DEFINE_NATIVE_ENTRY(Double_parse, 1) { |
208 GET_NON_NULL_NATIVE_ARGUMENT(String, value, arguments->NativeArgAt(0)); | 251 GET_NON_NULL_NATIVE_ARGUMENT(String, value, arguments->NativeArgAt(0)); |
209 const String& dummy_key = String::Handle(Symbols::Empty()); | 252 const String& dummy_key = String::Handle(Symbols::Empty()); |
210 Scanner scanner(value, dummy_key); | 253 Scanner scanner(value, dummy_key); |
211 const Scanner::GrowableTokenStream& tokens = scanner.GetStream(); | 254 const Scanner::GrowableTokenStream& tokens = scanner.GetStream(); |
212 String* number_string; | 255 String* number_string; |
213 bool is_positive; | 256 bool is_positive; |
214 if (Scanner::IsValidLiteral(tokens, | 257 if (Scanner::IsValidLiteral(tokens, |
215 Token::kDOUBLE, | 258 Token::kDOUBLE, |
216 &is_positive, | 259 &is_positive, |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
330 | 373 |
331 DEFINE_NATIVE_ENTRY(Double_getIsNegative, 1) { | 374 DEFINE_NATIVE_ENTRY(Double_getIsNegative, 1) { |
332 const Double& arg = Double::CheckedHandle(arguments->NativeArgAt(0)); | 375 const Double& arg = Double::CheckedHandle(arguments->NativeArgAt(0)); |
333 // Include negative zero, infinity. | 376 // Include negative zero, infinity. |
334 return Bool::Get(signbit(arg.value()) && !isnan(arg.value())); | 377 return Bool::Get(signbit(arg.value()) && !isnan(arg.value())); |
335 } | 378 } |
336 | 379 |
337 // Add here only functions using/referring to old-style casts. | 380 // Add here only functions using/referring to old-style casts. |
338 | 381 |
339 } // namespace dart | 382 } // namespace dart |
OLD | NEW |